Skip to content

Web Authentication and Authorization

Introduction

A good resource is here.

Original Diagram

Basic Authentication

Info

  • Involves sending a username and password with each request, but can be less secure without encryption.
  • Suitable for simple applications where security and encryption aren’t the primary concern or when used over secured connections.
sequenceDiagram
    participant Client
    participant Server
    Client->>Server: 1. Requests Resource
    Server->>Client: 2. Requests username/password
    Client->>Server: 3. Sends username/password
    Server->>Client: 4. Returns Resource

Token Authentication

Info

  • Uses generated tokens, like JSON Web Tokens (JWT), exchanged between client and server, offering enhanced security without sending login credentials with each request.
  • Ideal for more secure and scalable systems, especially when avoiding sending login credentials with each request is a priority.
sequenceDiagram
    participant Client
    participant Server
    Client->>Server: 1. User logs in
    Server->>Client: 2. Sends encrypted token
    Client->>Server: 3. Sends Auth request with token
    Server->>Client: 4. Returns Resource

Types of Tokens

  • Access Tokens
  • Refresh Tokens

Access tokens are used to grant access to a protected resource. When a client first authenticates it is given both types of tokens, but the access token is set to expire after a short period.

Refresh tokens are used to obtain a new access token when the current access token becomes invalid or expires, or to obtain additional access tokens with an identical or narrower scope. It does not need the credential information again. The refresh token is also valid for some duration, but it is much more than an access token.

JWT - JSON Web Token

Info

A JSON Web Token (JWT) is a standard that defines a safe, compact, and self-contained way of transmitting information between a client and a server in the form of a JSON object. A JWT can either be signed (JWS) or encrypted (JWE) or both. If a JWT is neither signed nor encrypted, then it is called an insecure JWT.

JWT structure

A JSON Web Token is basically three base64-encoded strings separated by a . (dot)

HEADER.PAYLOAD.SIGNATURE

1. Header

This is the first part of JWT. It is also known as the JOSE header (JSON Object Signing and Encryption). This header describes what algorithm is used to sign or encrypt the data contained in the JWT.

The header defines two attributes:

  • alg: the algorithm used to sign or encrypt the JWT.
  • typ: the content that is being signed or encrypted.

The header JSON looks like as shown below.

{
  "alg": "HS256",
  "typ": "JWT"
}
Now when we encode it to base64encode, we get the first part of our JSON web token eyJhbGciOiAiSFMyNTYiLCAidHlwIjogIkpXVCJ9.

2. Payload

This is the second part of JWT. It contains the main information that the server uses to identify the user and permissions. The payload consists of claims. Claims are statements about an entity (typically the user) and additional data.

There are three types of claims.

2.1. Registered Claim Names

These are reserved names that provide a starting point for a set of useful, interoperable claims.

  • iss: identifies the principal that issued the JWT.
  • sub: identifies the principal that is the subject of the JWT.
  • aud: identifies the recipients that the JWT is intended for.
  • exp: identifies the expiration time at or after which the JWT MUST NOT be accepted for processing.
  • nbf: identifies the time before which the JWT MUST NOT be accepted for processing.
  • iat: identifies the time at which the JWT was issued.
  • jti: The JWT ID is a unique identifier for the JWT.

2.2. Public Claim Names

Public claim names are JSON Web Token Claims that can be defined at will by those using JWTs. However, in order to prevent collisions, any new claim name SHOULD either be defined in the IANA Registry, JSON Web Token Claims Registry, or be defined as a URI that contains a collision resistant namespace.

2.3. Private Claim Names

A producer and consumer of a JWT may agree to any Private claim name that is not a Reserved claim name or a Public claim name. Unlike Public claim names, these Private claim names are subject to collision and should be used with caution.

3. Signature

The third and final part of JWT is the signature. It is created by combining the header and payload parts of JWT and then hashing them using a secret key.

Full example from jwt.io Original Diagram

OAuth Authentication

Info

  • Enables third-party limited access to user resources without revealing credentials by issuing access tokens after user authentication.
  • Ideal for scenarios requiring controlled access to user resources by third-party applications or services.
