Using long-lived access tokens

If it is inconvenient for your programmatic clients that the User Management Service (UMS) access_token tokens have a default validity of two hours, you can exchange an access_token for an app_token that is valid for 366 days.

Understanding app tokens

App tokens were introduced to support enforcing multi-factor authentication (MFA) for command line clients. Because Liberty does not support MFA natively, it is expected that authentication is delegated further to an existing identity provider that supports MFA. Therefore, the client should use the browser-based implicit flow to obtain an initial access_token, which is then exchanged for an app_token that has a much longer validity.

Design considerations for the custom app

  1. The custom application must register with UMS SSO, specifying the implicit grant_type and token response_type. For clarity and convenience, in the following examples, the UMS admin credentials are stored in the environment variables umsuser and umspassword and localhost:9443 are used for the UMS host and port:
    1. Create a new file named json.txt with content similar to the following, substituting your values where necessary:
      {
        "scope": "openid",
        "preauthorized_scope": "openid",
        "introspect_tokens": true,
        "response_types": ["token"],
        "grant_types": ["implicit"],
        "redirect_uris": [ "http://192.168.99.100:8080", "myapp://token" ],
        "appTokenAllowed": true  
      }
    2. Run the following commands:
      umsuser=umsadmin
      umspassword=passw0rd
      curl -k -s -X POST -H "Content-Type:application/json" -u "$umsuser:$umspassword" -d @json.txt "https://localhost:9443/oidc/endpoint/ums/registration"
      Example response:
      {
          "client_id_issued_at": 1572602365,
          "registration_client_uri": "https://localhost:9443/oidc/endpoint/ums/registration/1657e00324474d8b9fbe637b0883515d",
          "client_secret_expires_at": 0,
          "token_endpoint_auth_method": "client_secret_basic",
          "scope": "openid",
          "grant_types": ["implicit"],
          "response_types": ["token"],
          "application_type": "web",
          "preauthorized_scope": "openid",
          "introspect_tokens": true,
          "resource_ids": [],
          "proofKeyForCodeExchange": false,
          "publicClient": false,
          "appPasswordAllowed": false,
          "appTokenAllowed": true,
          "hash_itr": 0,
          "hash_len": 0,
          "client_id": "1657e00324474d8b9fbe637b0883515d",
          "client_secret": "5a8pw7rQWN3VeKGcfvsIs039zHHrmiliprDAVKlLvbK9yrnhHgOulvKpbLgN",
          "client_name": "1657e00324474d8b9fbe637b0883515d",
          "redirect_uris": ["http://192.168.99.100:8080", "myapp://token"],
          "allow_regexp_redirects": false
      }
    3. Note the values for client_id and client_secret. For demonstration purposes, you might store them in environment variables:
      clientid=1657e00324474d8b9fbe637b0883515d
      clientsecret=5a8pw7rQWN3VeKGcfvsIs039zHHrmiliprDAVKlLvbK9yrnhHgOulvKpbLgN
  2. The app obtains a short-lived access token. If UMS is not configured to delegate authentication further, we can use basic authorization, for example:
    curl -k -s -v -u "$umsuser:$umspassword" 'https://localhost:9443/oidc/endpoint/ums/authorize?response_type=token&client_id=$clientid&scope=openid&state=none&redirect_uri=myapp://token'
    Where
    • response_type=token indicates that the app wants an access token (not an id token).
    • client_id=$clientid identifies itself so that the authorization server can verify that the redirect_uri is in the preregistered whitelist and that it can include the client_id in the token information.
    • scope=openid is required.
    • state=none is a short-cut in this example. You can use this parameter to help re-establishing the context, for example, if the browser app had saved some parameters in HTML5 session storage or to make sure that the client actually sent the user to the authorization server.
    • redirect_uri the URI to come back to after the user authenticated and gave consent (depending on scopes).

    The 302 redirect response will contain an HTTP response header location that is pointing to the registered and requested location (myapp://token) with an appended fragment that includes among other things your access_token, for example:

    location: myapp://token#scope=openid&access_token=C87wJE2Mst7DEdBJMfV9Rw6I8RUlZ9bilITmZqhK&token_type=Bearer&expires_in=7199&state=none
    The short-lived access_token is C87wJE2Mst7DEdBJMfV9Rw6I8RUlZ9bilITmZqhK expires in 7199 seconds.
  3. Exchange the access_token for long-lived app_token by using the access token to call the UMS app-tokens endpoint. For example:
    curl -k -X POST -u "$clientid:$clientsecret" -d "app_name=myapp" -H "Accept: application/json" -H "access_token: $accesstoken" "https://localhost:9443/oidc/endpoint/ums/app-tokens"
    The response contains the app-token: GGONoU7vG9uJ6jJQOwKO7nBouq9sB08WHiOLzv0qBO
    {
        "app_token": "GGONoU7vG9uJ6jJQOwKO7nBouq9sB08WHiOLzv0qBO",
        "app_id": "Lk088OmmPgwAmglhR4skWd4OzKmYT4nprrR4xR3e",
        "created_at": "1572603852658",
        "expires_at": "1580379852658"
    }
    For demonstration purposes, you might store the token in an environment variable:
    apptoken=GGONoU7vG9uJ6jJQOwKO7nBouq9sB08WHiOLzv0qBO
    Tip: You can set the following lifetimes and limits for app tokens and app passwords in the custom resource file:
    ums_configuration.oauth.app_token_lifetime
    The lifetime of app tokens. The default is 366d.
    ums_configuration.oauth.app_password_lifetime
    The lifetime of app passwords. The default is 366d.
    ums_configuration.oauth.app_token_or_password_limit
    The maximum number of app tokens or app passwords per client. The default is 100.
  4. Use the app_token just like any other access_token to invoke an API. for example:
    curl -k -s -H "Authorization: Bearer $apptoken" https://sample-host/rest/bpm/wle/v1/user/current