Dev tutorials

10 mins read

Integrate Sign In Pages for Passwordless Authentication

Sign In Pages can be integrated with Cloudentity for passwordless authentcation of users stored in Identity Pools. To integrate your login page, you can use either the authorization code flow or the resource owner password credentials flow.

Prerequisites

Generate Authentication Codes

For authentication using Magic Links or Verification Codes, you need to be able to generate authentication codes using Cloudentity Generate Code of Specific Type API.

  1. Call the Cloudentity OAuth 2.0 Token Endpoint for the client application you connected to the System Workspace of your tenant.

    You need a token with the identity_self_registration scope.

    Sample CURL request:

    curl -X POST https://$TENANT_ID.$REGION_ID.authz.cloudentity.io/$TENANT_ID/system/oauth2/token \
    --header "Content-Type: application/x-www-form-urlencoded" \
    --data-raw "grant_type=client_credentials&client_id=$CLIENT_ID&client_secret=$CLIENT_SECRET&scope=identity_self_registration"
    
  2. Call the Generate Code of Specific Type API requesting a code of authentication type.

    Sample request:

    curl -k -X POST https://$TENANT_ID.$REGION_ID.authz.cloudentity.io/api/identity/$TENANT_ID/system/pools/$IDENTITY_POOL_ID/user/code/generate \
    --header "Authorization: Bearer $AT" \
    --data '{
    "address": "johndoe@example.com",
    "type": "authentication"
    }'
    

    See that the request contains the identifier of the Identity Pool the user for whom you are generating the code is registered within. You also provide this user’s email address to indicate for who do you generate the authentication code.

    Sample response:

    {"extended_code":"NjgzM2I5Yjk5MDg3NDBiMmIxYzY4NjA4MDU0YzE0Nzc6NDY1NTkzMjQ","code":"46559324"}
    

User Authentication in Authorization Code Flow

Login pages that integrate with Cloudentity can use the OAuth authorization code flow with passwordless authentication. When this method is used, client registered with Cloudentity can provide the user with an authentication OTP either used as a verification code or as part of a Magic Link.. When the client starts the authorization flow on behalf of the user, it passes the OTP in the authentication_code parameter in a request to the /authorize endpoint, which is a sign for Cloudentity to skip user authentication in the flow.

For the authorization code flow, we strongly advise choosing Magic Links for authentication rather than authenticating users with verification codes. The latter can be still used for custom authentication flows, but, in general, is considered less user friendly.

When client apps generate authentication codes, they receive a code and an extended_code. The code length can be configured, but it is a plain text. The extended_code is a URL-safe base64-encoded user identifier and the verification code. Extended codes make it possible for Cloudentity to know for which users the authorization flow happens - since, unlike in ROPC flow, there is no username present in the /authorize request. Because of that, Cloudentity expects the extended code as a value of the authentication_code parameter when clients request authorization. Making the user type in an extended code can be considered not optimal in terms of the user experience - therefore, it is much better to add the extended code to a link and use the Magic Links authentication.

[mermaid-begin]
sequenceDiagram autoNumber participant User participant Client application participant Cloudentity participant Resource server (API) User->>Client application: Request Code Client application->>Cloudentity: /user/code/generate Cloudentity->>Client application: code + extended_code Client application->>User: Magic Link with extended_code as part of the URL User->>Client application: Select provided Magic Link Client application->>Cloudentity: /oauth2/authorize with query parameter authentication_code=extended_code Cloudentity->>Cloudentity: Verify code Cloudentity->>User: Redirect to consent page User->>Cloudentity: Consent Cloudentity->>User: Redirect user to callback URL with authorization code provided as part of the callback URL
  1. The user provides their email/username in your custom login page and selects the Request Code button.

  2. The client application of your sign in page, sends a request to the Cloudentity Generate Code Of Specific Type API.

    The request must contain the type query parameter set to authentication.

    Learn more.

  3. Cloudentity provides the code and extended_code parameters in the request response.

  4. The sign in page must now provide the user with an URL that contains the extended_code as its query parameter over the email/text message.

  5. User selects the link.

  6. Sign in page’s client application sends a request to the Cloudentity OAuth 2.0 Authorize Endpoint.

    The request must contain the authentication_code parameter with the value set to the value of the extended_code parameter the client received in the third step as a response the Generate Code Of Specific Type API call. You use the extended code as it is tied to this particular user trying to authenticate and there is no user identifier provided as part of the request to the /authorize API.

    Example request:

    curl --location \
    --get \
    --url "https://$TENANT_ID.$REGION_ID.authz.cloudentity.io/$TENANT_ID/$WORKSPACE_ID/oauth2/authorize" \
    --data-urlencode "response_type=code" \
    --data-urlencode "client_id=$CLIENT_ID" \
    --data-urlencode "authentication_code=$extended_code"
    
  7. Cloudentity verifies the code and skips usual user authentication that takes place when clients call the /authorize endpoint.

  8. The user is redirected to the consent page.

  9. The user provides their consent.

  10. Cloudentity redirects the user to the callback URL registered for the client application and provides the authorization code as part of the URL.

