OAuth 2.0
Fleeting- third-party vs first-party
- scope
- what is not OAuth 2.0 is not useless or a bad idea
- the purpose of OAuth 2.0 was to avoid that the client oauth 2.0 sees the resource owner’s password
- user consent screen
- it starts with a oauth 2.0 client registering itself with a authorization server
- user agent
- two modes of communication
- cross jwt confusion
- 5 types of grant -> now only 2
- What is an Access Token?
- authorization server
- the resource owner needs to know the authorization server and trust it
- resource server
- refresh token - refresh token request - refresh token rotation
- access token
- token instrospection
- kinds of token
- oauth 2.0 client
- OAuth 2.0 access token response
- types of attack
- Notes linking here
- Permalink
- External reference: https://datatracker.ietf.org/doc/html/rfc6749#section-10.3
- External reference: https://auth0.com/intro-to-iam/what-is-oauth-2/
- External reference: https://datatracker.ietf.org/doc/html/rfc6749
- External reference: https://www.oauth.com/oauth2-servers/access-tokens/access-token-lifetime/
- External reference: https://www.oauth.com/oauth2-servers/access-tokens/self-encoded-access-tokens/
- External reference: https://datatracker.ietf.org/doc/html/rfc7523
- External reference: https://oauth.net/2/
- External reference: https://oauth.net/2/jwt/
OAuth stands for open authorization. There are a lot of specifications made by OAuth guys, but when people talk about OAuth2, they generally mean the initial specification created in 2012: OAuth 2.0 authorization framework (a.k.a. RFC 6749). This RFC defines the authorization delegation flows and defines the four roles (a client that gets granted access by an authorization server of resources belonging to a resource owner and stored in a resource server) and concepts (bearer token, access token, refresh token, etc).
It seems like OAuth2 guys also invented JWT (a.k.a. RFC 7519).
It also seems like a lot of implementations have made use of JWT (and more precisely JWS and JWE compact serialisations) to encode the access token in a self-encoded access tokens.
Now, people tend to forget that the framework was defined with opaque bearer token in mind and that using a JWT encoded access token is not part of the initial spec.
This use of JWT everywhere appears to be the reason why OAuth guys came with another RFC to try to specify a bit what should be put in those self-encoded access tokens. This RFC, called JWT Access Tokens for OAuth 2.0 (a.k.a. RFC9068) is very young (October 2021) compared to the initial spec (October 2012). They even suggest this in their website.1
Also, people also tend to forget that OAuth is only about authorization and not at all about authentication. Authentication is needed prior to authorize anything, but OAuth does not say a thing about it. That is one of the reasons why OpenID Connect exists. It is an extension that brings (among other things) this missing piece: authentication. Because this is strongly related to the notion of identity, it adds the concept of Identity Token (which is actually specified to be JWT encoded, making people confuse it with a self-encoded access tokens). It also defined a few oauth 2.0 scopes related to user’s identity (like openid).
In contrast to OAuth 2.0 access token, which is supposed to be opaque from the client point of view, the ID Token is meant to be read by this role. See ID Tokens vs Access Tokens.
Nothing is said in OAuth about how the resource server and the client should link resources to self-encoded access tokens claims.
The classical flow of OAuth 2.0 ensures that the client and resource servers won’t ever see the users credentials.2
The other flows are tailored to specific use cases and try to make sensible compromises on security.
The OAuth 2.0 authorization framework enables a third-party application to obtain limited access to an HTTP service
OAuth defines four roles:
- resource owner
- An entity capable of granting access to a protected resource. When the resource owner is a person, it is referred to as an end-user.
- resource server
- The server hosting the protected resources, capable of accepting and responding to protected resource requests using access tokens.
- client
- An application making protected resource requests on behalf of the resource owner and with its authorization. The term “client” does not imply any particular implementation characteristics (e.g., whether the application executes on a server, a desktop, or other devices).
- authorization server
- The server issuing access tokens to the client after successfully authenticating the resource owner and obtaining authorization.
(A) The client requests authorization from the resource owner. The authorization request can be made directly to the resource owner (as shown), or preferably indirectly via the authorization server as an intermediary.
(B) The client receives an authorization grant, which is a credential representing the resource owner’s authorization, expressed using one of four grant types defined in this specification or using an extension grant type. The authorization grant type depends on the method used by the client to request authorization and the types supported by the authorization server.
(C) The client requests an access token by authenticating with the authorization server and presenting the authorization grant.
(D) The authorization server authenticates the client and validates the authorization grant, and if valid, issues an access token.
(E) The client requests the protected resource from the resource server and authenticates by presenting the access token.
(F) The resource server validates the access token, and if valid, serves the request.
OAuth defines two client types, based on their ability to authenticate securely with the authorization server (i.e., ability to maintain the confidentiality of their client credentials):
confidential Clients capable of maintaining the confidentiality of their credentials (e.g., client implemented on a secure server with restricted access to the client credentials), or capable of secure client authentication using other means.
public Clients incapable of maintaining the confidentiality of their credentials (e.g., clients executing on the device used by the resource owner, such as an installed native application or a web browser-based application), and incapable of secure client authentication via any other means.
- web application
- A web application is a confidential client running on a web server. Resource owners access the client via an HTML user interface rendered in a user-agent on the device used by the resource owner. The client credentials as well as any access token issued to the client are stored on the web server and are not exposed to or accessible by the resource owner.
- user-agent-based application
- A user-agent-based application is a public client in which the client code is downloaded from a web server and executes within a user-agent (e.g., web browser) on the device used by the resource owner. Protocol data and credentials are easily accessible (and often visible) to the resource owner. Since such applications reside within the user-agent, they can make seamless use of the user-agent capabilities when requesting authorization.
- native application
- A native application is a public client installed and executed on the device used by the resource owner. Protocol data and credentials are accessible to the resource owner. It is assumed that any client authentication credentials included in the application can be extracted. On the other hand, dynamically issued credentials such as access tokens or refresh tokens can receive an acceptable level of protection. At a minimum, these credentials are protected from hostile servers with which the application may interact. On some platforms, these credentials might be protected from other applications residing on the same device.
The authorization server issues the registered client a client identifier – a unique string representing the registration information provided by the client. The client identifier is not a secret; it is exposed to the resource owner and MUST NOT be used alone for client authentication. The client identifier is unique to the authorization server.
The token may denote an identifier used to retrieve the authorization information or may self-contain the authorization information in a verifiable manner (i.e., a token string consisting of some data and a signature). Additional authentication credentials, which are beyond the scope of this specification, may be required in order for the client to use a token
This specification makes extensive use of HTTP redirections, in which the client or the authorization server directs the resource owner’s user-agent to another destination.
This specification defines four grant types:
- authorization code,
- implicit,
- resource owner password credentials,
- and client credentials
An authorization grant is a credential representing the resource owner’s authorization (to access its protected resources) used by the client to obtain an access token
The resource owner password credentials (i.e., username and password) can be used directly as an authorization grant to obtain an access token.
The credentials should only be used when there is a high degree of trust between the resource owner and the client (e.g., the client is part of the device operating system or a highly privileged application), and when other authorization grant types are not available (such as an authorization code)
This grant type can eliminate the need for the client to store the resource owner credentials for future use, by exchanging the credentials with a long-lived access token or refresh token.
The client credentials (or other forms of client authentication) can be used as an authorization grant when the authorization scope is limited to the protected resources under the control of the client
When choosing between the implicit grant type and the authorization code grant type, the following should be considered:
o Native applications that use the authorization code grant type SHOULD do so without using client credentials, due to the native application’s inability to keep client credentials confidential.
o When using the implicit grant type flow, a refresh token is not returned, which requires repeating the authorization process once the access token expires.
Authorization codes operate as plaintext bearer credentials, used to verify that the resource owner who granted authorization at the authorization server is the same resource owner returning to the client to complete the process.
Authorization codes MUST be short lived and single-use.
Unlike access tokens, refresh tokens are intended for use only with authorization servers and are never sent to resource servers.
(A) The client requests an access token by authenticating with the authorization server and presenting an authorization grant.
(B) The authorization server authenticates the client and validates the authorization grant, and if valid, issues an access token and a refresh token.
(C) The client makes a protected resource request to the resource server by presenting the access token.
(D) The resource server validates the access token, and if valid, serves the request.
(E) Steps (C) and (D) repeat until the access token expires. If the client knows the access token expired, it skips to step (G); otherwise, it makes another protected resource request.
(F) Since the access token is invalid, the resource server returns an invalid token error.
(G) The client requests a new access token by authenticating with the authorization server and presenting the refresh token. The client authentication requirements are based on the client type and on the authorization server policies.
(H) The authorization server authenticates the client and validates the refresh token, and if valid, issues a new access token (and, optionally, a new refresh token).
Steps (C), (D), (E), and (F) are outside the scope of this specification, as described in Section 7.
This specification does not provide any methods for the resource server to ensure that an access token presented to it by a given client was issued to that client by the authorization server
— https://datatracker.ietf.org/doc/html/rfc6749#section-10.3
ability to send request parameters in a JSON Web Token (JWT) instead, which allows the request to be signed with JSON Web Signature (JWS) and encrypted with JSON Web Encryption (JWE) so that the integrity, source authentication, and confidentiality properties of the authorization request are attained. The request can be sent by value or by reference
This specification defines the use of a JSON Web Token (JWT) Bearer Token as a means for requesting an OAuth 2.0 access token as well as for client authentication.
third-party vs first-party
The client IS a third party, hence a party that is from an organization different than the one owning the resources.
This RFC takes this into account in its security model. In the case of a first-party, where the client and the resource owner belong to the same organization, there are several aspects of the rfc that you don’t need, like the user consent screen or even the need for a delegated authorization scheme like oauth2. In that case, using OIDC, and passing only the ID Token as authentication proof, may be enough.
scope
what is not OAuth 2.0 is not useless or a bad idea
It’s just not supported by a group of people that have spent more than 10 years trying to define something secure.
For instance, you might have a good flow based on the implicit grant. It’s just not oauth anymore.
For example, OpenID Connect provide something very similar to the implicit grant, with a way to validate the access token using its hash in the id token.
the purpose of OAuth 2.0 was to avoid that the client oauth 2.0 sees the resource owner’s password
user consent screen
It is the human readable version of the oauth 2.0 scope, so that the resource owner can give per consent.
it starts with a oauth 2.0 client registering itself with a authorization server
user agent
Generally the web browser. The stuff used by the user to perform the authentication and used, via http redirection to share the authorization code.
two modes of communication
an ambiguity
There were defined at a time (~2010) when only backend could make secure connections. Therefore we need to remember that front channel actually means with intermediary, insecure and back channel means end-to-end and encrypted.
A front end can totally make back channel communication as of today.
front channel is about UI and the back channel is about converting the outcome of the frontchannel to tokens
The front channel is insecure and not trustworthy to send data between the authorization server and the oauth 2.0 client. Yet it is the only way so far to make the resource owner be part of this triangle communication and give per consent
back channel
A secure (meaning https) end to end communication.
For instance, it is the way the authorization code is shared between the authorization server and the oauth 2.0 client.
- see,
front channel
A less secure way of sharing information than the back channel, where the user agent is involved to share some information, like a mailman between two parties.
For instance, the authorization code is issued by the authorization server to the oauth 2.0 client using a 302 response.
The user agent being a man in the middle, there is no way for the authorization server to find out whether the oauth 2.0 client actually correctly received appropriate data and for the oauth 2.0 client to find out whether the data got from the authorization server is the correct one.
Also, there is no certainty that the data in the url did not got spoofed and used by the spoofer. Therefore, the implicit grant, with all the extensions like the browser syncing ones that save and reuse the browser history, is not deprecated.
Fortunately, the authorization code grant with PKCE mitigates this issue.
metaphor of the wall
It is like the frontchannel is a wall and you send stuff to the other side.
You cannot tell whether someoen got it and whether this someone is actually the appropriate recipient.
Also, the recipient cannot tell whether the stuff that is thrown above the wall comes from the appropriate sender.
cross jwt confusion
-
External reference: https://datatracker.ietf.org/doc/html/rfc8725#section-3.9 See also misuse of access token to impersonate resource owner in implicit flow
As JWTs are being used by more different protocols in diverse application areas, it becomes increasingly important to prevent cases of JWT tokens that have been issued for one purpose being subverted and used for another. Note that this is a specific type of substitution attack. If the JWT could be used in an application context in which it could be confused with other kinds of JWTs, then mitigations MUST be employed to prevent these substitution attacks.
the JWT MUST contain an “aud” (audience) claim that can be used to determine whether the JWT is being used by an intended party or was substituted by an attacker at an unintended party.
In such cases, the relying party or application MUST validate the audience value, and if the audience value is not present or not associated with the recipient, it MUST reject the JWT.
To prevent substitution of JWTs from one context into another, application developers may employ a number of strategies:
- Use explicit typing for different kinds of JWTs. Then the distinct “typ” values can be used to differentiate between the different kinds of JWTs.
- Use different sets of required claims or different required claim values. Then the validation rules for one kind of JWT will reject those with different claims or values.
- Use different sets of required Header Parameters or different required Header Parameter values. Then the validation rules for one kind of JWT will reject those with different Header Parameters or values.
- Use different keys for different kinds of JWTs. Then the keys used to validate one kind of JWT will fail to validate other kinds of JWTs.
- Use different “aud” values for different uses of JWTs from the same issuer. Then audience validation will reject JWTs substituted into inappropriate contexts.
- Use different issuers for different kinds of JWTs. Then the distinct “iss” values can be used to segregate the different kinds of JWTs.
Given the broad diversity of JWT usage and applications, the best combination of types, required claims, values, Header Parameters, key usages, and issuers to differentiate among different kinds of JWTs will, in general, be application-specific.
— https://datatracker.ietf.org/doc/html/rfc8725#section-3.12
5 types of grant -> now only 2
authorization code grant
The client constructs the request URI by adding the following parameters to the query component of the authorization endpoint URI using the “application/x-www-form-urlencoded” format, per Appendix B:
- response_type
- REQUIRED. Value MUST be set to “code”.
- client_id
- REQUIRED. The client identifier as described in Section 2.2.
- redirect_uri
- OPTIONAL. As described in Section 3.1.2.
- scope
- OPTIONAL. The scope of the access request as described by Section 3.3
- state
- RECOMMENDED. An opaque value used by the client to maintain state between the request and callback. The authorization server includes this value when redirecting the user-agent back to the client. The parameter SHOULD be used for preventing cross-site request forgery as described in Section 10.12.
Authorization Code Flow returns an Authorization Code to the Client, which can then exchange it for an ID Token and an Access Token directly. This provides the benefit of not exposing any tokens to the User Agent and possibly other malicious applications with access to the User Agent
— https://openid.net/specs/openid-connect-core-1_0.html#Introduction
access token request
-
External reference: https://datatracker.ietf.org/doc/html/rfc6749#section-4.1.3
The client makes a request to the token endpoint by sending the following parameters using the “application/x-www-form-urlencoded” format per Appendix B with a character encoding of UTF-8 in the HTTP request entity-body:
grant_type REQUIRED. Value MUST be set to “authorization_code”.
code REQUIRED. The authorization code received from the authorization server.
redirect_uri REQUIRED, if the “redirect_uri” parameter was included in the authorization request as described in Section 4.1.1, and their values MUST be identical.
client_id REQUIRED, if the client is not authenticating with the authorization server as described in Section 3.2.1.
— https://datatracker.ietf.org/doc/html/rfc6749#section-4.1.3
POST /token HTTP/1.1 Host: server.example.com Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW Content-Type: application/x-www-form-urlencoded
grant_type=authorization_code&code=SplxlOBeZQQYbYS6WxSbIA &redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Fcb
— https://datatracker.ietf.org/doc/html/rfc6749#section-4.1.3
authorization code
password grant
-
External reference: https://datatracker.ietf.org/doc/html/rfc6749#section-4.3
Is it appropriate to use resource owner password credential grant type.
The short answer is never
— Nat Sakimura (https://youtube.com/watch?v=qMtYaDmhnHU&t=4.65s)
implicit grant
-
External reference: https://datatracker.ietf.org/doc/html/rfc6749#section-4.2
Authorization Request
The client constructs the request URI by adding the following parameters to the query component of the authorization endpoint URI using the “application/x-www-form-urlencoded” format, per Appendix B:
- response_type
- REQUIRED. Value MUST be set to “token”.
- client_id
- REQUIRED. The client identifier as described in Section 2.2.
- redirect_uri
- OPTIONAL. As described in Section 3.1.2.
- scope
- OPTIONAL. The scope of the access request as described by Section 3.3
- state
- RECOMMENDED. An opaque value used by the client to maintain state between the request and callback. The authorization server includes this value when redirecting the user-agent back to the client. The parameter SHOULD be used for preventing cross-site request forgery as described in Section 10.12.
example, the client directs the user-agent to make the following HTTP request using TLS (with extra line breaks for display purposes only):
GET /authorize?response_type=token&client_id=s6BhdRkqt3&state=xyz &redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Fcb HTTP/1.1 Host: server.example.com
What is an Access Token?
-
External reference: https://oauth.net/2/access-tokens/ What is an Access Token - OAuth 2.0
OAuth Access Token is a string that the OAuth client uses to make requests to the resource server.
Access tokens do not have to be in any particular format, and in practice, various OAuth servers have chosen many different formats for their access tokens
Access tokens may be either “bearer tokens” or “sender-constrained” tokens. Sender-constrained tokens require the OAuth client to prove possession of a private key in some way in order to use the access token, such that the access token by itself would not be usable
Access tokens must not be read or interpreted by the OAuth client. The OAuth client is not the intended audience of the token.
Access tokens should only be used to make requests to the resource server
authorization server
authorization request
Rich Authorization Requests
-
External reference: https://datatracker.ietf.org/doc/html/draft-ietf-oauth-rar OAuth 2.0, user consent screen, oauth 2.0 scope
implement static scenarios and coarse-grained authorization requests, such as “give me read access to the resource owner’s profile” but it is not sufficient to specify fine-grained authorization requirements, such as “please let me transfer an amount of 45 Euros to Merchant A” or “please give me read access to directory A and write access to file X”.
— https://datatracker.ietf.org/doc/html/draft-ietf-oauth-rar#name-introduction
JWT-Secured Authorization Request
- External reference: https://datatracker.ietf.org/doc/html/rfc9101 OAuth 2.0, RAR,
authorization request in OAuth 2.0 described in RFC 6749 utilizes query parameter serialization
This document introduces the ability to send request parameters in a JSON Web Token (JWT) instead
allows the request to be signed with JSON Web Signature (JWS) and encrypted with JSON Web Encryption (JWE) so that the integrity, source authentication, and confidentiality properties of the authorization request are attained
ability to send request parameters in a JSON Web Token (JWT) instead, which allows the request to be signed with JSON Web Signature (JWS) and encrypted with JSON Web Encryption (JWE) so that the integrity, source authentication, and confidentiality properties of the authorization request are attained. The request can be sent by value or by reference
Pushed Authorization Requests
-
External reference: https://datatracker.ietf.org/doc/html/rfc9126 OAuth 2.0, JAR, RAR
pushed authorization request (PAR) endpoint, which allows clients to push the payload of an OAuth 2.0 authorization request to the authorization server via a direct request and provides them with a request URI that is used as reference to the data in a subsequent call to the authorization endpoint.
the resource owner needs to know the authorization server and trust it
This is the entity that will gets the user password and provide the user consent screen. A trust relationship between those entities is needed.
resource server
- External reference: https://datatracker.ietf.org/doc/html/rfc8725#section-3.12
refresh token
Unlike access tokens, refresh tokens are intended for use only with authorization servers and are never sent to resource servers.
used to obtain a new access token when the current access token becomes invalid or expires, or to obtain additional access tokens with identical or narrower scope
Refresh tokens are credentials used to obtain access tokens.
refresh token request
-
External reference: https://datatracker.ietf.org/doc/html/rfc6749#section-6
If the authorization server issued a refresh token to the client, the client makes a refresh request to the token endpoint by adding the following parameters using the “application/x-www-form-urlencoded” format per Appendix B with a character encoding of UTF-8 in the HTTP request entity-body:
grant_type REQUIRED. Value MUST be set to “refresh_token”.
refresh_token REQUIRED. The refresh token issued to the client.
scope OPTIONAL. The scope of the access request as described by Section 3.3. The requested scope MUST NOT include any scope not originally granted by the resource owner, and if omitted is treated as equal to the scope originally granted by the resource owner.
POST /token HTTP/1.1 Host: server.example.com Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW Content-Type: application/x-www-form-urlencoded
grant_type=refresh_token&refresh_token=tGzv3JOkF0XG5Qx2TlKWIA
refresh token rotation
According to OAuth – the good Parts - Anders Abel - NDC Oslo 2022, refresh tokens should be chained. Each refresh token should be for one time use only and refreshing should issue another refresh token. That way, when you don’t manage to refresh, you know someone spoofed it and can invalidate all the tokens made by this chain.
According to Forget about OAuth 2.0. Here comes OAuth 2.1 - Philippe De Ryck - NDC Oslo 2022, this does not prevent attacks. When an attacker gets access to the client code (using XSS), per can make the application ping a remote server to make it know how long the client session is open.
When the remote server ceases to receive pings, it can simply use the last refresh token. Per won’t be bothered as long as the user keeps logged out.
See also OIDC Silent Authentication.
Auth0 recommends using refresh token rotation which provides a secure method for using refresh tokens in SPAs while providing end-users with seamless access to resources without the disruption in UX caused by browser privacy technology like ITP.
technique for getting new access tokens using refresh tokens that goes beyond silent authentication.
— https://auth0.com/docs/secure/tokens/refresh-tokens/refresh-token-rotation
Refresh tokens are often used in native applications on mobile devices in conjunction with short-lived access tokens to provide seamless UX without having to issue long-lived access tokens.
— https://auth0.com/docs/secure/tokens/refresh-tokens/refresh-token-rotation
Until very recently, SPAs maintained the user’s session by using the Authorization Code Flow with PKCE in conjunction with silent authentication
— https://auth0.com/docs/secure/tokens/refresh-tokens/refresh-token-rotation
Unfortunately, long-lived refresh tokens are not suitable for SPAs because there is no persistent storage mechanism in a browser that can assure access by the intended application only
— https://auth0.com/docs/secure/tokens/refresh-tokens/refresh-token-rotation
using refresh tokens in SPAs has been strongly discouraged.
— https://auth0.com/docs/secure/tokens/refresh-tokens/refresh-token-rotation
Refresh token rotation offers a remediation to end-user sessions being lost due to side-effects of browser privacy mechanisms. Because refresh token rotation does not rely on access to the Auth0 session cookie, it is not affected by ITP or similar mechanisms.
— https://auth0.com/docs/secure/tokens/refresh-tokens/refresh-token-rotation
As soon as the new pair is issued by Auth0, the refresh token used in the request is invalidated. This safeguards your app from replay attacks resulting from compromised tokens.
— https://auth0.com/docs/secure/tokens/refresh-tokens/refresh-token-rotation
access token
The access token provides an abstraction layer, replacing different authorization constructs (e.g., username and password) with a single token understood by the resource server. This abstraction enables issuing access tokens more restrictive than the authorization grant used to obtain them, as well as removing the resource server’s need to understand a wide range of authentication methods.
access token is a string representing an authorization issued to the client. The string is usually opaque to the client
It may be a bearer token, provided in the authorization header as defined in https://datatracker.ietf.org/doc/html/rfc2617.
use different lifetimes for your access tokens depending on the criticality of the scope
short lived
need to make some decisions as to how long you want the tokens to last. Unfortunately there is no blanket solution for every service
— https://www.oauth.com/oauth2-servers/access-tokens/access-token-lifetime/
common method of granting tokens is to use a combination of access tokens and refresh tokens for maximum security and flexibility. The OAuth 2.0 spec recommends this option, and several of the larger implementations have gone with this approach
— https://www.oauth.com/oauth2-servers/access-tokens/access-token-lifetime/
token instrospection
kinds of token
reference token vs self-encoded access token
reference token | self encoded access token |
---|---|
easy to invalidate | needs to wait token expiration |
needs more authorization server calls | only need to fetch the public key from time to time |
not easily confused with id token | clients tend to feel legitimate looking into it |
needs to implement introspection in the resource server | easier dev because the token contains all the needed information |
This looks like a simple comparison, but depending on the properties of the self-encoded access token, the comparison might less relevant. For instance, the less the expiration time, the more the self encoded access token resembles a reference token with regards to validity and authorization call load.
Also, using JWE, one can make the token more opaque and mitigate the issue with client looking where they should not.
use an API Gateway
The API Gateway can, depending on the accessed data, decide to let the self-encoded access token go through or perform a token instrospection lookup to avoid the possibility of false positive (security vs user experience balance).
Is also provide a fast filter, allowing the domain logic to perform the slower checks in fewer requests.
reference token
A token that does not contain useful information and needs to go through a token instrospection endpoint, as opposed to a self-encoded access token.
self-encoded access tokens
- External reference: https://www.oauth.com/oauth2-servers/access-tokens/self-encoded-access-tokens/ They are access token that contain information so that there is no need to consult a database to process them (as opposed to reference token). Because they are signed by the authorization server, they can be relying upon. They are in general encoded using JWT and serialized using JWS if the data is no sensitive, or JWE if the data is private.
The most common way to implement self-encoded tokens is to use the JWS spec, creating a JSON-serialized representation of all the data you want to include in the token, and signing the resulting string with a private key known only to your authorization server.
— https://www.oauth.com/oauth2-servers/access-tokens/self-encoded-access-tokens/
RFC 9068 defines a standard way to use JWTs as access tokens, based on the real-world deployment experience of a number of large OAuth providers.
— https://www.oauth.com/oauth2-servers/access-tokens/self-encoded-access-tokens/
Because the token can be verified without doing a database lookup, there is no way to invalidate a token until it expires
— https://www.oauth.com/oauth2-servers/access-tokens/self-encoded-access-tokens/
Self-encoded tokens provide a way to avoid storing tokens in a database by encoding all of the necessary information in the token string itself
— https://www.oauth.com/oauth2-servers/access-tokens/self-encoded-access-tokens/
API servers are able to verify access tokens without doing a database lookup on every API request, making the API much more easily scalable
— https://www.oauth.com/oauth2-servers/access-tokens/self-encoded-access-tokens/
benefit of OAuth 2.0 Bearer Tokens is that applications don’t need to be aware of how you’ve decided to implement access tokens in your service. This means it’s possible to change your implementation later without affecting clients.
— https://www.oauth.com/oauth2-servers/access-tokens/self-encoded-access-tokens/
using self-encoded tokens if you’ve already solved the distributed database problem will only introduce new issues, as invalidating self-encoded tokens becomes an additional hurdle
— https://www.oauth.com/oauth2-servers/access-tokens/self-encoded-access-tokens/
One way to create self-encoded tokens is to create a JSON-serialized representation of all the data you want to include in the token, and sign the resulting string with a key known only to your server.
— https://www.oauth.com/oauth2-servers/access-tokens/self-encoded-access-tokens/
bearer token
-
External reference: https://datatracker.ietf.org/doc/html/rfc6750
-
External reference: https://oauth.net/2/bearer-tokens/ OAuth 2.0 Bearer Token Usage
Bearer Token is an opaque string, not intended to have any meaning to clients using it. Some servers will issue tokens that are a short string of hexadecimal characters, while others may use structured tokens such as JSON Web Tokens.
Bearer Token
A security token with the property that any party in possession of the token (a “bearer”) can use the token in any way that any other party in possession of it can. Using a bearer token does not require a bearer to prove possession of cryptographic key material (proof-of-possession).
When sending the access token in the “Authorization” request header field defined by HTTP/1.1 [RFC2617], the client uses the “Bearer” authentication scheme to transmit the access token.
For example:
GET /resource HTTP/1.1 Host: server.example.com Authorization: Bearer mF_9.B5f-4.1JqM
oauth 2.0 client
-
External reference: https://datatracker.ietf.org/doc/html/rfc8725#section-2.8
This is a third party3.
- JWT access token
- An OAuth 2.0 access token encoded in JWT format and complying with the requirements described in this specification
OAuth 2.0, which stands for “Open Authorization”, is a standard designed to allow a website or application to access resources hosted by other web apps on behalf of a user
OAuth 2.0 is an authorization protocol and NOT an authentication protocol
designed primarily as a means of granting access to a set of resources,
Access Token is a piece of data that represents the authorization to access resources on behalf of the end-user.
OAuth 2.0 doesn’t define a specific format for Access Tokens. However, in some contexts, the JSON Web Token (JWT) format is often used. This enables token issuers to include data in the token itself.
for security reasons, Access Tokens may have an expiration date.
Scopes are an important concept in OAuth 2.0. They are used to specify exactly the reason for which access to resources may be granted.
for better security, an Authorization Code may be returned, which is then exchanged for an Access Token. In
grants are the set of steps a Client has to perform to get resource access authorization
There are three main steps to OAuth 2.0:
- Request authorization from a user to access their data.
- Query the user’s data using the provided access token.
- Refresh expired access tokens with the corresponding refresh token.
— https://dev.fitbit.com/build/reference/web-api/developer-guide/authorization/
traditional client-server authentication model, the client requests an access-restricted resource (protected resource) on the server by authenticating with the server using the resource owner’s credentials. In order to provide third-party applications access to restricted resources, the resource owner shares its credentials with the third party.
Third-party applications gain overly broad access to the resource owner’s protected resources, leaving resource owners without any ability to restrict duration or access to a limited subset of resources
o Resource owners cannot revoke access to an individual third party without revoking access to all third parties, and must do so by changing the third party’s password
OAuth addresses these issues by introducing an authorization layer and separating the role of the client from that of the resource owner.
Instead of using the resource owner’s credentials to access protected resources, the client obtains an access token – a string denoting a specific scope, lifetime, and other access attributes. Access tokens are issued to third-party clients by an authorization server with the approval of the resource owner. The client uses the access token to access the protected resources hosted by the resource server.
For example, an end-user (resource owner) can grant a printing service (client) access to her protected photos stored at a photo- sharing service (resource server), without sharing her username and password with the printing service. Instead, she authenticates directly with a server trusted by the photo-sharing service (authorization server), which issues the printing service delegation- specific credentials (access token).
use of OAuth over any protocol other than HTTP is out of scope.
single authorization server may issue access tokens accepted by multiple resource servers.
authorization code is obtained by using an authorization server as an intermediary between the client and resource owner
client directs the resource owner to an authorization server (via its user-agent as defined in [RFC2616]), which in turn directs the resource owner back to the client with the authorization code
Because the resource owner only authenticates with the authorization server, the resource owner’s credentials are never shared with the client.
authorization code provides a few important security benefits, such as the ability to authenticate the client, as well as the transmission of the access token directly to the client without passing it through the resource owner’s user-agent and potentially exposing it to others, including the resource owner
When issuing an access token during the implicit grant flow, the authorization server does not authenticate the client. In some cases, the client identity can be verified via the redirection URI used to deliver the access token to the client. The access token may be exposed to the resource owner or other applications with access to the resource owner’s user-agent.
client credentials (or other forms of client authentication) can be used as an authorization grant when the authorization scope is limited to the protected resources under the control of the client, or to protected resources previously arranged with the authorization server.
when the client is acting on its own behalf (the client is also the resource owner) or is requesting access to protected resources based on an authorization previously arranged with the authorization server.
resource owner password credentials grant type is suitable in cases where the resource owner has a trust relationship with the client,
server should take special care when enabling this grant type and only allow it when other flows are not viable.
suitable for clients capable of obtaining the resource owner’s credentials (username and password, typically using an interactive form).
third party client
two kinds of client
public client
In brief, a public client runs on an environment that the END USER controls.
It cannot keep secret the client secret and therefore cannot do the authorization code flow. Yet, it can run the authorization code grant with PKCE, because it is like the former, but with a dynamically generated client secret.
A public client cannot ensure that the client id or client secret are not re-used by the users of the client. In case of web client, one should rather use server side communication with the server hosting the web client to ensure the id of the client.
confidential
In brief, a public client runs on an environment that the DEVELOPER controls.
It can keep secret the client secret and then use the authorization code flow securely.
client id
client secret
Its purpose is to make sure in the end of the flow that the client is indeed the expected one. This makes only sense in the case of a confidential client, because in the case of a public client, the secret can easily be read by anyone using the client.
In the case of a public client, one should rather use authorization code grant with PKCE.
do we really need client_secret to get access_token on PKCE flow?
-
External reference: https://stackoverflow.com/questions/63057801/do-we-really-need-client-secret-to-get-access-token-on-pkce-flow
The client secret allows the authorization server (identity provider) to determine the identity of the client
OAuth 2.0 access token response
authorization server issues an access token and optional refresh token, and constructs the response by adding the following parameters to the entity-body of the HTTP response with a 200 (OK) status code:
- access_token
- REQUIRED. The access token issued by the authorization server.
- token_type
- REQUIRED. The type of the token issued as described in Section 7.1. Value is case insensitive.
- expires_in
- RECOMMENDED. The lifetime in seconds of the access token. For example, the value “3600” denotes that the access token will expire in one hour from the time the response was generated. If omitted, the authorization server SHOULD provide the expiration time via other means or document the default value.
- refresh_token
- OPTIONAL. The refresh token, which can be used to obtain new access tokens using the same authorization grant as described in Section 6.
- scope
- OPTIONAL, if identical to the scope requested by the client; otherwise, REQUIRED. The scope of the access token as described by Section 3.3.
For example:
HTTP/1.1 200 OK Content-Type: application/json;charset=UTF-8 Cache-Control: no-store Pragma: no-cache
{ “access_token”:“2YotnFZFEjr1zCsicMWpAA”, “token_type”:“example”, “expires_in”:3600, “refresh_token”:“tGzv3JOkF0XG5Qx2TlKWIA”, “example_parameter”:“example_value” }
types of attack
misuse of access token to impersonate resource owner in implicit flow
- External reference: https://datatracker.ietf.org/doc/html/rfc6749#section-10.16
Notes linking here
- “Authorization” request header
- a cookie to deal with session create fewer attack surface
- a public client CANNOT securely save a client secret
- Access Token Validation in openid connect
- According to OAuth (blog)
- API key vs client id/secret
- As an openid provider (blog)
- audience claim
- Authentication with OAuth 2.0
- authorization code grant with PKCE
- authorization server redirection and user experience
- backend for frontend
- claims-based identity
- clk k8s and earthly in a local dev env (blog)
- clk k8s: accessing the host from the pod on linux and mac (blog)
- embedded password in each client
- Everything You Ever Wanted to Know About OAuth and OIDC
- Footnotes
- Forget about OAuth 2.0. Here comes OAuth 2.1 - Philippe De Ryck - NDC Oslo 2022
- from 5 grant flow to 2
- goa
- google account security to change the third party scope consent screen
- google api endpoint /auth OAuth 2.0
- google oauth2 testing refresh token == 7 days
- grant negotiation and access protocol
- how do I create an OAuth 2.0/OIDC resource server? (blog)
- how to deal with permissions in OAuth2?
- How to Hack OAuth
- hydra: the OIDC layer
- ID Tokens vs Access Tokens
- Identity Provider
- implementing saga with access token
- Introduction to OAuth and OpenID Connect
- is the bearer token opaque?
- it mostly removed stuffs from OAuth 2.0
- JSON Web Token Best Current Practices
- JSON web tokens
- JWT Access Tokens profile for OAuth 2.0
- JWT Access Tokens profile for OAuth 2.0
- JWT Access Tokens profile for OAuth 2.0 may be different from implementations
- make sense of keycloak, openid connect, oauth 2.0, jwt, jws (blog)
- making sense of github OIDC flow
- metaphor of the hotel
- misconceptions
- misconcetions
- My opinion (blog)
- OAuth 2
- OAuth 2 with Single-Page Apps
- OAuth 2.0 Authorization Server Metadata
- OAuth 2.0 for Browser-Based Apps
- OAuth 2.0 Playground
- OAuth 2.0 Security Best Current Practice
- OAuth 2.0 Threat Model and Security Considerations
- Oauth 2.0 to define the authentication flow (blog)
- OAuth 2.0 Token Exchange
- OAuth 2.0 Token Introspection
- OAuth 2.1
- OAuth and OpenID Connect in Plain English
- OAuth in Five Minutes
- OAuth It s complicated
- oauth security best practices
- OAuth Sketch Notes Q&A - PKCE, Scopes, Security, Passwordless
- OAuth the good Parts Dominick Baier
- OAuth – the good Parts - Anders Abel
- OAuth2 Demo with a Sidecar
- OAuth2 explained with cute shapes
- OIDC vs OAuth2
- OpenID Connect
- OpenID Connect : Is it fine to use id_token as access_token? - Stack Overflow
- OpenID Connect Provider
- playing with auth0 for the first time
- playing with google OIDC
- Protect Your APIs with OAuth
- Protecting Your APIs with OAuth
- relying party
- Resource Indicators for OAuth 2.0
- resource owner
- resource server does not need to know about the resource owner
- RFC 7636: Proof Key for Code Exchange by OAuth Public Clients
- RFC 8705 - OAuth 2.0 Mutual-TLS Client Authentication and Certificate-Bound Access Tokens
- RFC 8783: Distributed Denial-of-Service Open Threat Signaling (DOTS) Data Channel Specification
- scopes
- Securing Applications and Services Guide
- Securing Your APIs with OAuth 2.0
- Securing-SPAs-and-Blazor-Applications-using-the-BFF-Backend-for-Frontend-Pattern-Dominick-Baier
- several instances of client
- should I say JWT or JWT token, or JWS token or…? (blog)
- single sign-on
- the user consent screen is not compulsory
- three worlds analogy
- trying authenticating to keycloak using google as Identity Provider
- use an exhaustive list of redirect uri in exact match
- use differents kinds of scope
- userinfo endpoint
- using a bearer token encoded in JWT format? (blog)
- using a service worker (web worker) instead
- using google as identity provider is not doing SSO
- using id token as access token?
- using personal access token (PAT)
- using pkce does not prevent from using the client secret
- what should I put into those scopes and access tokens claims? (blog)
- what should I put into those scopes and access tokens claims? (blog)
- What’s new with OAuth2.1 with Aaron Parecki
- Which OAuth 2.0 Flow Should I Use?
Permalink
-
JWTs can be used as OAuth 2.0 Bearer Tokens to encode all relevant parts of an access token into the access token itself instead of having to store them in a database
-
Before directing the resource owner back to the client with the authorization code, the authorization server authenticates the resource owner and obtains authorization. Because the resource owner only authenticates with the authorization server, the resource owner’s credentials are never shared with the client.
-
OAuth 2.0 authorization framework enables a third-party application to obtain limited access to an HTTP service, either on behalf of a resource owner by orchestrating an approval interaction between the resource owner and the HTTP service, or by allowing the third-party application to obtain access on its own behalf.