Skip to content

Implementing Infinity Login

This page goes into some detail about how we offer our OAuth 2.0-compliant solution.

You can also consult the API reference directly.

Requirements

  • Infinity Login OAuth 2 application already created inside Unbox Studio
  • Basic understanding of how OAuth 2.0 works

OAuth 2 flows

We currently offer only the code flow, no token. Additionally, Proof Key for Code Exchange (PKCE) is always required and it supports only the S256 method (no plain text). See the PKCE requirements section at the end of this page.

Configuration

Automatic / openid-configuration

If your client library supports it you could use this URL directly:

https://clx-webx-authorization-server.unboxuniverse.io/.well-known/openid-configuration

This endpoint describes all available OAuth 2 endpoints which follow the appropriate RFC.

JWKS

If you are not using the automatic configuration, then in order to verify the JWT access token on your side, you can retrieve our keys by calling the following:

https://clx-webx-authorization-server.unboxuniverse.io/.well-known/jwks.json

Caution: We rotate these keys from time to time, so do not cache them indefinitely.

Web Application Flow

Here is the happy path of the flow between a web app client and XYZ, without Single sign-on (SSO):

  • client_id triggers a request to the /authorize endpoint, redirecting the end user to the Infinity Login server.
  • The Infinity Login server redirects the user to a login page.
  • The login page displays some client information and a QR Code.
  • User scans the QRCode with their XYZ mobile app. The result of the scan is that the app presents to the user some information about the login (typically scope of access to their information), and the user consents to this scope of access.
  • Infinity Login server notifies the login page to redirect the user to client application (using the client redirect_uri).
  • The client retrieves the response code through the callback and then calls the Infinity Login server through the /token endpoint to exchange it for a valid Infinity Login access token (JWT).

SSO-specific case

If the required scopes of access are already consented to (for this specific client) and the end user is already authenticated on the Infinity Login server (most likely via a prior successful login), then the signature mechanism involving XYZ is not required, and the client gets the code back immediately after the call to /authorize.

However, if at least one scope is new, the flow becomes identical to the one without SSO involved.

Mobile to XYZ Flow

In this flow, the client is a mobile application instead of a browser.

From an Infinity Login server point of view, this is called the headless flow or API flow, and the major difference is that there is no login page.

Additionally, there is no HTTP redirect_uri used. Everything is done through the exchanges between the mobile application and XYZ.

To use the headless flow you must have the following header in the /authorize and /login requests:

--header 'Accept: application/json'

How it works:

  • Client application calls the /authorize endpoint and gets the login_code_to_sign (with the header mentioned above).
  • Client application uses a deeplink to ask the XYZ native app to sign this code.
  • XYZ presents the login request.
  • End user consents to the access scope, which results in a callback to the client mobile application (also using a deeplink).
  • Client mobile application receives the following data from XYZ:
  • The original login_code_to_sign
  • The signature (or proof) which is the login_code_to_sign signed with the public key
  • The public key used to sign (encrypt), i.e. the identity which the end user selected to login
  • Client mobile application posts this data to the /login endpoint, which returns a code for next call.
  • Client mobile application posts the freshly received code to the /token endpoint, which returns the final access token.

Once the login part is completed, the flows are essentially the same for both mobile and web. The only exception is that the client mobile application needs to communicate with XYZ using a deeplink.

Note: We are currently working to provide mobile SDKs, namely React Native, Flutter, Android, and iOS. Please reach out to us if they are still not available or if you wish for something not on this list.

SSO

Since we support SSO, if a client application has already approved all its scopes and the user is already authenticated through Infinity Login server, then an immediate callback occurs to the redirect_uri with the code for the /token exchange endpoint.

Note: You still have to redirect your user with the /authorize endpoint as usual to get a new token.

SSO is only available through a browser, and because it uses cookies to make the session happen, they have to be enabled by the end user.

Logout

You can perform a logout by redirecting the user to the following URL, which takes them to the logout page:

https://clx-webx-authorization-server.unboxuniverse.io/openid/logout

Warning: using the logout feature does not invalidate any existing access token that's already issued, but destroys the session the user has within the Infinity Login server.

This is most likely a feature you might want to use if you need to switch user within the same browser session.

Again, this is very specific to SSO.

PKCE requirements

https://www.rfc-editor.org/rfc/rfc7636.html#section-6.2

PKCE is a mandatory mechanism to protect the token exchange. You must initiate a request to the /authorize endpoint with the hash value (code_challenge) to later use its clear value (code_verifier) during the token exchange:

  • Generate random value with enough entropy, at least 12 characters. This is the code_verifier.
  • Generate the SHA-256 and encode it in Base64 without the leading. This is the code_challenge using BASE64URL-ENCODE(SHA256(ASCII(code_verifier)))

Caution: Make sure to encode in Base64 without padding!

Implementation examples

Here are some simple examples of implementation. There may be better solutions out there. If you use any kind of OAuth 2 client library, there is a good chance that this is already available out of the box.

  // In Rust
  let mut sha256 = Sha256::new();
  sha256.update(code_verifier.as_bytes());
  let code_challenge = base64::encode_config(sha256.finish(), base64::URL_SAFE_NO_PAD)
  // In Javascript
  // Sure this could be better coded
  async function generateCodeChallenge(codeVerifier) {
    var digest = await crypto.subtle.digest("SHA-256",
      new TextEncoder().encode(codeVerifier));

    return btoa(String.fromCharCode(...new Uint8Array(digest)))
      .replace(/=/g, '').replace(/\+/g, '-').replace(/\//g, '_')
  }

Another example for React native: https://www.npmjs.com/package/react-native-pkce-challenge

Here's what the JSON looks like:

{
  "codeChallenge":"FrKXvAasmPJAnMh9jPOW-HMQouSjPYAwlMU-RP20vLs",
  "codeVerifier":"xDshz4RJuwAMLOa8j41R1gR-NhLMv7WoU2LiC-bqrwNpnU70l1mlZocMSh3pABbsWiIHBPKFbPEuFbZy_cQiRWMQjBXoxPY9FUe9STC5h4vJ7wyGKMDKKo9sQtraBScm"
}

Anatomy of the Infinity Login token

If you decode the access token, inside it you can find the following claims:

  • iss: The issuer, i.e. the Unbox server located at https://clx-webx-authorization-server.unboxuniverse.io/
  • sub: Corresponds to the identifier of the connected end-user, in our case always the public key
  • pub_key_hash: Corresponds to the hash of the public_key. This is provided for convenience but you could derive it from the sub.
  • aud: This is your client_id
  • scope: Consented scope from the end user.
  • storage_token: Currently not used for the community edition
  • iat: Timestamp of when the token gets delivered
  • exp: Timestamp of when the token expires