> ## Documentation Index
> Fetch the complete documentation index at: https://docs.ulm.m1amdocs.com/llms.txt
> Use this file to discover all available pages before exploring further.

# SSO for Web and Mobile Apps without a Back End

If you have or are building a web or mobile application that doesn't have its own separate back end server to manage user session data, configure your client with the **Authorization Code Grant with PKCE** (Proof Key for Code Exchange) flow to obtain tokens from Digital Identity Management.

This flow is similar to **Authorization Code Grant** flow described in the [SSO for Web Apps with a Back End](ssoAppsWithBackEnd) topic. However, since your application does not have a back end, it is not ideal for your UI or app to transmit the client's credentials over a front end channel to obtain an access token, because those credentials are vulnerable to a local attacker. As a best practice, your UI or app shouldn't know the client credentials at all.

In the **Authorization Code Grant with PKCE**, your app generates a cryptographic random string, and computes a hash of this string called the **code challenge**. Your app transmits the hash as part of the initial request to Digital Identity Management's `/oidc/authorize` endpoint, and then transmits the original (un-hashed) string, called the **code verifier**, in the final `/oidc/token` request. Digital Identity Management checks that the verifier hashes to the challenge, to prove that the app making the `/oidc/token` request is the same that made the previous `/oidc/authorize` request.

## Flow Diagram

The diagram below represents the communication flow between the key actors using the **Authorization Code Grant with PKCE**:

<img src="https://mintcdn.com/amdocs-ulm/11Eo_UmnVjqUC-Xl/portal/m1Connect/DIMProductDescription/images/ams_oidcAuthCodeFlowWithPKCE.png?fit=max&auto=format&n=11Eo_UmnVjqUC-Xl&q=85&s=4478a806d09d4001ea50fd1bbc78b618" alt="OIDC Authorization Code Flow with PKCE" width="1100" height="1367" data-path="portal/m1Connect/DIMProductDescription/images/ams_oidcAuthCodeFlowWithPKCE.png" />

## Interaction Steps

The interaction steps between each actor in the flow are as a follows:

1. The user visits or opens your application to access a secured service.

2. Your app determines that the user is not currently signed in.

3. Your app generates and stores a cryptographically random `nonce` ASCII string. This will be used to validate the OIDC response, and must not be guessable by an outside attacker.

4. Your app generates and stores a cryptographically random **verifier** string. The string must consist exclusively of:

   * lowercase and uppercase letters
   * numbers
   * period, underscore, hyphen, or tilde punctuation characters
     To produce the string, we recommend that your application generates at least 32 bytes of random binary data, then encodes it using the base64 URL scheme. Store this for later.

5. Taking the PKCE Verifier string generated in the previous step, your application must compute the SHA-256 hash of the string and base64url-encode it. This value will be used immediately in the OIDC redirect.

6. Your app generates and stores a cryptographically random `state` ASCII string. This will be used to validate the OIDC redirect back to your app, and it must not be guessable by an outside attacker. If your application is web-based, you may store this value in a cookie.

7. Your application redirects the end-user's browser (or in a mobile application, opens a browser window) to Digital Identity Management's `/oidc/authorize` endpoint with the following HTTP GET query parameters:

| Parameter | Description | Sample Value |
| - | - | - |
| `code_challenge` | The PKCE challenge string as generated in step 5. | `onSFASNZXv128912nklsa-ad812` |
| `code_challenge_method` | Value must always be `S256`. | `S256` |
| `scope` | Space-separated list of OAuth 2.0/OIDC scopes to request. | `openid profile email offline_access` |
| `response_type` | Defines the desired response type. Use the value `code` to select Authorization Code Grant Flow. | `code` |
| `client_id` | ID of the relying party. This ID must be registered with the issuer. | `MyApplication-WebUI` |
| `redirect_uri` | Location where the browser should be redirected once the OIDC interaction is complete whether successful or not.The location must have been configured for the relying party. | `https://myapplication/oidc_complete` |
| `state` | ASCII `state` value to help mitigate against CSRF/XSRF.As a best practice, we recommend your app to embed the value in a cookie for later checks. | `AASN12jkasdn21nasDASD9230j2` |
| `nonce` | ASCII `nonce` value to help mitigate against replay attacks.The back end will verify that the generated ID token contains this nonce value. | `DSJF#sdnSF9@#(sdmklsfmkad` |
| `prompt` | Optional parameter. Can be one of the following values: | |
| `none` | If the user is not already signed in to Digital Identity Management, do not prompt them to sign in. Instead, immediately redirect back to the RP with an error code.This can be useful if the application has a special onboard flow separate from Digital Identity Management, or if the application should only be accessed by end users who have already signed in to Digital Identity Management. | `none` |
| `login` | Even if the user is already signed in to Digital Identity Management, treat them as unauthenticated and require that they sign in again.This can be useful if the application in question is considered high-security or sensitive. | `login` |
| `max_age` | Optional parameter. If specified, then the user will be prompted to re-authenticate to Digital Identity Management if the last time they entered their Digital Identity Management credentials exceeds this value in seconds.This is similar to specifying `prompt=login`, but with a time sensitivity. | |

