OAuth - TairinySimeonato/WebAuditing GitHub Wiki

What is OAuth?

  • OAuth is an authorization protocol that allows a user’s account information to be used by a third-party service, such as Facebook or Google, without the user typing the password.
  • OAuth provides an access token that allows some user information to be shared with the service. This data can be username, date of birth and profile picture, for example.
  • OAuth uses access tokens to authorize users to access resources.
  • When a user logs in the application using their Google account, the Google authorization server will issue an access token to that website after the user agrees to log in using OAuth.
  • The web application can access some user information hosted in the resource server. The resource server can be the one hosting your photos, contacts list, Gmail inbox, calendar, etc.
  • Because any application can access some user data (some sensitive data too), the Authorization Server needs to give the application an access token beforehand.
  • OAuth can also be used for authentication, however it needs to be carefully implemented, since it can be very easy to commit mistakes.

OAuth Roles

OAuth has 4 different roles:

  • Authorization Server – the server that authorizes user information to be shared with a 3rd party application (client). Responsible to issue access token to the client. Example: Google
  • Resource Server – server that hosts protected resources. Example: Gmail
  • Resource Owner – User that agrees to have their resources accessed in order to gain authorization to a client
  • Client – 3rd party application that requests access to a resource server

OAuth Tokens

  • The resource server needs a token from the client application in order to allow the client to access user resources.

  • The authorization server is responsible to issue this token as a random string.

  • There are two types of tokens: access tokens and refresh tokens:

  • Access tokens: This token allows a 3rd party application to access user data on a resource server. This is sent by the client (3rd party app) either as a URL parameter or a HTTP request header to the resource server. This token should have an expiration date and should not be leaked. This token can be used to limit the scope of what the client can access. The user should be warned of what permissions an application is request and the user will decide if they can proceed or not. Access tokens are used by applications to make API requests in behalf of a user. It basically represents the power an application has in accessing user information. This value should be confidential both in transit and storage. Only the client, authorization server, and the resource server should have access to the access token. The token should be only used over HTTPS communication. The access token should be short lived and refresh tokens should be long lived.

  • Refresh tokens : This token is issued with the access token, but it is not sent in every request. This token Is used when an access token expires so the session can keep alive. The lifetime of this token is longer than the access token. This refresh token is used to generate a new access token. A user needs a refresh token when the user accesses a resource for the first time, or the previous access token got expired. They should not be leaked, and they can be revoked by the authorization server. Implicit grant flow can’t use a refresh token (we’ll talk about this later). A single page app should never receive a refresh token, because usually single page apps use the implicit grant flow.

OAuth Grant Types

  • There are 5 different grant types:
  1. Authorization code flow
  2. Implicit flow
  3. Client credentials flow
  4. Resource owner password credentials flow
  5. Refresh token flow

Authorization Code Grant Flow

  • The authorization code is a temporary code that the client (3rd party app) exchanges for an access token. The authorization server is responsible for giving the code and the user will be prompted with what information is being requested by the client, and they can allow or block the request. When a user authorizes a certain client to access their information, they are redirected back to the client with a code in the URL. The client then changes the code to an access token. During the request for an access token, the request is authenticated with the client secret. This decreases the risk of a malicious attacker to intercept the authorization code and use it in their behalf. The users will never see the access tokens, so this is the safest way to return the token to the client.It is recommended that all clients use the PKCE (Proof Key for Code Exchange) extension with this flow as well to provide better security.

See the detailed steps below:

1) Authorization code link

Firstly, the user is given an authorization link that looks like this:

https://authorization-server.com/oauth/authorize
?client_id=a33c21ed
&response_type=code
&state=58975bd30
&redirect_uri=https%3A%2F%2Fexample-app.com%2Fauth

where:

  • https://authorization-server.com/v1/oauth/authorize : is the API authorization endpoint
  • client_id : application identifier. When a developer register the application, a client_id is received from the authorization server
  • response_type=code: the value 'code' indicates that you want an authorization code as the response
  • state: this parameter is recommended and has two purposes. It works as a session key by including the state parameter in the redirect and persisting data between auth server and the user and also protects against CSRF attacks. When the user is redirected back to the application the state parameter should match the original value, this way an attacker won't be able to intercept the traffic.
  • redirect_url: this is an optional parameter, however is highly recommended. This is the URL where you want the user to be redirected after the authorization is complete. This must match the redirect URL that you have previously registered with the auth server.

2) User Authorizes Application

