Need to protect an application with tokens? The OAuth 2.0 security frameworkis what you're looking for. It has flows for web, mobile and IoT clients,plus useful APIs for managing the token lifecycle. What started as a simpleand effective solution for granting 3rd party access to socialprofiles, has evolved to support applications in a range of domains, witheven the most stringent securityrequirements.
1. Token-based security with OAuth2.0
The token has become a popular pattern for securing applications on theinternet. Developers love its conceptual simplicity, architects the ability todesign applications with nicely decoupled security roles. However, in theseeming ease of putting together token-based security lurkpitfalls.
To put together a solid framework for dealing with tokens, with sensiblybalanced security and ease of use, while drawing on lessons from early successh*ts (notably the original OAuth),engineers from the internet community devised OAuth 2.0 and published it asRFC 6749 in2012.
Key aspects in the OAuth 2.0 framework were deliberately kept open-ended andextensible. The base RFC 6749 specifies four securityroles and introduces fourways, called authorisation grants,for clients to obtain an access token. The rest, such as what goes inside thetoken, was left for implementers or future extensions to fillin.
2. The four roles inOAuth
OAuth defines four roles, with clean separation of their concerns. This,together with the shifting of security-related complexity into a dedicatedauthorisation server, makes it possible to roll out OAuth 2.0 protectedapplications and services quickly and with consistent securityproperties.
Resourceowner The end-user. The term reflects OAuth's originalpurpose, giving 3rd party software access on a user'sbehalf. Other scenarios are alsopossible. | Resourceserver The protected asset, typically a web API, which requires a tokenin order to be accessed. The token validation logic aims to beminimal and can also bestateless. |
Client The application -- web, mobile, desktop, or device-based, thatneeds to obtain a token to access the resource server.The client-side OAuth logic is intended to be simple andminimal. | Authorisationserver Dedicated server for issuing access tokens to the client, afterauthenticating the end-user and obtaining authorisation, from theend-user or based on somepolicy. |
3. How can a client obtain atoken?
In order to obtain an access token the client needs to present a valid grant(credential) to the authorisationserver.
If there's one thing that often daunts the newcomer to OAuth 2.0, it'sselecting a suitable grant for their application. The choice becomes obvious ifyou know the type of client (web, mobile, etc) youhave.
Here is a roughguide:
Grant type | Client type / Use case |
---|---|
Authorisation code | Intended for traditional web applications with a backend as well asnative (mobile or desktop) applications to take advantage of singlesign-on via the system browser. |
Implicit | Intended for browser-based (JavaScript) applications without abackend. |
Password | For trusted native clients where the application and theauthorisation server belong to the same provider. |
Client credentials | For clients, such as web services, acting on their own behalf. |
Refresh token | A special grant to let clients refresh their access token withouthaving to go through the steps of a code orpassword grant again. |
SAML 2.0 bearer | Lets a client in possession of a SAML 2.0 assertion (sign-in token)exchange it for an OAuth 2.0 access token. |
JWT bearer | Lets a client in possession of a JSON Web Token (JWT) assertionfrom one security domain exchange it for an OAuth 2.0 access tokenin another domain. |
Device | For devices without a browser or with constrained input, such as asmart TV, media console, printer, etc. |
Token exchange | Lets applications and services obtain an access token in delegationand impersonation scenarios. |
3.1 Authorisation code flowexample
We will now go through an example of a client obtaining an access token from anOAuth 2.0 authorisation server, using the authorisation codegrant. This grant is intendedprimarily for webapplications.
The client needs to perform two steps to obtain the token, the first involvingthe browser, the second a back-channel request. That's why this series of stepsis also called the codeflow.
Step 1 | Step 2 | |
---|---|---|
Purpose |
|
|
Request | Front-channel (browser redirection) | Back-channel (client to authorisation server) |
Serverendpoint | Authorisation endpoint | Token endpoint |
On success | Authorisation code (step 2 input) | Access token Refresh token (optional) |
Code flow: Step1
The client initiates the code flow by redirecting the browser to theauthorisation server with an authorisationrequest.
Example redirection to the authorisationserver:
HTTP/1.1 302 FoundLocation: https://c2id.com/login? response_type=code &scope=myapi-read%20myapi-write &client_id=s6BhdRkqt3 &state=af0ifjsldkj &redirect_uri=https%3A%2F%2Fclient.example.org%2Fcb
The authorisation request parameters are encoded in the URIquery:
response_type Set to
code
to indicate an authorisation codeflow.scope Specifies the scope of the requested token. If omitted theauthorisation server may assume some defaultscope.
client_id The identifier of the client at the authorisation server. Thisidentifier is assigned when the client is registered with the authorisationserver, via the client registration API, a developer console, or some othermethod.
state Optional opaque value set by the client to maintain state betweenrequest andcallback.
redirect_uri The client callback URI for the authorisation response. Ifomitted the authorisation server will assume the default registeredredirection URI for theclient.
At the authorisation server, the user will typically be authenticated bychecking if they have a valid session (established by a browser cookie), and inthe absence of that, by prompting the user to login. After that the server willdetermine if the client is to be authorised or not, by asking the user fortheir consent, by applying a rule or policy, or by some othermean.
The authorisation server will then call the client redirect_uri
with anauthorisation code (on success) or an error code (if access was denied, orsome other erroroccurred).
HTTP/1.1 302 FoundLocation: https://client.example.org/cb? code=SplxlOBeZQQYbYS6WxSbIA &state=af0ifjsldkj
The client must validate the state
parameter, and use the code
to proceedto the next step - exchanging the code forthe accesstoken.
Code flow: Step2
The authorisation code is an intermediate credential, which encodes theauthorisation obtained at step 1. It istherefore opaque to the client and only has meaning to the authorisationserver. To retrieve the access token the client must submit the code to theauthorisation server, but this time with a direct back-channel request. This isdone for tworeasons:
- To authenticate confidential clients with the authorisation server beforerevealing thetoken;
- To deliver the token straight to the client, thus avoid exposing it to thebrowser.
The code-for-token exchange happens at the token endpoint ofthe authorisationserver:
POST /token HTTP/1.1Host: c2id.comContent-Type: application/x-www-form-urlencodedAuthorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JWgrant_type=authorization_code &code=SplxlOBeZQQYbYS6WxSbIA &redirect_uri=https%3A%2F%2Fclient.example.org%2Fcb
The client ID and secret are passed via the Authorization
header. Apart fromHTTP basic authenticationOAuth 2.0 also supports authentication with aJWT, which doesn't expose the clientcredentials with the token request, has expiration, and thus provides strongersecurity.
The token request parameters areform-encoded:
grant_type Set to
authorization_code
.code The code obtained from step1.
redirect_uri Repeats the callback URI from step1.
On success the authorisation server will return a JSONobject with the issued accesstoken:
HTTP/1.1 200 OKContent-Type: application/jsonCache-Control: no-storePragma: no-cache{ "access_token" : "SlAV32hkKG", "token_type" : "Bearer", "expires_in" : 3600, "scope" : "myapi-read myapi-write"}
The expires_in parameter informs the client for how many seconds the accesstoken will be valid. The scope parameter what powers the token actuallyhas, as some of the originally requested scope values may have been denied orothers, not explicitly requested,granted.
The JSON object can include an optional refreshtoken, which lets the clientobtain a new access token from the authorisation server without having torepeat the codeflow.
4. How can a client access a protected resource with atoken?
Accessing a resource server, such as a web API, with a token is super easy. Theaccess tokens in OAuth 2.0 are commonly of typebearer, meaning the clientjust needs to pass the token with each request. The HTTP Authorization headeris the recommendedmethod.
GET /resource/v1 HTTP/1.1Host: api.example.comAuthorization: Bearer oab3thieWohyai0eoxibaequ0Owae9oh
If the resource server determines the token to be valid and not expired, itwill proceed with servicing therequest.
Else, it will return an appropriateerror in a HTTPWWW-Authenticate responseheader.
Example error for an invalid or expiredtoken:
HTTP/1.1 401 UnauthorizedWWW-Authenticate: Bearer realm="api.example.com", error="invalid_token", error_description="The access token is invalid or expired"
If the client receives an invalid_token error for an access token that usedto work, this is a signal that it must request a new one from the authorisationserver.
The usage of bearer tokens is specified in RFC6750.
Keep in mind that the bearer nature of the token means whoever has possessionof it can access the resource server. The bearer tokens must therefore beprotected:
- First, by keeping the tokens in safe client-sidestorage.
- By submitting the tokens over TLS /HTTPS.
Issuing short-lived tokens can mitigate the potential risk of tokenleakage.
To fix the bearer weakness of access tokens authorisation servers and clientscan implement the mTLS extension(for web and native applications) or thedPOP extension (forSPAs) which bind the token to a private key owned by the client. When an accesstoken is bound to a private key, which can be kept in a secure HSM or devicestorage, the access token is unusable without the key. Applications that needhigher security, such as in OpenBanking, therefore require mTLS securedtokens.
5. How to secure a resource server withtokens?
To clear a submitted request the resource server needs to validate the token.The validation ensures thefollowing:
- That the access token has been issued by the authorisationserver.
- That the token hasn'texpired.
- Its scope covers therequest.
How that's done depends on the particular implementation of the access token,which is determined by the authorisation server. More on that in the nextchapter.
The required token validation logic can be easily abstracted from theunderlying resource, or retrofitted to an existing one. A reverse HTTP proxy oran API gateway can be utilised to achievethat.
Most popular web servers and frameworks, such as Apache httpd and Spring,provide some sort of module for validating incoming requests secured with abearer access token. Upon successful validation the underlying resource can beprovided with selected useful token attributes, such as the end-user'sidentity. This again is a matter ofimplementation.
6. The accesstoken
The OAuth 2.0 framework doesn't prescribe a particular embodiment for accesstokens. This decision is leftto implementors for a good reason: to clients the token is just an opaquestring; their validation is a matter between the authorisation server and theresource server(s), and since they usually belong to the same provider therehasn't been enough demand to specify a standard tokenformat.
Fundamentally, there are two types of bearertoken:
Identifier-based | Self-contained |
---|---|
The token represents a hard-to-guess string which is a key to arecord in the authorisation server's database. A resource servervalidates such a token by making a call to the authorisationserver's introspectionendpoint. | The token encodes the entire authorisation in itself and iscryptographically protected against tampering.JSON Web Token(JWT) has become the defacto standard for self-contained tokens. |
Pros / cons of identifier-basedtokens:
| Pros / cons of self-containedtokens:
|
7. The authorisationserver
The authorisation server is responsible for issuing access tokens for protectedresources under itscontrol.
OAuth gives server implementers the freedom to determine how the users getauthenticated and how the actual authorisation is obtained. The Connect2idserver takes full advantage of this freedom and provides aflexible web API to plug inauthentication factors,policies and logic to determine the issue of the tokens and their properties,such asscope.
7.1 Authenticatingusers
An authorisation server may for instance implement a combination of passwordand risk-basedauthentication, where a second factor, such as aFIDO device, is required whenthe client requests an access token for a sensitive resource or high-valuetransaction.
Delegation of the authentication to an external provider is possible, forexample by presenting a choice of popular sociallogins.
After the user is authenticated the server typically creates a session so thatsubsequent requests don't require the user tore-authenticate.
The user can be asked to re-authenticate if the fingerprint of their browserchanges or if the token scope demands greater certainty that the legitimateuser is present. This again is subject to concrete serverpolicy.
7.2Authorisation
As with end-user authentication, the process of authorisation and determiningwhat scope the issued tokens receive is implementationspecific.
Authorisation servers that issue tokens for accessing end-user data and otherresources typically render a consent form where the end-user can decide whichscopes to grant and which not to the requestingapplication.
An authorisation server in a company would consult a policy which takes intoaccount the employee's status and role to determine the token scope, skippingany consent-related interaction. The client's trust level, e.g. internalapplication vs external application, can also be a factor inthis.
7.3 Clientauthentication
OAuth defines two types ofclients, depending on their capability to authenticate securely with theauthorisationserver:
Confidential -- A client with credentials which uniquely identify it withthe server and which are kept confidential from the user and other entities.A web application which executes on a web server can be such aclient.
Public -- A clients without credentials. An application which executes ona mobile device or in a browser (SPA) can be such aclient.
Regardless of their type, all clients get a unique client_id assigned bythe authorisationserver.
Six different methods for authenticating clients have been specified so far andan authorisation server can implement any one ofthem:
Method | Description |
---|---|
client_secret_basic | EssentiallyHTTPbasic authentication with a shared secret. The most widelyimplemented because of its simplicity, but also with the weakestsecurity properties. |
client_secret_post | A variant of basic authentication where the credentials are passedas form parameters instead of in the Authorization header. |
client_secret_jwt | The clientauthenticates with a JSON Web Token (JWT) secured with an HMACusing the client secret as key. Prevents leakage of the secret andlimits the time-window for replay if the request is accidentallysent over unsecured HTTP. |
private_key_jwt | Another JWT-basedauthentication method, but using a private key, such as RSA orEC, which public part is registered with the authorisation server.Private key authentication limits the proliferation of secrets andalso provides a non-repudiation property. |
tls_client_auth | The client authenticates with aclientX.509 certificate issued from a CA authority trusted by theauthorisation server. |
self_signed_tls_client_auth | The client authenticates with aself-signedclient X.509 certificate. Has similar properties as the privatekey JWT method. |
7.4. Authorisation serverendpoints
Core endpoints | Optional endpoints |
---|---|
|
|
7.4.1 Authorisationendpoint
This is the server endpoint where the end-user is authenticatedand authorisation is granted to the requesting client in the authorisationcode and implicit flows (grants). The remaining OAuth 2.0grants don't involve this endpoint, but the tokenenpoint.
This is also the only standard endpoint that serves requests via thefront-channel (the browser) and where users interact with theserver.
7.4.2 Tokenendpoint
The token endpoint lets the client exchange a validgrant, such as a code obtained from the authorisationendpoint, for an accesstoken.
A refresh token may also be issued, to allow the client to obtain a new accesstoken when it expires without having to resubmit a new instance of theoriginal authorisation grant, such as code or the resource owner passwordcredentials. The intent of this is to minimise the amount of end-userinteraction with the authorisation server and thus better the overallexperience.
If the client is confidential it will be required toauthenticate at the tokenendpoint.
7.4.3 Optionalendpoints
Authorisation servers can have these additionalendpoints:
Authorisation servers can have these additionalendpoints:
Server metadata -- JSON documentlisting the server endpoint URLs and its OAuth 2.0 features and capabilities.Clients can use this information to configure their requests to theserver.
Server JWK set -- JSON document with the server's public keys (typicallyRSA or EC) in JSON Web Key (JWK) format. These keys may be used to secureissued JWT-encoded access tokens and otherobjects.
Client registration -- RESTful webAPI for registering clients with the authorisation server. Registration maybe protected (require pre-authorisation) or open (public). The endpoint canbe enhanced to support client read, update and deleteoperations.
Pushed authorisation request (PAR) --enables clients to POST the payload of an authorisation request directly tothe server, the resulting handle can then be used at the authorisationendpoint to complete the request. With PAR clients can beauthenticated upfront (before the user interaction) and the authorisationrequest parameters receive integrity and confidentialityprotection.
Token introspection -- For lettingresource servers validate identifier-based access tokens.May also be used to validate self-contained accesstokens.
Token revocation -- Forletting clients notify the authorisation server that a previously obtainedrefresh or access token is no longer needed. Note this endpoint isn'tintended for revoking access for an end-user or client; that will require acustomAPI.
8.FAQ
8.1 How is OpenID Connect related to OAuth2.0?
OpenID Connect is a concrete protocol for authenticatingusers, devised on top of the OAuth 2.0 framework. As such OpenID Connect isalso often called a profile of OAuth2.0.
Do not use plain OAuth to autenticate users! OpenID Connect is designedspecifically for thispurpose.
OpenID Connect introduces a new token, called ID token,to assert the user's identity and the autheneticationevent.
The access token is still used. It facilitates retrieval of consented profiledetails (called claims or attributes) from the UserInfo endpoint of the OpenIDprovider.
8.2 What other OAuth 2.0 profilesexist?
The community around the OpenID Foundation is developing other concrete profilesbesides OpenID Connect, carefully vetted by experts, to provide token-basedsecurity for a particular industry or applicationdomain:
FAPI -- High-security profile forfinancial-grade applications, used in Open Banking and PSD2implementations.
HEART -- Profile for letting individualscontrol access to their health-relateddata.
MODRNA -- For mobile network operatorsproviding identity services to relyingparties.
EAP -- Security and privacy profileintegrating token binding andFIDO.
iGOV -- For authenticating and sharingconsented data with public sector services across theglobe.