Start a conversation

OAuth 2.0 authorization grant flow

Learn about our OAuth 2.0 authorization grant flow for API authentication in Aurora.

Khoros supports OAuth 2.0 to authenticate calls from a client application to the Khoros Community. The community supports an authorization grant flow with implicit consent. You can find complete OAuth documentation on the OAuth website.

Note: The OAuth 2.0 grant flow assumes that users will be authenticated in the Community Web UI (via Lithium Registration, LithiumSSO, or SAML 2.0) and that a web browser plays a part in the flow. See "Using the authorization grant flow via a back-end API call" later in this guide for a workaround for using the grant flow with a back-end API call. To make a fully-automated server-to-server API call, do not use OAuth; authenticate with a session key or SSO token instead.

Important: Contact support to add your community domain to the allowed domain list for the Authorization flow.

Before you begin

Before you get started, be sure you understand the following terminology and know how to obtain the credentials you’ll need during the OAuth flow.

Terminology

First, let's define a few terms:

  • User Agent – Software that acts on behalf of a user. It is an application remotely accessing a different computer, usually a server, through a network. For example, your browser is a user agent that enables you to send an email from a Gmail account or find a book on Amazon.
  • Authorization Service – A service that issues access tokens. An access token is issued upon the first successful user authentication. The token is passed with subsequent REST API calls so a user can make the calls without requiring additional sign-ins. The Authorization Service can also issue refresh tokens. You will not interface with the Authorization Service directly.
  • Khoros Community – A Community app hosted by Khoros. This is the entity in the OAuth flow that is responsible for permission control and enforcement.

Find your client ID and client secret

A client ID and secret are used as authorization credentials in the OAuth flow to retrieve the access and refresh tokens that allow the community member in session to make REST calls with the Community API.

  • The client ID is used for both anonymous and authenticated calls.
  • The client secret is used only for authenticated calls.

About the authorization grant flow

Let's look at a summary of the flow.

  1. A user must explicitly sign in to your Community app once to get an authorization code enabling them to get an OAuth access token. This Web UI authentication can happen using a Community-hosted sign-in page or SSO (LithiumSSO/SAML 2.0).

    • If Community is configured to use Lithium Registration (a Community-hosted sign-in page), Community opens a Sign In page for users to enter their login and password. Upon successful Community Web UI authentication, the user is redirected to the URL in the ‘redirect URI’ configured when you create the API app in Community Admin > Dev Tools.
    • Community returns an authorization code (code) as a parameter on a redirect URI to the OAuth client on your client application using a backend call.
    • If your Community uses SSO, you’ll make a POST call to /auth/authorize passing the SSO token in the payload. Upon successful SSO authentication, Community returns an authorization code in the response body to your client application using a backend call.
  2. Make a server-to-server POST call to /auth/accessToken from your OAuth client to the Community to get an access token and refresh token mapped to the authorized user.

  3. Make subsequent Community REST API calls as that user, passing the access token in the header. The access token inherits permissions of the Community app user based on the roles/permissions granted in Community Admin.

  4. The access token is valid for an hour. Refresh the access token before the access token expires. The refresh token does not expire unless it is specifically revoked. Once the refresh token is passed, the user will not have to log in again.

This diagram provides a high-level overview of the authorization grant flow. The flow begins with the User Agent attempting to access Community from a Customer App. Notice that the Community is the only piece of the Khoros platform that the Customer App interfaces with directly. The Authorization Service is transparent to the Customer App.

OAuth 2.0 Grant Authorization Flow Overview
OAuth 2.0 Grant Authorization Flow Overview

The following diagram provides a more technical description.

Lithium Registration flow

Lithium Registration Flow for OAuth Grant Authorization
Lithium Registration Flow for OAuth Grant Authorization

SSO Flow

SSO Flow for OAuth Grant Authorization
SSO Flow for OAuth Grant Authorization

Using the authorization grant flow via a back-end API call

Note: To make a fully-automated server-to-server API call, do not use OAuth; authenticate with a session key or SSO token instead.

