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 tokensclaims.
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
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.
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.
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 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.
(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
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.
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.
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.
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.
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.
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.
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
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.
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.
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
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”.
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 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.
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
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.
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.
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.
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.
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
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.
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.
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.
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.
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.
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
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.
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.
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
application area in which JWTs are commonly
used is representing digital identity information, such as OpenID
Connect ID Tokens [OpenID.Core] and OAuth 2.0 [RFC6749] access tokens
and refresh tokens, the details of which are deployment-specific
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 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.
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
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. This
specification replaces and obsoletes the OAuth 1.0 protocol described
in RFC 5849.
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 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.
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
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).
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
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.
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.
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.
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:
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.
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.