Skip to main content

using the Hybrid Flow

This tutorial will help you to sign-in using the Hybrid Flow.
If you want to learn how the flow works and why you should use it, see OpenID Hybrid Flow.


Before beginning this tutorial:

Create an App to retrieve a Client ID and Client Secret. These APP credentials identify your app during the authorization process.

  1. Log in to your Partner Dashboard.
  2. Click Apps.
  3. Click "Add an app" to open Developers Dashboard.
  4. Click Create App.
  5. Enter the App name, add an Allowed Redirect URL of https://YOUR_APP/callback.
  6. Click Create.
  7. View your Client ID and Client Secret (need re-enter your password).



  1. Authorize user: Request the user's authorization and redirect back to your app with an authorization code.
  2. Request tokens: Exchange your authorization code for tokens.
  3. Call API: Use the retrieved Access Token to call API.
  4. Refresh tokens: Use a Refresh Token to request new tokens when the existing ones expire.
  5. ID Token Structure
  6. Validate ID Tokens
  7. Library example configuration

Authorize user

To begin the flow, you'll need to get the user's authorization. This step may include one or more of the following processes:

  • Authenticating the user;
  • Redirecting the user to an Identity Provider to handle authentication;
  • Checking for active Single Sign-on (SSO) sessions;
  • Obtaining user consent for the requested permission level, unless consent has been previously given.

To authorize the user, your app must send the user to the authorization URL (open url on browser).

Authorization URL:


Note that for authorizing a user when calling a custom API, you can include additional scopes supported by the target API.

Parameter NameDescription
response_modeSpecifies the method with which response parameters should be returned. For security purposes, the value should be form_post. In this mode, response parameters will be encoded as HTML form values that are transmitted via the HTTP POST method and encoded in the body using the application/x-www-form-urlencoded format.
response_typeFor this flow, the value must include code and id_token.
scopeSpecifies the scopes for which you want to request authorization, which dictate which claims (or user attributes) you want returned. These must be separated by a space. You can request any of the standard OpenID Connect (OIDC) scopes about users, such as profile or email, or any scopes supported by the target API (e.g., com.read_products). Include offline_access to get a Refresh Token.
Ex: scope=openid profile email org userinfo
client_idYour application's Client ID.
redirect_uriThe URL to which Haravan will redirect the browser after authorization has been granted by the user. The Authorization Code will be available in the code URL parameter. You must specify this URL as a valid Redirect Url in your Application Settings.
The redirect URI must begin with the scheme https. There are some exceptions for localhost redirect URIs.

Warning: Per the OAuth 2.0 Specification, Haravan removes everything after the hash and does not honor any fragments.
state(recommended) An opaque arbitrary alphanumeric string your app adds to the initial request that Haravan includes when redirecting back to your application. Use this value to prevent cross-site request forgery (CSRF) attacks.
nonceA cryptographically random string that your app adds to the initial request and Haravan includes inside the ID Token, used to prevent token replay attacks.
orgid(optional) ID of the organization to use when authenticating a user. When not provided, the user will be able to select the organization when authenticating.
- OrgID is field id in https://{organization-store-name}
- Use this parameter to force user login in a specific organization.

As an example, your HTML snippet for your authorization URL when adding login to your app might look like:

<a href=" id_token&scope=openid profile email org userinfo offline_access&client_id=YOUR_CLIENT_ID&redirect_uri=https://YOUR_APP/callback&state=YOUR_STATE&nonce=YOUR_NONCE">
Sign In

Login permissions prompt. Haravan shows the following prompt to receive authorization from the user.



If all goes well, you'll receive an HTTP POST form. The requested credentials are encoded in the body:

Content-Type: application/x-www-form-urlencoded
scope=openid profile email org userinfo offline_access&

Example: receive a successful form


Example: receive an error form


Haravan will also return any state value you included in your call to the authorization URL.

You should validate your tokens before saving them. To learn how, see Validate ID Tokens.