8. The user's browser loads the `oidc/authorize` URL as per the HTTP 302 response from step 7. Digital Identity Management inspects the browser cookies to determine if the user is already authenticated. The next step depends on whether the user is already authenticated in Digital Identity Management.

9. **(Conditional)** If the request is not valid, or if the user is already authenticated and re-authentication is not being forced, then Digital Identity Management immediately responds with an `HTTP 302 Temporary Redirect` to the `redirect_uri` with certain HTTP Query parameters. Skip steps 10 through 12 and go to step 13.

10. **(Conditional)** If the user is not authenticated, then Digital Identity Management redirects them to the configured IdP Portal (that is, the central sign-up/sign-in page for all of your registered RPs).

    | Your Identity App (formerly called IdP Portal UI) |
    | - |
    | Your tenancy on the Digital Identity Management service comes with an out-of-the-box Identity Provider app, known as the **Identity app**, and associated Create ID/Sign-in pages. You can implement and leverage this **Identity app** for onboarding and authenticating your users, or you create and use your own IdP Portal using Digital Identity Management REST API and Processes. |

11. In the most conventional use case, the user authenticates with Digital Identity Management's `POST /sesion/start` API. This API invokes Digital Identity Management's multi-step Authenticate User Process.

    Alternatively, the user may need to first onboard with the Onboard User with Email or Mobile Process, which is invoked by the `POST /proces/start/{processName}` API. This and other variations are not included in the flow diagram.

12. Eventually, whether from a **/session/start** or other Process call, and potentially after several more steps (for example, to satisfy multi-factor authentication rules, if enabled), the user is authenticated. The final HTTP response from Digital Identity Management includes a special `X-Redirect-Location` header with a URL constructed from the `redirect_uri` parameter provided by the RP in step 7. The IdP then redirects the browser to that location.

13. The user's browser loads a URL which Digital Identity Management has constructed from the `redirect_uri` parameter, to which the following HTTP Query parameters will have been added:

    | Parameter | Description |
    | - | - |
    | `code` | The authorization code, if the OIDC request was successful. |
    | `state` | State value as passed in to the `/oidc/authorize` endpoint. The value must be checked against the `state` value **S** stored in a cookie. If there is a mismatch, a cross-site request forgery (CSRF/XSRF) must be suspected and the operation must be aborted. |
    | `error` | The error code, if an error occurred. The following codes are possible: |
    | **Error Code** | **Meaning** |
    | `invalid_request` | The `/oidc/authorize` request was not valid. |
    | `unauthorized_client` | The RP's `client_id` that was specified in the `/oidc/authorize` request does not exist. |
    | `unsupported_response_type` | The `response_type` that was specified in the `/oidc/authorize` request is not valid, or not enabled for this RP. |
    | `invalid_scope` | One or more of the `scope` values that was specified in the `/oidc/authorize` request is not enabled for this relying party. |
    | `server_error` | An error occurred on the Digital Identity Management server. Equivalent to an `HTTP 500` error code. The request may be retried. |
    | `temporarily_unavailable` | The Digital Identity Management server is temporarily unavailable to process the request. Equivalent to an `HTTP 503` error code. The request may be retried. |
    | `interaction_required` | The user must interact with Digital Identity Management to proceed, but the `/oidc/authorize` request specified that no such interaction be allowed (that is, `prompt=none`). |
    | `login_required` | The user must authenticate with Digital Identity Management to proceed, but the `/oidc/authorize` request specified that no such interaction be allowed (that is, `prompt=none`). |
    | `invalid_request_uri` | The specified `request_uri` value is not registered for this RP. |
    | `error_description` | An easily understandable and readable description of the error. |

14. Your app checks the `state` value in the request against the original `state` value stored in a cookie or HTML Web Storage. If there is a mismatch, a cross-site request forgery (CSRF/XSRF) attack is suspected, and the operation must be aborted with an error.

15. Your app makes a background call to Digital Identity Management's `POST /oidc/token` endpoint to redeem the authorization code for OIDC tokens:

    | Name | Value |
    | - | - |
    | `grant_type` | authorization\_code |
    | `code` | The authorization code received from Digital Identity Management in the redirect request (step 13). |
    | `redirect_uri` | The redirect URI as supplied in the initial `/oidc/authorize` request. This value will be used by Digital Identity Management to verify the request against a man-in-the-middle type of attack. |
    | `code_verifier` | The code verifier **V** as generated in step 4. |

    Unlike in the base Authorization Code Flow (as described in the [SSO for Web Apps with a Back End](ssoAppsWithBackEnd) topic), you do not pass any client credentials in the PKCE version of this flow. The body of the request is of type `application/x-www-form-urlencoded`.

16. Digital Identity Management checks that the `code_verifier` supplied in the token request hashes to the `code_challenge` supplied in the authorization request (step7).