The authorization grant flow assumes that a web browser is involved during authentication. If you want to use a back-end API call for OAuth, create an API-only user with appropriate permissions to make the API calls. Manually initiate the authorization grant flow and log in to the community (using any HTTP client) once for the API-only user following the authorization flow illustrated in the previous diagram. In the last step of the flow, you request and access, and refresh tokens. Store the tokens in your application to use for subsequent authenticated, backend API calls. Use the access token once and then use the refresh token after the access token expires. Using the refresh token ensures that no future logins are required unless the tokens are revoked.

API Application for Authorization Grant Flow

To use and integrate the Authorization Grant Flow, you must create and register the API application in your Aurora community. For example, we use the Salesforce Integration Application.

  1. Log in to your Aurora Community.
  2. Go to Account > Dev Tools > Create App.
  3. Create App Screenshot
  4. After the SalesforceIntegrationApp-olympuspub API application is created, you can find the client ID and Client Secret in the API Apps section of the Dev Tools.
  5. You can authorize your community either using recommended flow or Khoros SSO flow.

OAuth security considerations

OAuth tokens are scoped to a single client application (also referred to as a client ID). A call with a token specific to one client ID will fail if used with a different client ID. The authorization granted with this flow is granted with implicit consent. Client applications can be deleted in Community Admin > Dev Tools if needed.

OAuth API index

Request authorization

If a community user attempts to access the community, the user must be authenticated in the Community Web UI.

Do this once per user.

  • If your community is configured for user authorization grant flow, the user is redirected to the community home page for authentication. After a successful authentication, it directs to a redirect URL configured in the API Apps along with the auth code.
  • If your community is configured for Khoros SSO, the user goes through the Khoros SSO flow. You will pass the SSO token to POST /api/2.1/auth/authorize.

Request authorization (User Authorization Grant Flow – Involves Browser)

  1. Make a GET call to https://[YOUR COMMUNITY DOMAIN]/auth/oauth2/authorize with the following query parameters:
Field Description
client_id The client-id created in your API application.
response_type The value is code. It represents the authorization code.
redirect_uri The redirect URL where the control should be returned after authenticating with the tenant in case of login. The redirect_uri must match the callback URL defined in your Web App registration in Community Admin > Dev Tools.
state A randomly generated string. This is used to mitigate cross-site request forgery. This will be returned as-is in the redirect URL after successful login. How you generate the string is up to you.

The allowed length for state is limited by the limitations present in an HTTP GET URL.
This field will also function as a CSRF token.

Use the state parameter to look up and restore the previous state (before login) of your application. Your application generates a random string and sends it to the authorization server. The authorization server returns the state parameter. If both state values match, all is ok. If the state values differ, someone else has initiated the request.


Example GET /authorize request

https://[YOUR-COMMUNITY-DOMAIN]/auth/oauth2/authorize?client_id=CLIENT_ID&redirect_uri=REDIRECT_URI&response_type=


  1. When you make the authorization request, a screen prompts the user to approve the application's request to access the account.
  2. After you click the Authorize button, you will be redirected to your community login page. You must enter your credentials to log in to the community.

  3. Once the community authenticates the user, the browser will provide the redirected URL with authorization code, tenant ID, user ID, and, optionally, state.

    https://khoros-a6-dev-ed--c.develop.vf.force.com/apex/LTI_CustomSetting_vfp?code=yn7EqS0RgMO%2BXEYDm%2BauiTUgShBGkHVDqAqew6Vg5Wc%3D&tenant-id=olympuspub&user-id=1&state=dKxkguYxm0U8Tsw3P7gxlH1Zfr11zSSLbNF6iFk
  4. Use the above authorization code to generate the access token.

Request authorization (Khoros SSO flow)

Make a POST call to /api/2.1/auth/authorize, passing the following in the payload.