The client application may now request tokens from Cloudentity on behalf of the user and access the resources if the token is granted.

Verification Code Authentication in Authorization Code Flow

[mermaid-begin]
sequenceDiagram autoNumber participant User participant Client application participant Cloudentity participant Resource server (API) User->>Client application: Request Code Client application->>Cloudentity: /user/code/generate Cloudentity->>Client application: code + extended_code Client application->>User: Verification Code in email/text message Note over User, Client application: The verification code can be set
to the code provided as the response
to code generation request. User->>Client application: Verification Code on sign in page Client application->>Cloudentity: /oauth2/authorize with query parameter authentication_code=extended_code Cloudentity->>Cloudentity: Verify code Cloudentity->>User: Redirect to consent page User->>Cloudentity: Consent Cloudentity->>User: Redirect user to callback URL with authorization code provided as part of the callback URL
  1. The user provides their email in your custom login page and selects the Request Code button.

  2. The client application of your sign in page, sends a request to the Cloudentity Generate Code Of Specific Type API.

    The request must contain the type query parameter set to authentication.

    Learn more.

  3. Cloudentity provides the code and extended_code parameters in the request response.

  4. The sign in page must now provide the user with the value of the code parameter over the email/text message.

  5. User enters their verification code on the sign in page.

  6. Sign in page’s client application sends a request to the Cloudentity OAuth 2.0 Authorize Endpoint.

    The request must contain the authentication_code parameter with the value set to the value of the extended_code parameter the client received in the third step as a response the Generate Code Of Specific Type API call. You use the extended code as it is tied to this particular user trying to authenticate.

    Sample call to the authorize endpoint with Cloudentity as an authorization server including authentication code

    curl --location \
    --get \
    --url "https://$TENANT_ID.$REGION_ID.authz.cloudentity.io/$TENANT_ID/$WORKSPACE_ID/oauth2/authorize" \
    --data-urlencode "response_type=code" \
    --data-urlencode "client_id=$CLIENT_ID" \
    --data-urlencode "authentication_code=$extended_code"
    
  7. Cloudentity verifies the code and skips usual user authentication that takes place when clients call the /authorize endpoint.

  8. The user is redirected to the consent page.

  9. The user provides their consent.

  10. Cloudentity redirects the user to the callback URL registered for the client application and provides the authorization code as part of the URL.

The client application may now request tokens from Cloudentity on behalf of the user and access the resources if the token is granted.

User Authentication in Resource Owner Password Credentials (ROPC) Flow

Login pages that integrate with Cloudentity can use the Resource Owner Password Credentials Flow with passwordless authentication. When this method is used, client registered with Cloudentity can provide the user with an authentication OTP either used as a verification code or as part of a Magic Link. Either after the user selects a magic link or after the user provides their code,the client provides it as a part of the call to the OAuth 2.0 Token Endpoint.

Remember

Please, note that, in general, the ROPC flow is considered less secure than Authorization Code Flow and should be used only by trusted applications.

Verification Code Authentication in ROPC Flow