When the user clicks the link, they need to log in in the resource server to authenticate their identity. The user can auhthorize or deny the client to access their account. The server will let the user know what permissions the client is requesting. In the example above, Quora is asking permission for viewing email addresses, profile info and managing contacts from zgrossbart gmail account. If the user approves the request, they will be redirected back to the app along with the auth code and state parameters.

3) The service redirects the user back to the client and the client receives the authorization code

The service redirects the user back to the client that made the request. The redirect will include a “code”, which is the authorization code in the URL and the original “state” value.

https://example-app.com/cb?code=Yzk5ZDczMzRlNDEwY&state=5ca75bd30

4) The client changes the authorization code for an access token

The application requests an access token from the resource server, by inserting the authorization code with authentication details to the API token endpoint. The client uses the authorization code to get an access token by making a POST request to the authorization server, as seen below:

POST /oauth/token HTTP/1.1
Host: authorization-server.com
 
code=Yzk5ZDczMzRlNDEwY
&grant_type=code
&redirect_uri=https://example-app.com/cb
&client_id=mRkZGFjM
&client_secret=ZGVmMjMz

The authorization server will respond with:

{
  "access_token": "AYjcyMzY3ZDhiNmJkNTY",
  "refresh_token": "RjY2NjM5NzA2OWJjuE7c",
  "token_type": "bearer",
  "expires": 3600
}

Now the application is authorized to use user's information, limited to the scope of access. It may use the token to access the user’s account via the service API until the token expires or is revoked. If a refresh token was issued, it may be used to request new access tokens if the original token has expired.

When to use the Authorization Code flow? This flow is best used in web and mobile applications. This flow provides an extra step of exchanging the auth code for an access token as an extra security layer, unlike the implicit flow, which doesn't have this feature. The authorization code flow should be used with a PKCE extension. Whithout the PKCE, the application is susceptible to authorization code interception attacks.

Implicit grant flow

  • used best for single page apps (SPA)
  • SPAs are Web apps that load a single HTML page and dynamically update that page as the user interacts with the app
  • In this flow, there is no code exchange and the access token is returned to the client immediately
  • SPas are unable to securely store information such as the client secret.
  • The issued tokens are short lived and refresh tokens are not available in this flow
  • Implicit flows are rarely necessary in real life, since SPAs can also use the authoritization code flow
  • For a SPA to use the authorization code flow, it needs to make a POST request to the auth server. If the auth server is in a different domain, the server will need to set CORS to attend this situation. If the CORS does not allow it, then the client can use the implicit flow
  • The state parameter must be used and the redirect URL needs to be restricted to trusted clients.
  • The Implicit Grant flow starts out by creating a link and directing the user’s browser to that URL.
  • The flow has the following steps:
    • The application opens a browser to send the user to the OAuth server
    • The user sees the authorization prompt and approves the app’s request
    • The user is redirected back to the application with an access token in the URL fragment

Client credentials flow

  • Used when applications request an access token to access their own resources, not for a user.
  • The client can request an access token using only its client credentials (or other supported means of authentication) when the client is requesting access to the protected resources under its control
  • The client credentials grant type MUST only be used by confidential clients.
  • The following steps are the following:
    • Get the client id: Each application is assigned a unique Client ID (also known as Consumer key or API key) and Client Secret.
    • Generate an access token via POST request and the response will return an access token
POST /oauth/v2/accessToken HTTP/1.1
Host: www.linkedin.com
Content-Type: application/x-www-form-urlencoded

grant_type=client_credentials&client_id={your_client_id}&client_secret={your_client_secret}
* make API requests including an Authorization header with your token
  • The following parameters are included in the request:
    • grant_type: required parameter. The value must be set to "client_credentials"
    • scope: optional.
    • client authentication: required. This is divided in "client_id" and "client_secret" parameters or these values can be located in the HTTP basic auth header.

Resource owner password credentials flow

  • This flow allows exchanging the username and password of a user for an access token and, optionally, a refresh token.
  • This flow has significantly different security properties the user’s password is accessible to the application. This requires strong trust of the application by the user.
  • It is recommended only for first-party “official” applications released by the API provider

Step by step

  • Ask the user for their credentials
  • Exchange the credentials for an access token by performing a POST request to the auth server containing the following parameters:
    • grant_type="password"
    • scope : optional
    • client_id : optional
    • client_secret
    • username
    • password
  • Call the API

Refresh token flow

  • A client application presents a refresh token to a token endpoint and gets a new access token.
  • to obtain a new access token, the client will perform a POST request to the authorization server with the following parameters:
    • grant_type=refresh_token
    • refresh_token=xxxxxxxxxxx
    • client_id=xxxxxxxxxx
    • client_secret=xxxxxxxxxx

References