Author : MD TAREQ HASSAN | Updated : 2020/05/31
What is OAuth2
An open protocol to allow secure authorization in a simple and standard method from web, mobile, and desktop applications.
- OAuth2 is a delegated Authorization protocol (mentioned that it requires authentication as first step)
- OAuth2 is the industry-standard protocol for authorization
- OAuth2 is an open standard for access delegation, commonly used as a way for Internet users to grant websites or applications access to their information on other websites but without giving them the passwords
- OAuth2 is a protocol that allows a user to grant limited access to their resources on one site, to another site, without having to expose their credentials
- Links: dev-handy-sites#web-security
Courtesy: https://tools.ietf.org/html/rfc6749
The OAuth2 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.
OAuth requires Authentication as first step but it does not care about authentication
- All it cares is that it needs access token to access resources
- Uses access token and fetch user data (from Google, Facebook, Azure AD etc.)
How delegated authorization started
In past, if you wanted to see your friends that were already on Yelp or connect with them on Yelp or look at their reviews, what you had to do is you get to a form, choose the provider (email provider like Gmail) and you’d put in your email address and your password. Not your password for Yelp, your password for Gmail on Yelp. This is the state-of-the-art back then.
Same with Facebook at the time. If you wanted to see which of your friends were already on Facebook and you wanted to connect with them, Facebook would read in your contacts from Gmail or Yahoo or Hotmail and they would show you a list of all your contacts that were already on Facebook and give you the opportunity to connect with them.
We can see that this is really bad for a number of reasons. Of course, both Yelp and Facebook promised up and down, we’re just going to read your contacts, we’re not going to store your passwords, we won’t do anything with your contacts other than read them, but in this scenario, when we give our password from one site to another, we’re giving the keys to the kingdom.
And so we started this conversation about delegated authorization because this is really bad.
Terminologies
- Resource Owner: the entity that can grant access to a protected resource. Typically this is the end-user.
- Resource Server: the server hosting the protected resources. This is the API you want to access.
- Client: the app requesting access to a protected resource on behalf of the Resource Owner.
- Authorization Server: the server that authenticates the Resource Owner, and issues Access Tokens after getting proper authorization.
- Channels
- back channel: The back channel is when we have servers that are interacting with each other that are more secured
- front channel: the front channel is anything that passes through your browser URL bar is what we call the front channel. It’s less secure because we have a lot of stuff running in our browsers
OAuth2 Players
Concepts
Endpoints
- RFC6749 defines exactly two endpoints:
- authorization endpoint:
/authorize
- it used Interact with the user to confirm their identity. Therefore, it’s used for any user-facing grant types, such as the authorization code or the implicit flow
- Once a user’s confirmed, or if there isn’t a user involved at all, that’s when we move to the token endpoint
- token endpoint:
/token
- This is where we actually get the tokens themselves.
- If you use client credential or resource owner password flow you’ll skip directly to this
- authorization endpoint:
- Every other endpoint comes through an extension (While this flexibility is great, it also means various OAuth implementations may not be directly compatible)
/introspect
: allows you to analyze and decode a token/revoke
: allows you to invalidate and access a refreshed token/userinfo
: from the OpenID Connect specification, which publishes user profile data/foo
: your own.well-known/oauth-authorization-server
: oauth discovery document (querying to discover capabilities and functionalities)
OAuth2 in a Nutshell
Overview
Protocol flow
(Courtesy: https://openid-foundation-japan.github.io/rfc6749.ja.html)
+--------+ +---------------+
| |--(A)- Authorization Request ->| Resource |
| | | Owner |
| |<-(B)-- Authorization Grant ---| |
| | +---------------+
| |
| | +---------------+
| |--(C)-- Authorization Grant -->| Authorization |
| Client | | Server |
| |<-(D)----- Access Token -------| |
| | +---------------+
| |
| | +---------------+
| |--(E)----- Access Token ------>| Resource |
| | | Server |
| |<-(F)--- Protected Resource ---| |
+--------+ +---------------+
- (A) The client requests authorization from the resource owner. At that time (as shown in the figure), the authorization request can be made directly to the resource owner, but it is desirable to do it indirectly via the authorization server.
- (B) The client receives the authorization grant as a credential that represents the authorization of the resource owner. The authorization grant is issued by one of the four grant types defined in this specification, or by an extended grant type. Whether to use depends on the method of the authorization request used by the client and the grant type supported by the authorization server.
- (C) The client requests an access token by authenticating itself to the authorization server and presenting the authorization grant.
- (D) The authorization server authenticates the client, confirms the validity of the authorization grant, and if the authorization grant is valid, issues an access token.
- (E) The client makes a request to the protected resource of the resource server and authenticates with the issued access token.
- (F) The resource server confirms the validity of the access token and accepts the request if it is valid.
Flow types (grant types)
- Authorization code (front channel + back channel)
- Authorization code w/ PKCE (front channel + back channel)*
- Implicit (front channel only)
- Resource owner password (back channel only)
- Client credentials (back channel only)
Grant types / Flow types exmples:
grant-type=authorization_code
grant-type=password
grant-type=refresh_token
grant-type=client_credentials
Authorization code flow
Authorization Code Grant Type
- Designed for “confidential clients”
- Best for websites with a server back end
- Explicit user & client authentication
Courtesy: that-2019-oauth-and-oidc by dogeared
Authorization code flow example
Authorization Request
https://authserver.example.com/authorize
?response_type=code
&client_id=s6BhdRkqt3
&redirect_uri=https://client.example.com/callback
&state=xyz
&scope=api1 api2.read
Authorization Response
https://client.example.com/callback
?code=SplxlOBeZQQYbYS6WxSbIA
&state=xyz
Token Request
POST /token HTTP/1.1
Host: server.example.com
Content-Type: application/x-www-form-urlencoded
Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW
grant_type=authorization_code
&code=SplxlOBeZQQYbYS6WxSbIA
&redirect_uri=https://client.example.com/cb
&client_id=s6BhdRkqt3&client_secret=gX1fBat3bV
Basic Authentication and OAuth
Basic Authentication Style (RFC 7617): Base64(client_id + ":" + client_secret)
OAuth Style (RFC 6749): Base64(urlformencode(client_id) + ":" + urlformencode(client_secret))
Token Response
HTTP/1.1 200 OK
Content-Type: application/json
{
"access_token": "2YotnFZFEjr1zCsicMWpAA",
"token_type": "Bearer",
"expires_in": 3600,
"scope": "api2.read"
}
Authorization code flow with PKCE
- PKCE ==> pronounced “pixy” is an acronym for Proof Key for Code Exchange
- Courtesy: that-2019-oauth-and-oidc by dogeared
The Client Credentials Grant Type
Used when client application itself is the resource owner
- Designed for client applications who are the resource owner
- Best for machine-to-machine communication
- Requires client authentication
- Benefits:
- Allows backend systems to use OAuth
- no user interaction is needed
- How does it work?
- Client app has id and secret
- Client app send id & secret to authorization-server & server sends back ‘Access Token’
- Client app uses ‘Access Token’ to get protected resource
- Why to use Client Credentials over API Keys: consistency (using delegated authorization to access protected resources)
- Disadvantages:
- client secret is sensitive (~password)
- can not be used by SPA and Native Apps (iOS, Android)
Resource Owner Password Credentials Grant Type
- Designed as a stop-gap for legacy applications
- Negates most of the benefits of OAuth
- Should no longer be used
Refresh Token
- A refresh token is typically a long lived token that could be used by the client application at some point in the future and swapped for new access tokens (and maybe even you refresh tokens). This allows us to reform long running background tasks without the use of being present.
- Refresh tokens are highly confidential. If a refresh token is stolen, there is the potential for the thief to get a new
- It’d access to your APIs, negating the effectiveness of your short lived access tokens. (Ideally, whenever we include the scope in on authorization request, the user should always be prompted to consent to the scope, even if they have previously consented to it in the past)
- The user should also be made aware that refresh tokens are being requested
- Refresh tokens allow the client application to continue to act on the user’s behalf when they are no longer present
- When the client application goes to get tokens (using refresh token), the new refresh token is returned alongside the access token. The current application can then use this access token into the expires.
Playing with OAuth2
See: dev-handy-sites#web-security
Which flow (grant type) do I use?
- Web application w/ server backend: authorization code flow
- Native or mobile app: authorization code with PKCE flow
- JavaScript app (SPA) w/ API backend:
- authorization code with PKCE flow (if you can)
- implicit flow (if you must)
- Microservices and APIs: client credentials flow
Response type
- token
Scopes
- A permission to do something within a protected resource on behalf of the resource owner
- Sapce seperated list of free form text i.e “Scope: profile contacts”
- It has to be in a form that Authorization provider understands
- Naming scopes:
- Simple String:
- prefix: something that clearly identifies the app i.e.
xxx_yyy
,xxx_api
- delimeter:
.
,:
, space - intended usage: read, write, profile etc.
- example:
foo_api.profile
,openid profile
- prefix: something that clearly identifies the app i.e.
- Namespace style:
app.resource.read
app.resource.write
- URL Style (used by Google):
https://api.company.com/resource.read
https://api.company.com/resource.write
- Simple String:
Token types
- Access Token: delegated authorization (intended for OAuth2)
- Refresh Token: to retrive new Token (+ new refresh token) when access token is expired (intended for OAuth2)
- Identity Token: intended for OIDC and used for SSO (always in JWT format)
- Bearer: Authorization provider does not care about who holds the token, any entity has this token can access resource
Note: “Authentication type: basic” means id and password are converted into Base64 string and added in the header of a request
OAuth 2.1
2.0 flows
2.1 flows
Extending OAuth2
Device flow details:
- https://alexbilbie.com/2016/04/oauth-2-device-flow-grant/
- https://auth0.com/docs/flows/concepts/device-auth
RFC 8414 - OAuth discovery document
RFC 8414 is the authorization server metadata specification or more affectionately known as the OAuth discovery document. This allows us to query the authorization server itself, get back a JSON file with its capabilities and related end points, and then configure our applications. We don’t have to guess what’s available, the server will tell us. Once again, that is incredibly powerful.