If your application only needs to use Hybrid Flow for sign-on, you will not need an Access Token, only an ID Token with claims. and you can skip next step.

Request tokens

Now that you have an Authorization Code, you must exchange it for tokens. Using the extracted Authorization Code (code) from the previous step, you will need to POST to the token URL /connect/token.

The Access Token you receive in this step is the one you should use to call your API.

Example POST to token URL

curl --request POST \
--url '' \
--header 'content-type: application/x-www-form-urlencoded' \
--data 'grant_type=authorization_code' \
--data 'client_id=YOUR_CLIENT_ID' \
--data 'client_secret=YOUR_CLIENT_SECRET' \
--data 'redirect_uri=https://YOUR_APP/callback'
Parameter NameDescription
grant_typeSet this to authorization_code
codeThe authorization_code retrieved in the previous step of this tutorial.
client_idYour application's Client ID. You can find this value in your Application Settings.
client_secretYour application's Client Secret. You can find this value in your Application Settings.
redirect_uriThe valid callback URL set in your Application settings. This must exactly match the redirect_uri passed to the authorization URL in the previous step of this tutorial. Note that this must be URL encoded.


If all goes well, you'll receive an HTTP 200 response with a payload containing access_token, id_token, token_type, and (optional) refresh_token values:

"id_token": "eyJh...Mqqg",
"access_token": "C5BD...3009",
"expires_in": 86400,
"token_type": "Bearer",
"refresh_token": "C2ED...2500",
"scope": "openid profile email org userinfo offline_access"
Parameter NameDescription
id_tokenA JSON Web Token (JWT). The app can decode the segments of this token to request information about the user who signed in. The app can cache the values and display them, and confidential clients can use this for authorization.
access_tokenThe requested access token. The app can use this token to authenticate to the secured resource, such as userinfo or a web API.
expires_inHow long the access token is valid (in seconds).
token_typeIndicates the token type value. The only type that Haravan supports is Bearer
refresh_tokenAn OAuth 2.0 refresh token. The app can use this token acquire additional access tokens after the current access token expires. Refresh_tokens are long-lived, and can be used to retain access to resources for extended periods of time.
Note: Only provided if offline_access scope was requested.
scopeThe scopes that the access_token is valid for.



You should validate your tokens before saving them. To learn how, see Validate ID Tokens.

ID Token contain user information that must be decoded and extracted.

Access Tokens are used to call the Haravan Authentication API's /connect/userinfo endpoint or another API.

Refresh Tokens are used to obtain a new Access Token or ID Token after the previous one has expired. The refresh_token will only be present in the response if you included the offline_access scope for your API.

Refresh Tokens must be stored securely since they allow a user to remain authenticated essentially forever.

Call API

To call API from a regular web application (or similar cases in which the Client Secret can be safely stored), the application must pass the retrieved Access Token as a Bearer token in the Authorization header of your HTTP request.

Example: GET userinfo endpoint

curl --request GET \
--url \
--header 'authorization: Bearer ACCESS_TOKEN' \
--header 'content-type: application/json'

Example: GET products.json endpoint. The scopes must include com.read_products and enabled in your Application Settings.

curl --request GET \
--url \
--header 'authorization: Bearer ACCESS_TOKEN' \
--header 'content-type: application/json'

Refresh tokens

You have already received a Refresh Token if you've been following this tutorial and included the offline_access scope when you initiated the authentication request through the authorize endpoint.

You can use the Refresh Token to get a new Access Token. Usually, a user will need a new Access Token only after the previous one expires or when gaining access to a new resource for the first time. It's bad practice to call the endpoint to get a new Access Token every time you call an API, and Haravan maintains rate limits that will throttle the amount of requests to the endpoint that can be executed using the same token from the same IP.

To refresh your token, make a POST request to the /connect/token endpoint in the Authentication API, using grant_type=refresh_token.

Example POST to token URL

