Sample login flow

Important Note! It is NOT recommended to build session management out from scratch. Web development frameworks typically have built-in session management features. Some OIDC libraries include session management. Others allow you to plug in your session library of choice.

The steps below are meant to explain how session management works and the role Hosted Login plays.

There are lots of different ways to implement session management. An example of a secure session management implementation for a web application looks something like this: Login flow diagram | Icons by Font Awesome, see fontawesome.com/license

Good to know: Hosted Login is built on OpenID Connect (OIDC), the leading standard in online identity and authentication. In terms of the OIDC protocol, the user-facing application is the relying party (RP) and Akamai’s Hosted Login is the OIDC provider (OP).

Let’s step through the details:

  1. When an end user loads the application in their browser, it checks for a server-side session. If no session exists, it creates one.

    • When the application creates a session, it generates a unique session ID that is stored in the session and is also placed into a cookie. This way, the application’s client-side can reference the server-side session information when needed.
    Example session content:
    {
        “id”: “iamauniquesessionid12345”,
        “authState”: “unauthenticated"
    }

    This session is owned and maintained by the application. Hosted Login is not yet involved.

  1. The user clicks the application’s login button and the application makes the /login/authorize call to Hosted Login.

    https://v1.api.us.janrain.com/a12bc34d-567e-8f90-gh12-3i45jk678lm9/login/authorize
     	?client_id=12a345b6-c7d8-9e01-f2g3-h4567i890j12
     	&redirect_uri=https://myapp.com/redirect_uri
     	&scope=openid
     	&code_challenge=PWt_2Fz95DnyzxREOAhdFAD95m9HoErGlfOpj3yLC3E
     	&code_challenge_method=S256
     	&response_type=code
     	&claims={"userinfo":{"given_name":null}}
     	&state=Vz8tHF2An2hXJ-aN_-xh0qpB7DtavIjdQivhGmzcX64

    The state and code_challenge values are created by the application before this call is made. The application stores the state token and a code verifier (related to the code_challenge) in the session so they can be referenced later in the process.

    • The state parameter is multi-purpose; It is used for security purposes as we’ll see in the next step, and can also be used for UX purposes to return the user to their intended path after authentication.
    • The code_challenge and code_challenge_method parameters are part of the PKCE protocol, an added layer of security that prevents code interception attacks. For more information, see Authorization Code + PKCE.
    Example session content:
    {
        “id”: “iamauniquesessionid12345”,
        “authState”: “unauthenticated”,
        “loginParams”: {
            “state”: “Vz8tHF2An2hXJ-aN_-xh0qpB7DtavIjdQivhGmzcX64”,
            “code_verifier”: “iamacodeverifier”,
            “post_login_redirect”: “/redirect/location”
        }

    }

    • The user is redirected to the Hosted Login page and completes login. Hosted Login default sign-in screen

      This default Hosted Login screen can be customized to match your application’s look and feel; see Customize screens.

    • Hosted Login redirects back to the app and includes the state token and authorization code in the redirect URL.

      https://myapp.com/redirect_uri
        	?code=U4r9tTEA1y2DVsp9
        	&state=Vz8tHF2An2hXJ-aN_-xh0qpB7DtavIjdQivhGmzcX64
  2. The application validates the state token and makes the /login/token call with the authorization code.

    To validate the state token, the application compares the returned state value to the state value stored in the application session (see note in previous step). If the compared values do not match, this transaction should be rejected.

    curl -X POST \
     https://v1.api.us.janrain.com/a12bc34d-567e-8f90-gh12-3i45jk678lm9/login/token \
     -d 'grant_type=authorization_code' \
     -d 'code=U4r9tTEA1y2DVsp9' \
     -d 'redirect_uri=https://myapp.com/redirect_uri' \
     -d 'client_id=12a345b6-c7d8-9e01-f2g3-h4567i890j12' \
     -d 'code_verifier=RjDD-OPH1KraW8hDHSIHGHkQ9KXX023nZ-VfSYRJUOs'
    • Hosted Login responds with an access_token, refresh_token, and id_token.
      {
        	"access_token": "HnsFZz0ZZuSK26Yx8NcPCqc-3xzBkKgwyw09b9-NdVbEARDn-O1KGlxh3iUE__LL",
        	"refresh_token": "ba69op6soz4wad74qrFHRDsmJJAXnapscoPnH3ccaO9IsUC0Vfc8__xBiA0KtQh3",
        	"expires_in": 3600,
        	"token_type": "Bearer",
        	"scope": "openid",
        	"id_token": "eyJhbGciOiJSUzI1NiIsImtpZCI6IjMwZTYxNWM1ODY3NDkwY2U1ZWQ3NTVkZjJlYWU2ZWQwN2VlNWFjOTciLCJ0eXAiOiJKV1QifQ.eyJhdF9oYXNoIjoiMHBoWjlqOW01dGFFZ1ctZ0NOTTI3dyIsImF1ZCI6WyI4N2Y4NzBjOS1kNGUzLTRjMDUtYThkNS1lNjA5NWMzMzVjOTYiXSwiYXV0aF90aW1lIjoxNjA4MDYxNTA1LCJleHAiOjE2MDgwNjUxMDgsImdsb2JhbF9zdWIiOiJjYXB0dXJlLXYxOi8vZXUtZGV2LmphbnJhaW5jYXB0dXJlLmNvbS90ZXAyZGNxeTRmd3Vyd3Rwa2F4Zzc2dHdnZi91c2VyL2IzMTcxNzVlLWE5OTMtNDExNy1hYjM0LWY3NDEzMDUzNjY3ZiIsImlhdCI6MTYwODA2MTUwOCwiaXNzIjoiaHR0cHM6Ly92MS5hcGkuZXUuamFucmFpbi5jb20vYjE4ZmM4MWQtNDU3ZS00YTQwLWFjODctMmI3OGJkOTQ2ZmEyL2xvZ2luIiwianRpIjoiX3JSSWNDWG91VFhCMHNSVVhGSHZoUWhXIiwic3ViIjoiYjMxNzE3NWUtYTk5My00MTE3LWFiMzQtZjc0MTMwNTM2NjdmIn0.cd3LCH5_rHdhwvKo3GWMiEKVpXsxyBnnVxePYGML2cmro7t-lFhExR_-_IyIYivNXWFhxMIfY0v5FKZ3OfeTYm8itA6VCg6JtwId6N_9T7WSJ6tznd87IO0zM7OdDCW5WNX3s_2P_1yLvtaryvd7mk8HHDR0lfzG-Vmgd6p46-kl4i4wfYylvKySrAmgJSUprmiL-7LZpqlgDLn7dk1CuecxLWUjj3UHXKhcZnliaS2teeh2wux32d8L4Q6ZWZpwV99YtlqFYDbHoUbRQK72hScH7j4cofpPVxbozmsJ7Xmbu0gs4jVNGEuMzR7dHEwPSSFfkpvl70aoRf8eQXNpfg"
      }
  3. The application validates the id_token and can retrieve information from it.

    The id_token is a JSON Web Token (JWT) that must be decoded and validated as part of the authentication process. This step is detailed in the OpenID Connect Core specification. For help decoding and validating a JWT, see jwt.io.

    Decoded id_token:

    {
     	"at_hash": "0phZ9j9m5taEgW-gCNM27w",
     	"aud": [
     		"12a345b6-c7d8-9e01-f2g3-h4567i890j12"
     	],
     	"auth_time": 1608061505,
     	"exp": 1608065108,
     	"global_sub": "capture-v1://us-dev.janraincapture.com/a1bcde2fg3h456ijk7l8mnop9q/user/b317175e-a993-4117-ab34-f7413053667f",
     	"iat": 1608061508,
     	"iss": "https://v1.api.us.janrain.com/a12bc34d-567e-8f90-gh12-3i45jk678lm9/login",
     	"jti": "_rRIcCXouTXB0sRUXFHvhQhW",
     	"sub": "b317175e-a993-4117-ab34-f7413053667f"
     }

    To learn more about the contents of the id_token, see OpenID Connect Token Reference.

  1. The application can also retrieve data by making the /profiles/oidc/userinfo call to Hosted Login, passing in the access_token to authorize the call.

    curl -X GET \
     	https://v1.api.us.janrain.com/a12bc34d-567e-8f90-gh12-3i45jk678lm9/profiles/oidc/userinfo \
     	-H 'Authorization: Bearer HnsFZz0ZZuSK26Yx8NcPCqc-3xzBkKgwyw09b9-NdVbEARDn-O1KGlxh3iUE__LL'

    Example response:

    {
     	"given_name": "Jane",
     	"global_sub": "capture-v1://us-dev.janraincapture.com/a1bcde2fg3h456ijk7l8mnop9q/user/b317175e-a993-4117-ab34-f7413053667f",
     	"sub": "b317175e-a993-4117-ab34-f7413053667f"
     }

    The user profile data available in the id_token or the /userinfo response depends on both:

    • The scopes and claims the application passed into the preceding /login/authorize call
    • The allowedScopes defined in the token policy

    For more information, see OpenID Connect Scopes and Claims.

  2. The application places the access, refresh, and id tokens into its server-side session, along with any user data it needs to make available there.

    • It is a good idea for the application to also rotate the session ID at this time - meaning, replace the original session ID with a new one in both the session and the cookie referencing it. This prevents a malicious actor from recording unauthenticated session IDs and then replaying them after users log in.
    Example session content:
    {
        “id”: “iamauniquesessionid67890”,
        “authState”: “authenticated”,
        “tokens”: {
            “accessToken”: “HnsFZz0ZZuSK26Yx8NcPCqc-3xzBkKgwyw09b9-NdVbEARDn-O1KGlxh3iUE__LL”,
            “refreshToken”: “ba69op6soz4wad74qrFHRDsmJJAXnapscoPnH3ccaO9IsUC0Vfc8__xBiA0KtQh3”,
            “idToken”: “eyJhbGciOiJSUzI1NiIsImtpZCI6IjMwZTYxNWM1ODY3NDkwY2U1ZWQ3NTVkZjJl..."
        },
        “user”: {
            “given_name”: “Jane”,
            “sub”: “b317175e-a993-4117-ab34-f7413053667f”
        }

    }

  3. From here, the application can enhance and personalize the user’s experience as desired. For example:

    • Redirect the user to a specific landing page based on their state, session or profile information
    • Display personalized elements such as the user’s first name and avatar
    • Display options and release content only available to logged-in users

Tip! The OWASP Session Management Cheat Sheet is a great resource for session management best practices, including recommendations for the session ID and cookie.