OAuth and OIDC
OAuth 2.0
OAuth is an open web standard for authorization that is widely used around the world and is currently available in version 2.0
Explanation of terms
Third-party application: Third-party application, also known as “client” in this document.
HTTP Service: HTTP Service Provider, referred to as “Service Provider” in this document.
Resource Owner: The person who owns the resource, also known as the “user” in this document.
User Agent: User agent, in this article, means browser.
Authorization server: Authentication server, i.e., the server dedicated by the service provider to handle authentication.
Resource server: Resource server, i.e., the server where the service provider stores user-generated resources. It can be the same server as the authentication server, or a different server.
OAuth sets up an authorization layer between the “client” and the “service provider”. The “client” cannot log in directly to the “service provider”, but only to the authorization layer, thus distinguishing the user from the client. The token used by the “client” to log in to the authorization layer is different from the user’s password. The user can specify the scope of authority and validity of the authorization token at the time of login.
After the “client” logs in to the authorization layer, the “service provider” opens the user’s stored data to the “client” according to the scope and validity of the token.
Authorization Process
After the user opens the client, the client asks the user to give authorization.
The user agrees to give the client authorization.
The client uses the authorization obtained in the previous step to request a token from the authentication server.
After the authentication server authenticates the client, it confirms that there is no error and agrees to issue the token.
The client uses the token to request access to resources from the resource server.
The resource server confirms that the token is correct and agrees to open the resource to the client.
The key in these steps is how the client obtains authorization, OAuth 2.0 defines four different ways to obtain authorization.
Four ways to get authorization
OAuth 2.0 defines four types of authorization.
- Authorization code mode (authorization code)
- Simplification mode (implicit)
- 密码模式(resource owner password credentials)
- Client mode (client credentials)
Authorization code mode
(A) The user accesses the client, which directs the former to the authentication server.
(B) The user chooses whether to grant authorization to the client.
© Assuming that the user gives authorization, the authentication server directs the user to the redirection URI specified by the client in advance, along with an authorization code.
(D) The client receives the authorization code, attaches the earlier “redirect URI” and requests a token from the authentication server. This step is done on the server in the backend of the client and is not visible to the user.
(E) The authentication server verifies the authorization code and redirect URI, and then sends an access token and a refresh token to the client after confirming that there are no errors.
The URI of the client requesting authentication in step A, contains the following parameters:
- response_type: indicates the authorization type, mandatory, the value here is fixed to “code”
- client_id: the ID of the client, required
- redirect_uri: means redirect URI, optional
- scope: indicates the scope of the requested permission, optional
- state: indicates the current state of the client, you can specify any value, the authentication server will return this value unchanged.
In step C, the server responds to the client’s URI with the following parameters:
- code: indicates the authorization code, mandatory. The validity of this code should be very short, usually set to 10 minutes, the client can only use this code once, otherwise it will be rejected by the authorization server. The code is in one-to-one correspondence with the client ID and the redirect URI.
- state: If the client’s request contains this parameter, the authentication server’s response must also contain this parameter in exactly the same way.
In step D, the HTTP request for a token from the client to the authentication server contains the following parameters:
- grant_type: indicates the authorization mode used, mandatory, the value here is fixed to “authorization_code”.
- code: indicates the authorization code obtained in the previous step, mandatory.
- redirect_uri: indicates the redirect URI, mandatory, and must be consistent with the value of this parameter in step A.
- client_id: the client ID, mandatory.
The HTTP reply sent by the authentication server in step E, contains the following parameters:
- access_token: indicates the access token, mandatory.
- token_type: indicates the token type, the value is case-insensitive, mandatory, can be bearer type or mac type.
- expires_in: indicates the expiration time in seconds. If this parameter is omitted, the expiration time must be set in some other way.
- refresh_token: indicates the refresh token, which is used to get the next access token, optional.
- scope: indicates the scope of the permission, if the scope is the same as the client application, this item can be omitted.
Simplify mode
The simplicit grant type requests a token directly from the authentication server in the browser without going through the server of the third-party application, skipping the “authorization code” step, hence the name. All steps are done in the browser, the token is visible to the visitor, and the client does not need to authenticate.
(A) The client directs the user to the authentication server.
(B) The user decides whether to give authorization to the client.
© Assuming the user gives authorization, the authentication server directs the user to the “redirect URI” specified by the client and includes the access token in the hash portion of the URI.
(D) The browser sends a request to the resource server, which does not include the Hash value received in the previous step.
(E) The resource server returns a web page that contains code to get the token in the Hash value.
(F) The browser executes the script obtained in the previous step and extracts the token.
(G) The browser sends the token to the client.
password mode
In password mode (Resource Owner Password Credentials Grant), the user provides the client with his or her username and password. The client uses this information to request authorization from the “service provider”.
In this model, the user must give his password to the client, but the client must not store it. This is usually used in cases where the user has a high level of trust in the client, such as when the client is part of the operating system or produced by a reputable company. The authentication server should only consider using this mode if other authorization modes cannot be implemented.
(A) The user provides the user name and password to the client.
(B) The client sends the user name and password to the authentication server and requests a token from the latter.
© After the authentication server confirms that there is no error, it provides the access token to the client.
In step B, the client sends an HTTP request with the following parameters:
- grant_type: the authorization type, the value here is fixed to “password”, mandatory.
- username: user name, required.
- password: the password of the user, mandatory.
- scope: the scope of the permission, optional.
Client Mode
Client mode (Client Credentials Grant) means that the client authenticates to the “service provider” in its own name, rather than in the name of the user. Strictly speaking, the client mode is not part of the OAuth framework to solve the problem. In this model, the user registers directly with the client, and the client asks the “service provider” to provide services in its own name, so there is no authorization problem.
Update token
If the client’s “access token” has expired when the user accesses, you need to use the “update token” to request a new access token.
The client sends an HTTP request to update the token, containing the following parameters:
- granttype: indicates the authorization mode used, the value here is fixed to "refreshtoken", mandatory.
- refresh_token: indicates the update token received earlier, mandatory.
- scope:Indicates the authorization scope of the application, which cannot exceed the scope of the previous application. If this parameter is omitted, it means the same as the previous one.
OIDC
OpenID Connect is an interoperable authentication protocol based on the OAuth 2.0 family of specifications. It is implemented using simple REST / JSON message flows and can be easily integrated by developers compared to any previous authentication protocol.
OpenID Connect allows developers to authenticate users across websites and applications without the need to own and manage password files. openID Connect allows all types of clients, including browser-basedJavaScriptand native mobile applications, start the login flow and receive verifiable assertions about the identity of the logged-in user.
Briefly, OIDC is a security mechanism for applications to connect to an Identity Service to obtain user information and return that information to the application in a secure and reliable way.
Difference
OpenID is Authentication, which authenticates the user’s identity and determines whether it is valid, i.e., lets the site know that “you are the user you claim to be”;
OAuth is Authorization, which is the authorization of a user to allow certain actions when the user’s identity is known to be legitimate, i.e., to let the site know “you are allowed to do those things”.
It is clear from this that authorization is done after authentication, and only if the user’s identity is determined can authorization be granted.
OpenID Connect is a combination of “authentication” and “authorization”, and because it is based on the OAuth protocol, the OpenID-Connect protocol also contains the client_id, client_secret and redirect_uri fields. The OpenID-Connect protocol also contains fields such as client_id, client_secret and redirect_uri. This information is stored in the “authentication server” to ensure that specific clients receive information only from legitimate application platforms. This is done in order to prevent client_id leaks from causing malicious websites to initiate OIDC processes.
Process Introduction
OAuth2 provides Access Token to solve the problem of authorizing third-party clients to access protected resources; similarly, OIDC provides ID Token on top of this to solve the problem of identifying user authentication by third-party clients. The core of OIDC is to provide the user’s authentication information (ID-Token) to the third-party client along with the authorization process of OAuth2, ID-Token is wrapped using JWT format, thanks toJWTThe self-contained, compact, and tamper-proof mechanism of ID-Token allows it to be securely passed to third-party client applications and easily verified. There should be a server that uses the Access-Token interface to UserInfo to exchange more information about the user after verifying that the ID-Token is correct.
It is clear from the above that OIDC follows the OAuth protocol flow and returns an ID-Token to authenticate the user’s identity while applying for an Access-Token.
Terminology
EU: End User, user.
RP: Relying Party , used to refer to a trusted client in OAuth2, the consumer of authentication and authorization information;
OP: OpenID Provider, a service provider with the ability to provide EU authentication (such as the authorization service in OAuth2), used to provide the RP with EU authentication information;
ID-Token: data in JWT format, containing information about EU identity authentication.
UserInfo Endpoint: user information interface (protected by OAuth2) that returns information about an authorized user when the RP is accessed using Access-Token, this interface must use HTTPS.
Specific process
If it is a JS application where all its code is exposed by being loaded into the browser and no backend can secure client_secret, then it needs to be using Default Mode Flow (Implicit Flow).
If it is a traditional client-side application, the back-end code and the user are isolated and can ensure that client_secret is not leaked, you can use Authorization Code Pattern Flow (Authentication Flow).
There is also Hybrid Flow, which in short is a fusion of the above two.
Authorization Code Process
RP sends an authentication request to the OP with a client_id attached;
The OP authenticates the EU;
The OP returns a response, sending the authorization code to the RP;
The RP uses the authorization code to request the ID-Token and Access-Token from the OP, which is verified by the RP and returned to the RP;
RP sends a request to UserInfo EndPoint using the Access-Token; UserInfo EndPoint returns the EU’s Claims.
authentication request
RP uses OAuth2’s Authorization-Code approach to complete user authentication, and all Tokens are passed through the OP’s Token EndPoint (OAuth2中定义) to be issued. To construct an Authentication Request for OIDC, the following parameters are required:
- scope: Mandatory. oidc requests must contain the parameter “openid” for the scope.
- response_type: mandatory. Same as OAuth2.
- client_id: mandatory. Same as OAuth2.
- redirect_uri: Required. Same as OAuth2.
- state: Recommended. Same as OAuth2. prevents CSRF, XSRF.
After the OP receives the authentication request, it needs to do strict validation of the request parameters, and the specific rules are described inhttp://openid.net/specs/openid-connect-core-1_0.html#AuthRequestValidationAfter the authentication has passed, the EU is directed to authenticate and agree to the authorization. After this is done, it redirects to the callback address specified by the RP (redirect_uri) and passes the code and state parameters.
RP uses the code obtained in the previous step to request Token EndPoint, a step that buckets OAuth2 and will not be expanded in detail. The Token EndPoint then returns the response Token, which has an additional id_token field in addition to some of the data specified by OAuth2. The id_token field is the ID Token mentioned above.
ID token
As mentioned above OIDC’s most significant extension to OAuth2 is the provision of ID-Token. Let’s take a look at the main components of ID-Token:
- iss = Issuer Identifier: Required. Unique identifier of the person providing the authentication information. Usually the host+path part of the Url;
- sub = Subject Identifier: must. unique identifier of the EU provided by iss; maximum of 255 ASCII characters;
- aud = Audience(s): required. Identifies the audience of the ID-Token. Must contain the client_id of OAuth2;
- exp = Expiration time: required. Expiration time of ID-Token;
- iat = Issued At Time: must. time of the JWT build.
- auth_time = AuthenticationTime: the time when the EU completes authentication. This Claim is required if the RP carries the max_age parameter when sending the authentication request.
- nonce: random string provided by the RP when sending the request, used to mitigate replay attacks and also to associate the ID-Token with the RP’s own Session information.
- acr = Authentication Context Class Reference: optional. Indicates an authentication context reference value that can be used to identify an authentication context class.
- amr = Authentication Methods References: optional. Indicates a set of authentication methods.
- azp = Authorized party: optional. Used in combination with aud. This value is only used if the authenticated party and the audience (aud) do not agree, and is rarely used in general.
Default Process
The default process is similar to the one in OAuth, except that it also adds ID-Token related content.
It is important to note here that the OIDC documentation makes it very clear that all user-related information is to be encoded using the JWT form. In JWT, no sensitive data should be included in the load. If the transfer is the User ID of the user, this value is not actually sensitive and is generally safe to be known.
UserInfo Endpoint
Some readers may have noticed that ID-Token only sub is related to EU, which is not enough in general, other information such as EU username, avatar, etc. must also be needed, OIDC provides a set of public cliams to provide more information about the user, which is - UserIndo EndPoin.
After RP gets the Access Token, it can request this resource and then get a set of EU-related Claims, which can be said to be an extension of ID-Token, ID-Token only needs to contain the unique identification sub of EU (to avoid the ID Token being too large and exposing the user’s sensitive information), and then after getting the complete EU’s information through this interface. This resource must be deployed on top of TLS
A little thinking about OAuth
User: User
User Agent: User agent, such as a browser
Consumer: Information consumer, such as Leetcode
Service Provider: There are two service providers, the Identity Provider (IDP), such as QQ, and the Resource Provider, but they are generally the same.
OAuth is not designed to solve security or performance problems.
OAuth also does not save the login state in the Consumer for us.
The purpose of OAuth appeared is to help us associate multiple application accounts with a third-party account, it is the user who gives the permission to the consumer in SP, not the permission to the user in the consumer. We have not lost one account, but established a one-to-many relationship, similar to if we want to get a driver’s license, we need to use our ID card, and authorize the driving school to use our ID card information to go to the Public Security Bureau to confirm our existence and retrieve some other information. But that’s where it ends, and what happens next has nothing to do with OAuth.
The IDP cannot and has no responsibility to save any information of the user in the consumer, it just tells the consumer some information in the case of user authorization.
The first time is for the IDP to set the location in the return 302, you can not verify whether it is set by the consumer, the second time is to verify whether the redirect_uri is set by you in the IDP, and whether it is the same as the first time over, this step must be verified, because this step is the most critical, this step will return the token.
In the end, I still can’t trust my comrade browser, so I let him be a tool to help my own backend to apply for an authorization code to a third party, and then give this authorization code to my own backend, and then my own backend use this code to apply for a token to a third party, and then I don’t tell my browser afterwards. This token is what, they left, that is to say, the browser comrades from beginning to end have not seen the token.
What is the use of Secret? The reason is that IDPs don’t believe in anyone, they believe in the secret they give out. because redirect_uri is the domain name, and ultimately where it goes still depends on the IP address, if the domain name is right, but the domain name is pointed to their IP by the attacker, the attacker will receive the token. how to modify this DNS pointing involves DNS pollution, because DNS will cache layers, but then there is time. But then there is time, if you keep broadcasting to tell the router or host I am leetcode, I am leetcode, over time you are considered as leetcode in this piece of LAN. But if you have a secret, even if you come over to IDP with code, without the secret I gave you, IDP will not give token. so client_id shows who you are, only if you give client_secret, IDP will believe what you say and give you token, so this secret is very important, our The backend will not believe the browser comrades, so our browser comrades from the beginning to the end also did not touch the secret.
And what is the use of State? Similar to the defense of CSRF, to ensure the consistency of the request device, but not like CSRF is to forge the victim’s request, but let the victim login to their own account, if the victim in it to save a bitcoin account would not be beautiful? The specific implementation is the attacker logged in, the normal application, but to the IDP returned 302 after the request to stop, do not allow the browser to send requests to their own background, and then the request link with code to the victim, the victim clicked in to get access_token to successfully log in, if you do not pay attention to this account is not their own upload sensitive information, it is very happy. If there is a state, different devices my background are generated a random string to the front end, the attacker even if the request to the victim, he does not know the state of the victim’s device, the background take a look at your state and just said that the state is not the same, it will directly throw away the request, of course, to say that the attacker to your state from the huge Internet of A certain request to steal to, that is also the absolute, this belongs to the fixed-point blast, is to mess with you, then this person has mostly mixed in your side.
Why will finally return two token because one represents who you are and one represents what you can do, what you can do can be changed by the administrator at any time, but who you are is fixed, and the general access_token expiration time is relatively short, if I use it expired, can not let the user re-login it, that is not back to the beginning?
After all, these designs are stuck above the transport layer, so what if I mess with your network layer? I then spread an ARP virus? Engage the link layer is a bit exaggerated.
Reference article:
https://sunra.top/2019/11/16/OAuth%20and%20OIDC/ :OAuth,OIDC简介
https://sunra.top/posts/74ee5df7/ : Routing Protocol
https://sunra.top/posts/dfdf7442/ : ARP principle and defense
https://www.jianshu.com/p/0db71eb445c8 : Example of OAuth authentication process
https://www.chrisyue.com/security-issue-about-oauth-2-0-you-should-know.html :OAuth2.0中的安全考虑
https://www.cnblogs.com/linianhui/p/openid-connect-core.html :OIDC文档
https://www.zhihu.com/question/19851243 : OAuth1.0 and 2.0 difference
https://docs.azure.cn/zh-cn/active-directory/azuread-dev/v1-protocols-openid-connect-code :OIDC + AAD
https://www.sciencedirect.com/science/article/pii/S2215098617316750 : Security issues faced in cloud services
https://developer.mozilla.org/zh-CN/docs/Web/Security/Same-origin_policy :同源策略