Field Description
client_id The client-id for the community
ssoToken The user’s SSO token.
redirect_uri The redirect URL where the control should be returned after authenticating with the tenant in case of login. The redirect_uri must match the callback URL defined in your Web App registration in Community Admin > Dev Tools.
state A randomly generated string. This is used to mitigate cross-site request forgery. This will be returned as-is in the redirect URL after successful login. How you generate the string is up to you.

 The allowed length for state is limited by the limitations present in an HTTP GET URL.

 Use the state parameter to look up and restore the previous state (before login) of your application. Your application generates a random string and sends it to the authorization server. The authorization server returns the state parameter. If both state values match, all is ok. If the state values differ, someone else has initiated the request.


Example POST /authorize request

curl -X POST \
  https://mycommunity.lithium.com/api/2.1/auth/authorize \
  -H 'Content-Type: application/json' \
  -d '{
  "ssoToken":"[SSO_TOKEN}",
        "clientID":"[CLIENT ID]",
        "redirectUri":"[REDIRECT URI]",
        "state":"[RANDOMLY-GENERATED STRING]"
      }'

The response will contain the authorization code.


Example Response

{  
  "status":"success",
  "message":"",
  "data":{  
    "code":"XMvE+YIZAt/hr0Lde6ZQtgioAicuUQtQ8pU7w0zVLPI=",
    "user-id":"50355515",
    "state":"state-1",
  }
}

Request access and refresh tokens

POST /auth/accessToken

To get an access token, make a POST call to /auth/accessToken.

The /auth/accessToken endpoint returns an access token and a refresh token that can be passed to /auth/refreshToken (used to refresh a user's access token before the 24 hour expiration period completes).

Header Parameters

Header Parameter Description
client-id The client ID generated in Community Admin > Dev Tools
Content-type application/json


Body Parameters

Body Parameter Description
client_id The application's ID
client_secret The application's secret
code The authorization code received from the authorization server. The code is returned from the call to the /authorize endpoint is URL encoded. Before calling the /accessToken endpoint, be sure to decode the code value.
grant_type Always authorization_code
redirect_uri The redirect_uri used in the authorization request. This URI must match the callback URL defined for the community.


Example POST /auth/accessToken request

curl -X POST \
    https://[COMMUNITY DOMAIN]/api/2.1/auth/accessToken \
    -H "Content-Type: application/json" \
    -H "client-id: [CLIENT ID]" \
    -d '{
            "client_id":"[CLIENT ID]",
            "client_secret":"[CLIENT SECRET]",
            "grant_type":"authorization_code",
            "redirect_uri":"[REDIRECT URI]",
            "code":"[AUTHORIZATION CODE]"
         }'


Example POST /auth/accessToken response

{ 
    "response": { 
        "status": "success", 
        "message": "OK", 
        "http_code": 200, 
        "data": {
            "access_token": "o5IV0yIiNDj/5lNJ6doJh08LX6SsDwtkDXDVmhGvRtI=", 
            "expires_in": 86400, 
            "lithium_user_id": "2d8c95ed-21dc-4ba6-ab9f-d3eff9c928ce", 
            "refresh_token": "XAAWIWKr38W33SlqYooR9OEJW0um9DoyB/o843rdIxk=",
            "token_type": "bearer" 
        }
    }
}

Pass the access token with your REST call

When you have your access and refresh token, you are ready to make authorized REST calls to the Community API. Include the authorization token in your request header. All requests should be made over HTTPS. Remember that while the token enables the user to make a Community API call, the permissions applied to the user account in session will determine whether or not the call will be successful.

For instructions for building a Community API v2 URL see Getting Started. For instructions for building a Community API v1 URL, see The API Call.

Before making calls to a third-party application, register the domain from which you will make the calls by filing a Support ticket .

Header Parameters

Header Parameter Description
client-id The client ID generated in Community Admin > Dev Tools
Content-type application/json
Authorization Bearer token
 where token is the OAuth token obtained on behalf of the user


This example call creates a message on the community.


Example Community API v2 call with access token

curl -X POST \
    https://[COMMUNITY DOMAIN]/api/2.1/messages \
    -H 'content-type: application/json' \
    -H 'Authorization: Bearer [TOKEN]' \
    -H 'client-id: [CLIENT ID]' \
    -d '{
            "data":{
                "type":"message",
                "subject":"This is the message subject",
                "body":"This is a message post.",
                "board":{
                    "id":"myForum"
                }
            }
        }'