17. If all parameters are correct and the Authorization Code is valid, Digital Identity Management replies with a JSON payload that contains the requested token(s). The payload is of type `application/json`, and it consists of a JSON object resembling the following:

    ```
    **oidc/token response - body**
    {
      "access_token": "eyJraWQiOiJyc2ExIiwiYWxnIjoiConnectyNTYifQ.eyJzdWIiOiI0ZmE2ZmZlMS05NmMwLTQ3ODAtYjNkYi1kNTMwY2RjN
                      TJhOGIiLCJhenAiOiJzZW5zaWNhbERldmljZUdyYW50LU9JREMtQ2xpZW50IiwiaXNzIjoiaHR0cHM6XC9cL3NlbnNpY2FsLX
                      VsbS1wZHQubTFhbWRvY3MuaW9cL29pZGMiLCJleHAiOjE2MTANzE4NzksImlhdCI6MTYxMDQ2ODI4MCwianRpIjoiMGVhNzhm
                      YTktMTIwMS00YmQzLTlkODYtZGU0ZGM5ZTU0ZDQ5In0.TiSh4oiT2xERbFtkQI09oMOBw4QvOdFt11fE8kh-yVxWISjPHj_V-
                      m9QxYCj_1AKrIHBJW1eZw5qyI4xqlNil0ax7RWEuEYqhBOTNQDSzfquERRLKgA1SsmleiO-ps1fXjo0ODmGTDQuJKKKhvgdPy
                      AIYirr8bBW_GNRsi4LJa8LM6yjC9-q9k79-WKNI3OgLy5T4Y-kObN236g0eXAyaSUZ4Ly1pJmUilRJnkI4KNyzqURz7_0awV6
                      k13J1aQnxUIJ5IQhEp0_3Xtq4l8b-rck0X8zXvjwyr7xUAAB6-lGEb2J7bvZEFcvGbn6ss25l1ceZeLLEFXtp9o3ZinyOYA", 
      "token_type": "Bearer", 
      "expires_in": 3599, 
      "scope": "email openid profile", 
      "id_token": "eyJraWQiOiJyc2ExIiwiYWxnIjoiConnectyNTYifQ.eyJzdWIiOiI0ZmE2ZmZlMS05NmMwLTQ3ODAtYjNkYi1kNTMwY2RjNTJhO
                  GIiLCJhdWQiOiJzZW5zaWNhbERldmljZUdyYW50LU9JREMtQ2xpZW50IiwiZW1haWxfdmVyaWZpZWQiOnRydWUsImtpZCI6InJzYT
                  EiLCJpc3MiOiJodHRwczpcL1wvc2Vuc2ljYWwtdWxtLXBkdC5tMWFtZG9jcy5pb1wvb2lkYyIsIm5hbWUiOiJQcmltYXJ5IFVzZXI
                  gRGlzcGxheSBOYW1lIEhlcmUiLCJ1bG1fdXNlcl9pZCI6MTAzLCJleHAiOjE2MTA0Njg4ODAsImlhdCI6MTYxMDQ2ODI4MCwianRp
                  IjoiYWMzOTUxY2YtZTlhZC00MjBmLTk3OGYtYmJiOGU2Y2YzZTViIiwiZW1haWwiOiJ0Z29rY2VuMjAyMTAxMTJAbWFpbGluYXRvc
                  i5jb20ifQ.Hp0fDfODZ08F25HRYZmzImb-mH7-IsPHNLmWN6L7IfM791z7qDBpVRPT1SIKD875rGG88xBGbD0QgiPqnnUmz3xz0zy
                  cokk8pmwzFYGyo2LE0ySeL4K-N2iUv4LUieDCE323KvHxKZV2QsazHivaTKGJ1aCy6dv_90LMf0Mv0_pAD3Zyd8eaM2Plt8zUe-Tt
                  YQ-ojxrseD6lw2v1YJJpU8h1jtDKjFGLiMGUwDrV7bcUEsVZEOBZ_y1AbfhahbADnttrmN2Kifw9HeeFkGxVkwfFuswNvBx0F0nvL
                  PHkWqbOLdotGlQrn6fhFoW1Ibg_PUWNz3ZCXS5uO6r-cpxTWQ" 
    }
    ```

    The fields of this JSON object are as follows:

| Field | Description |
| - | - |
| `access_token` | The access token, a JSON Web Token (JWT). |
| `token_type` | Value is always `Bearer`. |
| `expires_in` | The lifetime in seconds of the access token. After this point, the access token must be refreshed (if possible) to continue treating the user as authenticated. |
| `scope` | The scopes granted by the access token. This may not always be the scopes requested; some scopes may have been denied. |
| `id_token` | The ID token, a JSON Web Token (JWT). |
| `refresh_token` | The refresh token, a JSON Web Token (JWT). |

18. Your app decodes the ID token, and inspects the payload to make sure the `nonce` key is present and its value matches the `nonce` value **N** from the original request (generated in step 3). If not, a replay attack is suspected and the operation must be aborted with an error.
19. Your app stores the tokens in an appropriate place (for example, cookies or HTML5 Web Storage for a web UI, or device storage for a mobile app).
20. As long as the access token remains valid, the user remains authenticated. For more details on how to refresh (that is, get replacement) a token, refer to the [Refreshing Tokens](refreshingTokens) topic.

**Parent topic:**[Using Digital Identity Management for Single Sign-On](../topics/useM1ConnectForSSO)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.