sequenceDiagram
    participant Client as Application (Client)
    participant User as Resource Owner (User)
    participant AuthServer as Authorization Server
    participant ResourceServer as Resource Server
    Client->>User: 1. Authorization request
    User->>Client: 2. Authorization grant
    Client->>AuthServer: 3. Authorization grant
    AuthServer->>Client: 4. Access token
    Client->>ResourceServer: 5. Access token
    ResourceServer->>Client: 6. Returns Resource

Here is a more detailed explanation of the steps in the diagram:

  1. The application requests authorization to access service resources from the user.
  2. If the user authorized the request, the application receives an authorization grant (a credential representing the resource owner’s authorization to access its protected resources
  3. The application requests an access token from the authorization server (API) by presenting authentication of its own identity, and the authorization grant.
  4. If the application identity is authenticated and the authorization grant is valid, the authorization server (API) issues an access token to the application. Authorization is complete.
  5. The application requests the resource from the resource server (API) and presents the access token for authentication.
  6. If the access token is valid, the resource server (API) serves the resource to the application.

Grant Types

Info

Grant type refers to the way an application gets an access token. Each grant type is optimized for a particular use, whether that’s a web app, a native app, a device without the ability to launch a web browser, or server-to-server applications.

Some good resource regarding different grant types are here and here.

1. Authorization Code Grant Type

Note

The Authorization Code grant type is the most commonly used OAuth 2.0 grant type. It is used by both web apps and native apps to get an access token from the authorization server once the user has authorized. The Authorization Code flow is most suitable for websites and mobile apps that have a backend.

This type has the extra step of exchanging the authorization code for the access token. The exchange of authorization code for the access token takes place in the back channel. Due to this feature, it provides an additional layer of security.

Here is the high-level overview of the Authorization Code flow:

  1. The user clicks on a link or button on a web page that requests access to a resource.
  2. The user is redirected to the Authorization Server, where they authenticate themselves and grant permission to the requesting application.
  3. The Authorization Server generates an authorization code and redirects the user back to the requesting application with the authorization code.
  4. The requesting application exchanges the authorization code for an access token that can be used to access the protected resource.
    sequenceDiagram
        participant User
        participant Client as Client (App)
        participant AuthServer as Authorization Server
        participant ResourceServer as Resource Server
    
        User->>Client: 1. User click "Login with OAuth2"
        Client ->> AuthServer: 2. Redirect to /authorize
        Note over Client,AuthServer: GET /authorize?<br/>response_type=code<br/>&client_id=12345<br/>&redirect_uri=https://client.dummy.com/callback<br/>&scope=images_read<br/>&state=abcde
        AuthServer->>User: 3. Prompt for login and consent
        User->>AuthServer: 4. Enter credentials and consent
        AuthServer->>Client: 5. Redirect to client callback URL with code
        Note over AuthServer,Client: GET /callback?<br/>code=hhdf6hsbhjG66hgtgfGGHJGCHJ<br/>&state=abcde
        Client->>AuthServer: 6. Exchange code (+ client_secret) for token
        Note over Client,AuthServer: POST /token<br/>grant_type=authorization_code<br/>code=hhdf6hsbhjG66hgtgfGGHJGCHJ<br/>client_id=12345<br/>client_secret=gh5Gdkj743HFG45udbfGfs
        AuthServer->>Client: 7. Return Access Token (+ Optional Refresh Token)
        Note over AuthServer,Client: HTTP 200 OK<br/>{<br/>"access_token": "YT3774ghsghdj6t4GJT5hd",<br/>"token_type": "bearer",<br/>"expires_in": 3600,<br/>"refresh_token": "YT768475hjsdbhdgby6434hdh",<br/>"scope": "images_read"<br/>}
        Client->>ResourceServer: 8. Request with Access Token
        ResourceServer->>Client: 9. Protected Resource

Step 1: Get the user's permission

The user clicks on a link or button on a web page that requests access to a resource. The requesting application sends a request to the Authorization Server with the following parameters:

  • response_type=code: indicating the Authorization Code flow.
  • client_id=12345: the Client's unique identifier.
  • redirect_uri: The URI where the authorization server redirect to once it has finished interacting with the resource owner.
  • scope=images_read: The level of access being requested.
  • state=abcde: The application generates a random string and includes it in the request. It should then check that the same value is returned after the user authorizes the app. This is used to prevent CSRF attacks.

Step 2: Redirect to the Authorization Server

The user is redirected to the Authorization Server, where they authenticate themselves and grant permission to the requesting application. The Authorization Server could ask the user to log in or prompt them to authorize the access request.

Step 3: Redirect back to the app

If the user grants permission, the Authorization Server generates an authorization code and redirects the user back to the requesting application with the authorization code. The response includes:

  • code=hhdf6hsbhjG66hgtgfGGHJGCHJ (the authorization code)
  • state=abcde (the same state value sent in step 1, for verification)

Step 4: Exchange code for token

The requesting application exchanges the authorization code for an access token that can be used to access the protected resource. The requesting application sends a POST request to the Authorization Server with the following parameters:

  • grant_type: The value of this parameter should be set to authorization_code to indicate that the authorization code will be exchanged for an access token.
  • client_id: The ID of the client that is making the request.
  • client_secret: The client secret that is used to authenticate the client.
  • code: The authorization code that was received in the previous step.
  • redirect_uri: The URL where the Authorization Server redirected the user after they granted permission.

The Authorization Server validates the request and responds with an access token and a refresh token (if enabled). The requesting application can use the access token to access the protected resource.

2. Implicit Grant Type

Note

The Implicit grant type is designed for single-page JavaScript apps that do not have a backend and have no way to store client secrets. Storing the client secret in the JavaScript code is not as safe, because anyone can access it. Therefore, we use the Implicit flow for these apps.

In Implicit flow, the authorization server directly returns the access token instead of returning the code. This flow type should be used only if there is no alternative option because it is not safe. The exchange of token happens at the front end and an attacker can access the token.

sequenceDiagram
    participant Client
    participant User
    participant AuthServer as Authorization Server
    participant ResourceServer as Resource Server

    Client->>User: 1. Authorization Request
    User->>AuthServer: 2. Authorize Client
    AuthServer->>User: 3. Access Token
    User->>Client: 4. Access Token
    Client->>ResourceServer: 5. Request with Access Token
    ResourceServer->>Client: 6. Protected Resource

3. Client Credentials Grant Type

Note

This grant type is used for machine to machine authorization. There is no user involved in this flow. Suppose we have an application that follows the microservices architecture. The application is divided into small parts and each part is deployed on a separate server.

If one internal server needs to access some data from the other server, then they can use the client credentials grant type.

sequenceDiagram
    participant Client
    participant AuthServer as Authorization Server
    participant ResourceServer as Resource Server

    Client->>AuthServer: 1. Client Credentials
    AuthServer->>Client: 2. Access Token
    Client->>ResourceServer: 3. Request with Access Token
    ResourceServer->>Client: 4. Protected Resource

4. Resource Owner Password Credentials Grant Type

Note

The Resource Owner password credentials grant type is used in cases where the resource owner trusts the client and is ready to share its credentials with the client. The authorization server should take special care when enabling this grant type and only allow it when other flows are not viable.

This flow was introduced to migrate existing clients using direct authentication schemes such as HTTP Basic or Digest authentication to OAuth by converting the stored credentials to an access token. Today, there is no case in which this flow should be used, as it is very insecure.

sequenceDiagram
    participant Client
    participant AuthServer as Authorization Server
    participant ResourceServer as Resource Server

    Client->>AuthServer: 1. Resource Owner Credentials + Client Credentials
    AuthServer->>Client: 2. Access Token (+ Optional Refresh Token)
    Client->>ResourceServer: 3. Request with Access Token
    ResourceServer->>Client: 4. Protected Resource

API Key Authentication

Info

  • Assigns unique keys to users or applications, sent in headers or parameters; while simple, it might lack the security features of token-based or OAuth methods.
  • Convenient for straightforward access control in less sensitive environments or for granting access to certain functionalities without the need for user-specific permissions.