Community validates the mandatory client-id and the optional Authorization with the bearer token and routes the call.

Refresh the access token

POST /auth/refreshToken

An access token is valid for an hour before it expires. Refresh the token within that time period with a POST call to /auth/refreshToken and passing the refresh_token received in the response from POST /auth/accessToken. Otherwise, the user will go through the authentication flow again.

When you pass the refresh_token, the Authorization Service issues a new access token and (optionally) a new refresh token. Store the new refresh token in case you need it for subsequent refreshes. The refresh token does not expire.

By default, you'll be issued the same refresh token originally returned from POST /auth/accessToken, however, you can force the authentication service to generate a new refresh token by sending the optional force_refresh parameter.

Header Parameters

Header Parameter Description
client-id The client ID generated in Community Admin > Dev Tools
Content-type Always application/json


Body Parameters

Body Parameter Description
client_id The application's ID
client_secret The application's secret
refresh_token The refresh token received from POST /auth/accessToken
force_refresh When true, forces the authentication service to generate a new refresh token and expire the refresh token specified in the refresh_token field passed to the call.

 When true a new refresh_token is included in the response.

 Default is false.
grant_type The type of access to grant. Set to refresh_token


Example POST /auth/refreshToken request

curl -X POST \
    https://[COMMUNITY DOMAIN]/api/2.1/auth/refreshToken \
    -H "Content-Type: application/json" \
    -H "client-id:[CLIENT ID]" \
    -d '{
            "client_id":"CbEwdj3DjslDJLsldk30823480lkaXvNLvA=",
            "client_secret":"BV32987skdjfhSDlkajdhfASDF409234ItWs=",
            "grant_type":"refresh_token",
            "refresh_token":"ZVQaoDdkcsC/9vKZUw0OHEvKG3nd/HoIdwdHLNFwB8E="
        }'


Example POST /auth/refreshToken response

{
    "response":{
        "status":"success",
        "message":"OK",
        "http_code":200,
        "data":{
            "access_token":"o5IV0yIiNDj/5lNJ6doJh08LX6SsDwtkDXDVmhGvRtI=",
            "expires_in":86400,
            "lithiumUserId":"2d8c95ed-21dc-4ba6-ab9f-d3eff9c928ce",
            "refresh_token":"NJIjGeQP3rsdE2Wz46gFExlWdLpwv1kRompX5szrnXY=",
            "token_type":"bearer"
        }
    }
}

Validate the access token

GET /auth/validateToken

If needed, you can validate your OAuth token with /auth/validateToken. Generally, you will not need to perform token validation.

Header Parameters

Header Parameter Description
client-id The client ID generated in Community Admin > Dev Tools
Authorization Bearer token
 where token is the OAuth token obtained on behalf of the user


Example GET /validateToken request

curl -X GET \
https://[COMMUNITY DOMAIN]/api/2.1/auth/validateToken \
-H 'Authorization: Bearer <access_token>'


Example GET /validateToken response

{
    "status": "success",
    "message": "",
    "data": {
        "valid": true,
        "clientId": "<client-id>",
        "clientSecret": "<client-secret>",
        "lithiumUserUuid": "<user uuid>"
    }
}

Invalidate the access token

POST /auth/invalidateToken

If your token is compromised, you can invalidate it with /auth/invalidateToken. No body is required.

Header Parameters

Header Parameter Description
client-id The client ID generated in Community Admin > Dev Tools
Authorization Bearer token
 where token is the OAuth token obtained on behalf of the user


Example POST /invalidateToken request

curl -X POST \
https://[COMMUNITY DOMIAN]/api/2.1/auth/invalidateToken \
-H 'Authorization: Bearer <access_token>'


Example POST /invalidateToken response

{
    "status": "success",
    "message": "",
    "data": {}
}
Choose files or drag and drop files
Was this article helpful?
Yes
No
  1. ATLAS

  2. Posted
  3. Updated

Comments