[mermaid-begin]
sequenceDiagram participant User participant Client application participant Cloudentity participant Resource server (API) User->>Client application: Request Code Client application->>Cloudentity: /user/code/generate Cloudentity->>Client application: code + extended_code Client application->>User: Verification Code in email/text message Note over User, Client application: The verification code can be set
to the code provided as the response
to code generation request. User->>Client application: Verification Code on sign in page alt code as plain text Client application->>Cloudentity: /oauth2/token + grant_type=password + password=$code + username else extended code + username Client application->>Cloudentity: /oauth2/token + grant_type=password + password=$extended_code + username=username else extended code + email Client application->>Cloudentity: /oauth2/token + grant_type=password + password=$extended_code + username=email end Cloudentity->>Client application: OK + token(s) Client application->>Resource server (API): Call API with token
  1. The user provides their email in your custom login page and selects the Request Code button.

  2. The client application of your sign in page, sends a request to the Cloudentity Generate Code Of Specific Type API.

    The request must contain the type query parameter set to authentication.

    Learn more.

  3. Cloudentity provides the code and extended_code parameters in the request response.

  4. The sign in page must now provide the user with the value of the code parameter over the email/text message.

  5. User enters their verification code on the sign in page.

  6. The client requests token by calling the token endpoint.

    The password query parameter must be set to either:

    • Value of the code parameter which is less secure due to the code being in plain text and easier to guess.

    • Value of the extended_code parameter which is safer due to the base64 encoding of the user identifier and actual authentication code.

    The username parameter can be set to either the username or email of the user.

    Sample request to the /token endpoint with client authentication method set to client secret post:

    curl -X POST https://$TENANT_ID.$REGION_ID.authz.cloudentity.io/$TENANT_ID/$WORKSPACE_ID/oauth2/token \                                                                                   ~/repo
    --header 'Content-Type: application/x-www-form-urlencoded' \
    -d grant_type=password \
    -d client_id=$CLIENT_ID \
    -d client_secret=$CLIENT_SECRET \
    -d password=$EXTENDED_CODE \
    -d username=johndoe@example.com
    
  7. Authorization server validates user credentials.

  8. Authorization server returns the access and ID tokens.

  9. The client application may now request access to resources on behalf of the user using the access token it got from Cloudentity.

[mermaid-begin]
sequenceDiagram participant User participant Client application participant Cloudentity participant Resource server (API) User->>Client application: Request Code Client application->>Cloudentity: /user/code/generate Cloudentity->>Client application: code + extended_code Client application->>User: Magic Link with extended_code as part of the URL User->>Client application: Select provided Magic Link alt code as plain text Client application->>Cloudentity: /oauth2/token + grant_type=password + password=$code + username else extended code + username Client application->>Cloudentity: /oauth2/token + grant_type=password + password=$extended_code + username=username else extended code + email Client application->>Cloudentity: /oauth2/token + grant_type=password + password=$extended_code + username=email end Cloudentity->>Cloudentity: Verify code Cloudentity->>Client application: OK + token(s) Client application->>Resource server (API): Call API with token
  1. The user provides their email/username in your custom login page and selects the Request Code button.

  2. The client application of your sign in page, sends a request to the Cloudentity Generate Code Of Specific Type API.

    The request must contain the type query parameter set to authentication.

    Learn more.

  3. Cloudentity provides the code and extended_code parameters in the request response.

  4. The sign in page must now provide the user with an URL that contains the extended_code as its query parameter over the email/text message.

  5. User selects the link.

  6. The client requests token by calling the token endpoint.

    The password query parameter must be set to either:

    • Value of the code parameter which is less secure due to the code being in plain text and easier to guess.

    • Value of the extended_code parameter which is safer due to the base64 encoding of the user identifier and actual authentication code.

    The username parameter can be set to either the username or email of the user.

    Sample request to the /token endpoint with client authentication method set to client secret post:

    curl -X POST https://$TENANT_ID.$REGION_ID.authz.cloudentity.io/$TENANT_ID/$WORKSPACE_ID/oauth2/token \                                                                                   ~/repo
    --header 'Content-Type: application/x-www-form-urlencoded' \
    -d grant_type=password \
    -d client_id=$CLIENT_ID \
    -d client_secret=$CLIENT_SECRET \
    -d password=$EXTENDED_CODE \
    -d username=johndoe@example.com
    
  7. Authorization server validates user credentials.

  8. Authorization server returns the access and ID tokens.

  9. The client application may now request access to resources on behalf of the user using the access token it got from Cloudentity.

Updated: May 22, 2023