curl --request POST \
--url '' \
--header 'content-type: application/x-www-form-urlencoded' \
--data 'grant_type=refresh_token' \
--data 'client_id=YOUR_CLIENT_ID' \
--data 'client_secret=YOUR_CLIENT_SECRET' \
--data 'refresh_token=YOUR_REFRESH_TOKEN'
Parameter NameDescription
grant_typeSet this to refresh_token.
client_idYour application's Client ID. You can find this value in your Application Settings.
client_secretYour application's Client Secret. You can find this value in your Application Settings.
refresh_tokenThe Refresh Token to use.

If all goes well, you'll receive an HTTP 200 response with a payload containing a new access_token, its lifetime in seconds (expires_in), granted scope values, token_type, new id_token, and new refresh_token:

"id_token": "eyJh...Yyzw",
"access_token": "3BDD...A3FF",
"expires_in": 86400,
"token_type": "Bearer",
"refresh_token": "C2ED...2500",
"scope": "openid profile email org userinfo offline_access"

You should validate your tokens before saving them. To learn how, see Validate ID Tokens.

Refresh token lifetime: Refresh tokens have a significantly longer lifetime than access tokens. The default lifetime for the Refresh tokens is 30 days and they replace themselves with a fresh token upon every use. This means that whenever a refresh token is used to acquire a new access token, a new refresh token is also issued. Securely delete the old refresh token after acquiring a new one. Refresh tokens need to be stored safely like access tokens or application credentials.

Notes: new refresh_token may be the same value as old refresh_token, but may be different in the future, alway store new refresh_token.

Refresh tokens can be revoked at any time, because of timeouts and revocations. Your app must handle rejections by the sign-in service gracefully when this occurs. This is done by sending the user to an interactive sign-in prompt to sign in again.

ID Token Structure

ID tokens are JSON web tokens (JWT). These ID tokens consist of a header, payload, and signature. The header and signature are used to verify the authenticity of the token, while the payload contains the information about the user requested by your client.


Payload parameters

Parameter NameDescription
nbfA UNIX timestamp. When the token activates.
expA UNIX timestamp. When the token expires.
issAn issuer URI. Identifies the issuer, or "authorization server" that constructs and returns the token.
audClient ID
nonceThe nonce matches the parameter included in the original /authorize request to the IDP. If it does not match, your application should reject the token.
iatA UNIX timestamp. When the token was issued.
sidA unique session ID per user and app.
idpRecords the identity provider that authenticated the subject of the token. This value is identical to the value of the Issuer claim.
orgidOrganization ID
orgnameOrganization name
orgcatOrganization's category
subUser id, The user that the session token is intended for.
emailUser's email
nameUser's name
middle_nameUser's middle_name
roleUser's roles
localeUser's locale

Validate ID Tokens

An ID token, which contains user profile attributes, is consumed by an app and is typically used for user interface display. Haravan issues all ID tokens in JSON web token (JWT) format.

If any of these checks fail, the token is considered invalid, and the request must be rejected.

  1. Validate the JWT.

    • We strongly recommend that you use middleware or one of the existing open source third-party libraries to parse and validate JWTs. At, you can find libraries for various platforms and languages, such as .NET, Python, Java, Ruby, Objective-C, Swift, Nodejs, and PHP.
    • To verify the signature of a token from one of your applications, we recommend that you get the Public Key from Haravan JWKS:
  2. Check additional standard claims. If you've performed the standard JWT validation, you have already decoded the JWT's Payload and looked at its standard claims. Additional claims to verify for ID tokens include:

    • Token audience (aud, string): The audience value for the token must match the Client ID of the application as defined in your Application's Settings in the Client ID field.
    • Nonce (nonce, string): Passing a nonce in the token request is recommended (required for the Implicit Flow) to help prevent replay attacks. The nonce value in the token must exactly match the original nonce sent in the request.
    • Token expiration (exp, Unix timestamp): The expiration date/time must be after the current date/time.
    • Token issuer (iss, string): The issuing authority inside the token must match the issuing authority (issuer) identified in Haravan discovery document, which exists at

Library example configuration