Authentication for User App
userapp
can authenticate with fabric Identity in one of the 2 ways:
Using Authorization Code Flow with PKCE (recommended)
To initiate this authentication flow, the following details are needed (for more information see here)
client-id
- This is a unique ID that represents the userapp
and is required for OpenID Connect authentication flows
Authorization Url
- This is the http end point of fabric Identity that the app needs to communicate with for getting its access token.
Once the above details are available, proceed with building the authentication flow as depicted below:
1. Generate PKCE code verifier and code challenge
In this step, the single page app or a mobile app, represented by the respective userapp
in fabric Identity, generates a code verifier and a code challenge from the code verifier. These codes ensure that the access token returned by fabric Identity (in step #8) is returned to the correct requestor.
code-verifier
: Random URL-safe string with a minimum length of 43 characters. See here for more details
code-challenge
: Base64 URL-encoded SHA-256 hash of the code-verifier
The app should store the code-verifier
securely to be used later (in step #6). The code-challenge
is sent earlier in the call to the /authorize
endpoint (in step #2)
2. Authorization Code request with code_challenge
In this step, the app should prepare a GET request to fabric Identity's /authorize
endpoint and load the GET url into the window.location
. This will allow fabric Identity to send a browser re-direct and take the end user to the hosted login page.
Here is a representation of the URL that should be constructed and loaded into window.location
https://${Authorization Url}/v1/authorize?client_id=${client-id}&response_type=code&scope=openid&redirect_uri=${redirect-uri}&state=${state}&code_challenge_method=S256&code_challenge=<sha256(${code-verifier})>
-
Authorization Url
: This is the url made available upon creating auserapp
. See Getting Started for more details. -
client-id
: Unique ID created for theuserapp
. See Getting Started for more details. -
redirect-uri
: This is the URI that fabric Identity will redirect to after a successful authentication. This should a URI of the requestinguserapp
and will contain a temporary authorization code (see step #5). The app should be prepared to use the query parameters on theredirect-uri
and then complete the authentication flow with fabric Identity -
state
: An opaque value (can be a random string) used by the app to maintain state between the request and callback from fabric Identity. This parameter is tyically used for preventing cross-site request forgery. See here for more information. -
code_challenge
: This query parameter in the above URL is a SHA256 hash of thecode-verifier
. See here for more details.
3. fabric Identity send 302 redirect to authentication prompt
As a response to step #2, fabric Identity would sent a redirect to the client browser to bring up the hosted login page. This hosted login page can also be configured for social logins, sign-up and forgot password links.
4. Enter credentails & provide consent
This is an action by the end users to successfully provice their identity. If configured, they would also provide consent tp fabric Identity to share their basic profile information with the calling app.
5. Authorization Code response sent back to the given redirect uri
After a successful login, fabric Identity would redirect the end user back to the redirect-uri
shared in the step #2. As part of this redirect, fabric Identity sends the following additional details as query parameters:
-
code
: The authorization code, a temporary code which should be returned back to fabric Identity along withcode-verifier
to get an access token -
state
: The samestate
send by the app to fabric Identity in step #2
6. Send authorization code with code_verifier
Once the app receives the redirect from fabric Identity it should validate if the state
field matches with the one sent in step #2. After this, the app should use the code
and make a POST request to fabric Identity to fetch the access token.
Below is an example of the POST request (represented as a curl command)
curl --request POST \
--url https://${Authorization Url}/v1/token \
-H 'accept: application/json' \
-H 'content-type: application/x-www-form-urlencoded' \
-d 'grant_type=authorization_code'
-d 'client_id=${client-id}'
-d 'redirect_uri=${redirect-uri}'
-d 'code=${code}'
-d 'code_verifier=${code-verifier}'
-
Authorization Url
: This is the url made available upon creating auserapp
. See Getting Started for more details. -
client-id
: Unique ID created for theuserapp
. See Getting Started for more details. -
redirect-uri
: This is the same URI that was originally sent by the app to fabric Identity in the step #2 -
code
: The authorization code received by the app in step #5 -
code-verifier
: The originalcode-verifier
generated by app in step #1
7. Validates Code Verifier
Once the POST request is received on its /token
endpoint, fabric Identity validates the code-verifier
by computing its SHA256 value and verifies this against the code-challenge
sent by the app in step #2. Upon successful validation it return the response with the access token i it.
8. Respond back with access token
Upon successful validation of the code-verifier
, fabric Identity returns the response with the access token.
Below is an example of a successful response from fabric Identity
{
"access_token": "eyJhbGciOiJ...",
"expires_in": 3600,
"id_token": "eyJhbGciOiJI...",
"refresh_token": "cBMrwDsXRwPqVmCQx7I5IX0jQ9-Lc_zHOgYeab1xZm4"
"scope": "openid offline_access",
"token_type": "Bearer"
}
The access_token
returned in the response above is a user token and would have a default expiry of 30 minutes (3600 seconds). This token should be used as a bearer token by the app to invoke fabric's APIs.
Also note that the response contains a refresh_token
. The refresh_token
can be used by the app to fetch a new access_token
once the previous one expires.
9. Request fabric platform API using access token as a bearer token
The app can now invoke any of the fabric API using the access_token
received in the previous step. This token should be sent in the Authorization
header as a Bearer
token which is then validated by the fabric API.
App developers can use 3rd party libraries (see here for an example) to achieve the above authentication flow.
Using Authorization Code Flow
TBD
Refresh Access Token
User tokens generated by fabric Identity have a default expiry of 30 minutes. Refresh tokens on the other hand are longer-living tokens and can be used to retrieve new access tokens without asking the end user to login again. For security reasons, every time a refresh token is used to get a new access token, the previous refresh token is discarded and a new one is recreted. Refresh tokens are also discarded if not used for 7 days. In such a cases the app should follow the previous authentication flow and allow end user to login again.
New access token can be requested from fabric Identity using a refresh token in a single step. Below is an example http call that the app can make to get a new access token from a refresh token:
curl --location --request POST 'https://${Authorization Url}/v1/token' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'grant_type=refresh_token' \
--data-urlencode 'redirect_uri=${redirect-uri}' \
--data-urlencode 'scope=offline_access openid' \
--data-urlencode 'refresh_token=${refresh-token}' \
--data-urlencode 'client_id=${client-id}'
-
Authorization Url
: This is the url made available upon creating auserapp
. See Getting Started for more details. -
client-id
: Unique ID created for theuserapp
. See Getting Started for more details. -
redirect-uri
: This is the same URI that was originally sent by the app to fabric Identity in the step #2 of the authentication flow. -
refresh-token
: Refresh token received by the app along with the access token.
Below is a sample response sent from the fabric Identity for the refresh request:
{
"token_type": "Bearer",
"expires_in": 3600,
"access_token": "eyJraWQiO...",
"scope": "offline_access openid",
"refresh_token": "jSdVOtddMk8HMHP...",
"id_token": "eyJraWQ..."
}
Note that the response contains a new access_token
along with a new refresh_token
.