OAuth2 Authorization Code Grant Credentials (Web Applications)

The OAuth2 Authorization Code Grant is described in the RFC6749. This provides the ability for a user to grant access to your web application. Your application will be able to make the API requests on behalf of multiple users. This is both easier and more secure than the client credentials grant.

With this workflow, the user will not need to copy/paste any credentials and just click a button to authorize the client.

An authorization code grant credential workflow follows these steps:

  1. Create a single client for your application.

    Note: This should only be done once.

  2. Put a link on your web application. When the user clicks on the link, they are redirected to IROH, and they can grant access to your application. The user returns to your web application with a secret code and you can retrieve a refresh token that you should keep securely.

    Note: This should only be done once per user.

  3. With the refresh token, you can retrieve an access token without user interaction.

    Note: This should only be done when you want to call the API and the access token has expired (every 10 minutes by default).

  4. The access token is used to call the IROH APIs on behalf of the user.

    Note: This should be done for all API calls. We recommend to cache the access tokens and not to call the refresh token for each API call to IROH.

Create a Client

There are two ways to create a client:

  1. Using the Cisco XDR UI
  2. Using the API (via the Swagger UI interface)

Both ways will result in the same outcome. But, before creating the Authorization Code Grant client, read this section in its entirety to determine the correct client configuration settings.

Mandatory Configuration Settings

  1. During client creation, you must set the field grants to ["auth-code"] in order to support Authorization Code Grant workflow.
  2. If you want to be autonomous, you’ll need to have control of an HTTPS URL (generally something along https://my.domain.tld/path/to/callback). This is the URL you’ll use to set in the redirects value of the client.

Depending on the information you provide during client creation, the client won’t be automatically approved. The client will be approved during creation if all the following conditions are met:

For more details about each field, refer to OAuth2 Client Model.

Optional Configuration Settings

  • Provide Access to All Users

If you need to open your web application to all users and not only to the members of your organization, you will need to create a client with the availability field equal to everyone. The client won’t be approved and you’ll need to reach out to a IROHadministrator to approve it.

  • Redirect to Localhost Without HTTPS

For clients with availability set to everyone, every URI in the redirects array must be https. If you need to you use another scheme in your URI, then you will need to reach out an administrator to approve your client.

  • Create a Public Client

If your application is a front-end only application, having a password does not make sense. For this specific case, it is recommended (by the RFC) to not use the Implicit grant. Instead, use an Authorization Code Grant client without any password. In this case you must set the client-type to public.

This is also a very specific need. You will need to request approval from a IROH administrator.

  • Change Access Token Lifetime

The current default lifetime of access token is 10 minutes. The current default lifetime for refresh token is unlimited.

If you want a longer lived access token or shorter lived refresh token, you simply need to set the fields access-token-lifetime-in-sec and refresh-token-lifetime-in-sec when creating your client. You will need to request a IROH administrator approve your client.

After a refresh-token lifetime, the refresh token will not work anymore. After half the lifetime, when getting a new access token, you will also get an updated refresh token with the same lifetime. It is then up to you to perform a new refresh token call during the second half or one hour before the expiration to get a new refresh token. After a new refresh token is provided, the old one can be revoked anytime so you should cease using the old refresh token.

Without a valid refresh token you will be forced to re-engage the user in an interactive authorization workflow.

For more details about each field, refer to the section OAuth2 Client Model.

Using the Cisco XDR UI

Before creating a client, make sure to read the Mandatory Configuration Settings in its entirety to determine the correct client configuration settings.

Note: When creating an OAuth Code Client, there is an auto-approve feature if all the criterias are met. If some criterias are not met, the client is created but disabled until it has been approved by an administrator.

For details on how to create OAuth Code Client credentials, see API Clients.

Using the API (via the Swagger UI Interface)

Before creating a client, make sure to read the Client Configurations in its entirety to determine the correct client configuration settings.

The Swagger UI interface will provide raw access to the API to create a client. However, the only way to work with this API is by using a JWT with the oauth scope.

Retrieve the list of your scopes. You will not be able to create a client with more scopes than you’re allowed to access.

To get the list of scopes, use the /iroh/profile/whoami API:

  1. Open the whoami API Swagger UI interface: https://visibility.amp.cisco.com/iroh/profile/#!/Profile/get_iroh_profile_whoami.

  2. If you are already logged in to https://visibility.amp.cisco.com/, you will not need to enter any information in the Authorization header inputs in Swagger. If not, click Authorize and provide authorization either with a IROH login, apiKey, or OAuth2 credentials.

  3. Click Try it out to the right of Parameters.

  4. Click Execute.

    Under Server response, assuming you received a HTTP status code of 200, you will find the response from the API request. It is a JSON containing your user and org information including the list of your scopes.

Here is example response from the /iroh/profile/whoami API:

{
    "user": {
        "scopes": [
            "admin",
            "casebook",
            "cisco",
            "collect",
            "enrich",
            "global-intel:read",
            "inspect",
            "integration",
            "oauth",
            "private-intel",
            "profile",
            "response",
            "ui-settings"
            "users"
        ],
        "updated-at": "2019-04-30T13:54:21.641Z",
        "user-email": "dev.null@cisco.com",
        "org-id": "13375cf9-561c-4958-0000-6d84b7ef09d4",
        "user-id": "idb-amp:13375ee9-2e3a-4e1b-977d-961facb5fd84",
        "idp-mappings": [{
            "idp": "idb-amp",
            "user-identity-id": "13375ee9-2e3a-4e1b-977d-961facb5fd84",
            "organization-id": "13375cf9-561c-4958-0000-6d84b7ef09d4"
        }],
        "enabled?": true,
        "last-logged-at": [
            "2019-04-30T13:54:21.843Z"
        ],
        "created-at": "2019-04-30T13:54:21.622Z"
    },
    "org": {
        "scim-status": "activated",
        "name": "IROH Testing",
        "enabled?": true,
        "id": "13375cf9-561c-4958-0000-6d84b7ef09d4",
        "created-at": "2019-04-30T13:54:21.634Z"
    }
}

For a description of each field, refer to the User Model section on the Data Model page.

Now that you know which scopes you have access to, you can create the client.

To use the /iroh/oauth2-clients/clients API:

  1. Open the clients API Swagger UI interface: https://visibility.amp.cisco.com/iroh/oauth2-clients/index.html#/OAuth2Client/post_iroh_oauth2_clients_clients.
  2. Click Try it out to the right of Parameters.
  3. Edit the JSON under CreateClientParams with the configuration for the client. For a description of each field, refer to the section OAuth2 Client Model.
  4. Click Execute.

Under the Server response section, assuming you received a HTTP status code of 200, you will find the response from the API request. For a description of each field in the response, refer to OAuth2 Client Model.

Use the Client

If you have not yet created a client that can be used for Authorization Code Grant, refer to Create a Client.

If you have successfully created the client and it is approved, you should have the following information:

  • client-id
  • client-password
  • redirect-uri; one of the URL(s) you set in the redirects array of the client
  • scopes; the list of scopes required for your application

You will also need to know the authorization and token URLs of IROH. You can get them at the metadata endpoint (c.f. OAuth2 Metadata).

Present the URL to the User

The first step is to present the user with the URL (return line here is for readability only):

https://visibility.amp.cisco.com/iroh/oauth2/authorization?
   response_type=code
   &client_id=YOUR_CLIENT_ID
   &redirect_uri=YOUR_REDIRECT_URL
   &scope=LIST_OF_SCOPES_SPACE_SEPARATED
   &state=A_DIFFICULT_TO_GUESS_RANDOM_STRING

Once the user clicks on the link, they will be redirected to IROH and asked to grant access to your web application. If the user accepts or refuses, the user will be redirected to the redirect uri with parameters that will contain further information.

Get the Refresh Token

Listen to your redirect_uri and parse the query parameters. An example of the URL the user will be redirected to after granting your app the access would be:

YOUR_REDIRECT_URL?state=A_DIFFICULT_TO_GUESS_RANDOM_STRING&code=SOME_CODE

Then, you must verify that the value of the state is the same one the user has clicked. (In our example, the state must be A_DIFFICULT_TO_GUESS_RANDOM_STRING.)

Next, get the refresh token by using the /iroh/oauth2/token API with the value of the code query parameter in the request parameters.

Here is an example API request to /iroh/oauth2/token using a cURL command:

curl -X POST \
     -u "YOUR_CLIENT_ID:YOUR_CLIENT_PASSWORD" \
     -H "Content-Type: application/x-www-form-urlencoded" \
     -d "grant_type=authorization_code&redirect_uri=YOUR_REDIRECT_URL&code=SOME_CODE" \
     'https://visibility.amp.cisco.com/iroh/oauth2/token'

The -u is to use Basic Auth, with client-id as user and client-password as password. In order to manually supply the correct header, you must base64 encode the client_id:client_password string. The following two code examples are interchangeable:

curl -u "client_id:client_password" https://example.com

and

creds=$(echo -n client_id:client_password | base64)
curl -H "Authorization: Basic $creds" https://example.com

It is also important to set the content type to application/x-www-form-urlencoded. The route does not support parameters sent via a JSON Content-Type (cf. RFC6749 section 4.1.3).

The server should then return a successful response (cf. RFC6749 section 4.1.4):

{
    "access_token":"eyJhbG...",
    "token_type":"bearer",
    "expires_in":600,
    "refresh_token":"eJJyFFA..."
}

IMPORTANT: The POST to the /token route exposes your client password, so it must be done on the server and not within the browser.

You should have both an access token and a refresh token. The access token will expire in 600 seconds. But the refresh token shouldn’t expire soon. Make sure to save the refresh token for your user. Each time you need a new access token, you’ll need the refresh token.

Make an API Request Using the Access Token

Now that you have retrieved the access token (which is a JWT), you can make an API request on behalf of the user. However, it will be restricted to the scope they granted your application.

Here is an example request using the access token:

ACCESS_TOKEN="eyJhbGciO..."
curl -X POST \
    -H 'Accept: application/json' \
    -H 'Content-Type: application/json' \
    -H "Authorization: Bearer $ACCESS_TOKEN" \
    -d '{"content":"cisco.com"}' \
    'https://visibility.amp.cisco.com}/iroh/iroh-inspect/inspect'

To see an exhaustive list of APIs with links to their swagger UI interfaces and a list of scopes, see Authorization Access / Scopes.

Get a New Access Token

The access token will expire (default is 10 minutes). API access after token expiration will require user interaction. You will need to use the refresh token of the user to get a new access token.

The request to refresh a token uses the same API you used to get it the first time. But instead of using a grant_type of authorization_code, you will use a grant_type equal to refresh_token (cf. RFC6749 section 6).

Example request:

curl -X POST \
     -u "YOUR_CLIENT_ID:YOUR_CLIENT_PASSWORD" \
     -H "Content-Type: application/x-www-form-urlencoded" \
     -d "grant_type=refresh_token&refresh_token=REFRESH_TOKEN" \
     'https://visibility.amp.cisco.com/iroh/oauth2/token'

The server should then return a successful response:

{
    "access_token":"eyJhbG...",
    "token_type":"bearer",
    "expires_in":600
}

IMPORTANT: The response might also contain a new refresh token along with the new access token. In that case, you must revoke the old refresh token and use the new one instead. IROH might accept the old refresh token for a short period to prevent bugs in distributed environments.

Tutorial

This section provides complete example. The credentials used will not be functional, but you should be able to follow all the steps with your own credentials.

Clone Demo Project

Clone the demo project from: https://github.com/yogsototh/oauth2-client-demo

Serve it to your own domain, possibly in some directory. This tutorial assumes it will be: https://my.domain.tld/ctr-oauth/

If you cannot test directly from your domain and want to test on localhost check the Run Demo on localhost section for instructions.

Create the Client

Use the /iroh/oauth2-clients/clients API to create the client.

Here is an example API request to /iroh/oauth2-clients/clients using a cURL command:

ACCESS_TOKEN="eyJhbGciO..."
curl -X 'POST' \
   \
    -H 'Accept: application/json' \
    -H 'Content-Type: application/json' \
    -H 'User-Agent: ob-http' \
    -H 'Authorization: Bearer $ACCESS_TOKEN" \
    -d '{
        "scopes": [ "profile", "inspect" ],
        "description": "Developer Doc OAuth2 Test Client",
        "redirects": [ "https://my.domain.tld/ctr-oauth/callback.html" ],
        "availability": "org",
        "name": "OAuth2 Developer Doc Test",
        "grants": [ "auth-code" ],
        "client-type": "confidential"
    }' \
    'https://visibility.amp.cisco.com/iroh/oauth2-clients/clients'

The server should then return a successful response:

{
  "scopes": [
    "profile",
    "inspect"
  ],
  "description": "Developer Doc OAuth2 Test Client",
  "approved?": true,
  "redirects": [
    "https://my.domain.tld/ctr-oauth/callback.html"
  ],
  "availability": "org",
  "password": "CrXwg31_vnRHpjPXzgVzUFKHr6RO8GTL-iI8aDeUU3n48NtD7PFLhg",
  "name": "OAuth2 Developer Doc Test",
  "org-id": "f47a89bf-5d2e-4392-b770-000000000000",
  "enabled?": true,
  "grants": [
    "auth-code"
  ],
  "client-type": "confidential",
  "id": "client-3bb1e787-381d-4f12-bf32-e1158f200ddc",
  "approval-status": "approved",
  "owner-id": "f0010924-e1bc-4b03-b600-000000000000",
  "created-at": "2019-07-25T14:15:29.117Z"
}

For a description of each field in the response, refer to the section OAuth2 Client Model.

Configure the Demo

Edit the info.js to look like:

var oauthURLPrefix="https://visibility.amp.cisco.com";
var oauthServerUrl=oauthURLPrefix + "/iroh/oauth2/authorize";
var oauthServerTokenUrl=oauthURLPrefix + "/iroh/oauth2/token";
var resourceProviderTestEndpoint=oauthURLPrefix + "/iroh/profile/whoami" ;
var response_type="code";
var client_id="client-3bb1e787-381d-4f12-bf32-e1158f200ddc";
var client_password = "CrXwg31_vnRHpjPXzgVzUFKHr6RO8GTL-iI8aDeUU3n48NtD7PFLhg";
var redirect_uri="https://my.domain.tld/ctr-oauth/callback.html";
var scopes=[ "profile", "inspect" ];
var scope=scopes.join(" ");
var state="whatever=";

Run the Demo

  1. Go to the URL where the demo project was served on your domain (or localhost). In this tutorial, it is https://my.domain.tld/ctr-oauth/index.html.
  2. Click the link. You will be redirected to IROH
  3. Authorize the client.
  4. Now back at https://my.domain.tld/ctr-oauth/callback.html, you should inspect the request in your browser and play with the demo.
  5. Retrieve the access token and refresh token using the value of the code query parameter.
  6. Get another access token using the refresh token.

Details About Steps in the Demo

While the workflow necessitates user interaction through the browser, we will describe most requests in detail.

  • Code in callback URL

The user interaction is only needed to authorize the client. They will then visit the URL https://my.domain.tld/ctr-oauth/callback.html and pass the query parameters code and state.

Here is an example URL:

https://my.domain.tld/ctr-oauth/callback.html?
  code=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJodHRwczpcL1wvc2NoZW1hcy5jaXNjby5jb21cL2lyb2hcL2lkZW50aXR5XC9jbGFpbXNcL3VzZXJcL2VtYWlsIjoieWFlc3Bvc2lAY2lzY28uY29tIiwiaHR0cHM6XC9cL3NjaGVtYXMuY2lzY28uY29tXC9pcm9oXC9pZGVudGl0eVwvY2xhaW1zXC91c2VyXC9zY29wZXMiOlsiaXJvaC1hZG1pbiIsImludGVncmF0aW9uIiwicHJpdmF0ZS1pbnRlbCIsImFkbWluIiwicHJvZmlsZSIsImluc3BlY3QiLCJpcm9oLWF1dGgiLCJzc2UiLCJ1c2VycyIsImNpc2NvIiwiY2FzZWJvb2siLCJvcmJpdGFsIiwiZW5yaWNoIiwib2F1dGgiLCJnbG9iYWwtaW50ZWwiLCJjb2xsZWN0IiwicmVzcG9uc2UiLCJ1aS1zZXR0aW5ncyJdLCJodHRwczpcL1wvc2NoZW1hcy5jaXNjby5jb21cL2lyb2hcL2lkZW50aXR5XC9jbGFpbXNcL3VzZXJcL25pY2siOiJZYW5uIEVzcG9zaXRvIiwiZW1haWwiOiJ5YWVzcG9zaUBjaXNjby5jb20iLCJpc3MiOiJJUk9IIEF1dGgiLCJodHRwczpcL1wvc2NoZW1hcy5jaXNjby5jb21cL2lyb2hcL2lkZW50aXR5XC9jbGFpbXNcL3Njb3BlcyI6WyJwcm9maWxlIiwiaW5zcGVjdCJdLCJleHAiOjE1NjQxMjk4NDcsImh0dHBzOlwvXC9zY2hlbWFzLmNpc2NvLmNvbVwvaXJvaFwvaWRlbnRpdHlcL2NsYWltc1wvb2F1dGhcL3VzZXJcL2lkIjoiZjAwMTA5MjQtZTFiYy00YjAzLWI2MDAtODljNmNmNTI3NTdjIiwiaHR0cHM6XC9cL3NjaGVtYXMuY2lzY28uY29tXC9pcm9oXC9pZGVudGl0eVwvY2xhaW1zXC9vcmdcL2lkIjoiZjQ3YTg5YmYtNWQyZS00MzkyLWI3NzAtYWQ0ODIxYTgyYWNmIiwiaHR0cHM6XC9cL3NjaGVtYXMuY2lzY28uY29tXC9pcm9oXC9pZGVudGl0eVwvY2xhaW1zXC9vYXV0aFwvZ3JhbnQiOiJhdXRoLWNvZGUiLCJqdGkiOiJmMjFiMDU5NS04YzhjLTRkZTktOGI4MS01NWVmZTIwMThlODMiLCJuYmYiOjE1NjQxMjkxODcsImh0dHBzOlwvXC9zY2hlbWFzLmNpc2NvLmNvbVwvaXJvaFwvaWRlbnRpdHlcL2NsYWltc1wvb2F1dGhcL3Njb3BlcyI6WyJwcm9maWxlIiwiaW5zcGVjdCJdLCJodHRwczpcL1wvc2NoZW1hcy5jaXNjby5jb21cL2lyb2hcL2lkZW50aXR5XC9jbGFpbXNcL3VzZXJcL25hbWUiOiJZYW5uIEVzcG9zaXRvIiwiaHR0cHM6XC9cL3NjaGVtYXMuY2lzY28uY29tXC9pcm9oXC9pZGVudGl0eVwvY2xhaW1zXC91c2VyXC9pZCI6ImYwMDEwOTI0LWUxYmMtNGIwMy1iNjAwLTg5YzZjZjUyNzU3YyIsImh0dHBzOlwvXC9zY2hlbWFzLmNpc2NvLmNvbVwvaXJvaFwvaWRlbnRpdHlcL2NsYWltc1wvb2F1dGhcL2NsaWVudFwvaWQiOiJjbGllbnQtM2JiMWU3ODctMzgxZC00ZjEyLWJmMzItZTExNThmMjAwZGRjIiwiaWF0IjoxNTY0MTI5MjQ3LCJodHRwczpcL1wvc2NoZW1hcy5jaXNjby5jb21cL2lyb2hcL2lkZW50aXR5XC9jbGFpbXNcL29hdXRoXC9raW5kIjoiY29kZS10b2tlbiJ9.IL5xGEfcwnKpd2KNMyo2_kNtkEsfwTa6vYKJHR6uF3L3CGX7edat_eYXNmLACgamX3pdYfXo8JAHEOvdr7zl6-fLq0SHlFdxy4pbVQbr8gJt6TAZVWgNu8wxJfTzL6-V0oIv6mcYD2NWTXYoA8R19u6iFnOtoTwXVx58Dk2UXQuueHmq2CejpJspGgjChAHsebh1XKl-6uPo7debCQvrzPhB56lGShKT0NgEqT_ZML032iFqGIBHUe6WdlqO_i6ji1-QX3CPmA_rwep7n0h1RuDxWib9YCtwJFh0SO0AQX_bK-0000000000000000000000000000000000000000
  &state=y5jaXNjby5jb21cL2lyb2hcL2lkZW

The code represents an agreement from a IROH user to grant access to your application. Remember OAuth2 Authorization Code Grant is a contract between three entities: your application (the client), the user, and IROH. The code query parameter is a JWT. Once decoded it contains:

{
   "https://schemas.cisco.com/iroh/identity/claims/user/email":"dev.null@cisco.com",
   "https://schemas.cisco.com/iroh/identity/claims/user/scopes":[
       "integration",
       "private-intel",
       "admin",
       "profile",
       "inspect",
       "sse",
       "users",
       "casebook",
       "enrich",
       "oauth",
       "global-intel:read",
       "collect",
       "response",
       "ui-settings"
   ],
   "https://schemas.cisco.com/iroh/identity/claims/user/nick":"Yann Esposito",
   "email":"dev.null@cisco.com",
   "iss":"IROH Auth",
   "https://schemas.cisco.com/iroh/identity/claims/scopes":[
       "profile",
       "inspect"
   ],
   "exp":1564129847,
   "https://schemas.cisco.com/iroh/identity/claims/oauth/user/id":"f0010924-e1bc-4b03-b600-000000000000",
   "https://schemas.cisco.com/iroh/identity/claims/org/id":"f47a89bf-5d2e-4392-b770-000000000000",
   "https://schemas.cisco.com/iroh/identity/claims/oauth/grant":"auth-code",
   "jti":"f21b0595-8c8c-4de9-8b81-55efe2018e83",
   "nbf":1564129187,
   "https://schemas.cisco.com/iroh/identity/claims/oauth/scopes":[
       "profile",
       "inspect"
   ],
   "https://schemas.cisco.com/iroh/identity/claims/user/name":"Yann Esposito",
   "https://schemas.cisco.com/iroh/identity/claims/user/id":"f0010924-e1bc-4b03-b600-000000000000",
   "https://schemas.cisco.com/iroh/identity/claims/oauth/client/id":"client-3bb1e787-381d-4f12-bf32-000000000000",
   "iat":1564129247,
   "https://schemas.cisco.com/iroh/identity/claims/oauth/kind":"code-token"
}

The JWT claims are detailed in the Call the API / JWT section. Note that the JWT contains three different claims related to scopes: the user scopes, the scope the user agreed to grant and the the scopes the client asked for.

Another field to note is the oauth/kind that contains code-token. This JWT can only be used as a temporary code during the OAuth2 workflow.

Also notice the expiration date (exp) is just 10 minutes after the creation date (iat).

IMPORTANT: Your client must check that the state parameter is the same as the state parameter in the link the user clicked on. Each time you present a link to grant your application to a user, you should generate a new strong random string.

  • Get the access and refresh token with the code

With the code token (you don’t need to decode it), you can get a refresh token and an access token.

Here is an example API request to /iroh/oauth2/token using a cURL command (return line here is for readability only):

client_id="client-38bbc74d..."
client_password="FIz1FDf40..."
curl -X POST \
   -u "$client_id:$client_password" \
   -H 'Accept: application/json' \
   -H 'Content-Type: application/x-www-form-urlencoded' \
   -H 'User-Agent: ob-http' \
   -d 'redirect_uri=https%3A%2F%2Fmy.domain.tld%2Fctr-oauth%2Fcallback.html
      &grant_type=authorization_code
      &scope=profile%2533inspect
      &code=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJodHRwczpcL1wvc2NoZW1hcy5jaXNjby5jb21cL2lyb2hcL2lkZW50aXR5XC9jbGFpbXNcL3VzZXJcL2VtYWlsIjoieWFlc3Bvc2lAY2lzY28uY29tIiwiaHR0cHM6XC9cL3NjaGVtYXMuY2lzY28uY29tXC9pcm9oXC9pZGVudGl0eVwvY2xhaW1zXC91c2VyXC9zY29wZXMiOlsiaXJvaC1hZG1pbiIsImludGVncmF0aW9uIiwicHJpdmF0ZS1pbnRlbCIsImFkbWluIiwicHJvZmlsZSIsImluc3BlY3QiLCJpcm9oLWF1dGgiLCJzc2UiLCJ1c2VycyIsImNpc2NvIiwiY2FzZWJvb2siLCJvcmJpdGFsIiwiZW5yaWNoIiwib2F1dGgiLCJnbG9iYWwtaW50ZWwiLCJjb2xsZWN0IiwicmVzcG9uc2UiLCJ1aS1zZXR0aW5ncyJdLCJodHRwczpcL1wvc2NoZW1hcy5jaXNjby5jb21cL2lyb2hcL2lkZW50aXR5XC9jbGFpbXNcL3VzZXJcL25pY2siOiJZYW5uIEVzcG9zaXRvIiwiZW1haWwiOiJ5YWVzcG9zaUBjaXNjby5jb20iLCJpc3MiOiJJUk9IIEF1dGgiLCJodHRwczpcL1wvc2NoZW1hcy5jaXNjby5jb21cL2lyb2hcL2lkZW50aXR5XC9jbGFpbXNcL3Njb3BlcyI6WyJwcm9maWxlIiwiaW5zcGVjdCJdLCJleHAiOjE1NjQxMzA5NTAsImh0dHBzOlwvXC9zY2hlbWFzLmNpc2NvLmNvbVwvaXJvaFwvaWRlbnRpdHlcL2NsYWltc1wvb2F1dGhcL3VzZXJcL2lkIjoiZjAwMTA5MjQtZTFiYy00YjAzLWI2MDAtODljNmNmNTI3NTdjIiwiaHR0cHM6XC9cL3NjaGVtYXMuY2lzY28uY29tXC9pcm9oXC9pZGVudGl0eVwvY2xhaW1zXC9vcmdcL2lkIjoiZjQ3YTg5YmYtNWQyZS00MzkyLWI3NzAtYWQ0ODIxYTgyYWNmIiwiaHR0cHM6XC9cL3NjaGVtYXMuY2lzY28uY29tXC9pcm9oXC9pZGVudGl0eVwvY2xhaW1zXC9vYXV0aFwvZ3JhbnQiOiJhdXRoLWNvZGUiLCJqdGkiOiI2NWU4MGE0Yi03YTM2LTQzNDEtOGI0NC0zZTM2MTk4YjRiMTQiLCJuYmYiOjE1NjQxMzAyOTAsImh0dHBzOlwvXC9zY2hlbWFzLmNpc2NvLmNvbVwvaXJvaFwvaWRlbnRpdHlcL2NsYWltc1wvb2F1dGhcL3Njb3BlcyI6WyJwcm9maWxlIiwiaW5zcGVjdCJdLCJodHRwczpcL1wvc2NoZW1hcy5jaXNjby5jb21cL2lyb2hcL2lkZW50aXR5XC9jbGFpbXNcL3VzZXJcL25hbWUiOiJZYW5uIEVzcG9zaXRvIiwiaHR0cHM6XC9cL3NjaGVtYXMuY2lzY28uY29tXC9pcm9oXC9pZGVudGl0eVwvY2xhaW1zXC91c2VyXC9pZCI6ImYwMDEwOTI0LWUxYmMtNGIwMy1iNjAwLTg5YzZjZjUyNzU3YyIsImh0dHBzOlwvXC9zY2hlbWFzLmNpc2NvLmNvbVwvaXJvaFwvaWRlbnRpdHlcL2NsYWltc1wvb2F1dGhcL2NsaWVudFwvaWQiOiJjbGllbnQtM2JiMWU3ODctMzgxZC00ZjEyLWJmMzItZTExNThmMjAwZGRjIiwiaWF0IjoxNTY0MTMwMzUwLCJodHRwczpcL1wvc2NoZW1hcy5jaXNjby5jb21cL2lyb2hcL2lkZW50aXR5XC9jbGFpbXNcL29hdXRoXC9raW5kIjoiY29kZS10b2tlbiJ9.yrOZloNpYGrs0eIWk9dVl-OoSgnSggTcCGrS-iPyhsefZ48SFeoWYtiktki8-uRi6hCjYwQ7WMOQ-MQ9Fr7w4ELMNZJeBSHZjHFty-wH_Fmx62NkVzdAty9pALD2sgqBMS44NWPlyzni1h7sP7wRRxr70o4XdPZUD-wIyjmM0Ewtf0tB-MEPfdXm51na-xt3RAd_hoCP3CubuSPYCDp9dQ-9AOzAAJfogRGboI_u1I38oMY_x_GRZUdyLdOHvVz4XaoBUfRgwS-C7eVu73ULavfJmd5W4UaO_LNV9oNgxQQD9B9JlLs7dMVzFxe6UaYi8KXUdk-qZRD5Px_lth7uVw'
   'https://visibility.amp.cisco.com/iroh/oauth2/token'

Here is an example response from the /iroh/oauth2/token API:

{
   "access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJodHRwczpcL1wvc2NoZW1hcy5jaXNjby5jb21cL2lyb2hcL2lkZW50aXR5XC9jbGFpbXNcL3VzZXJcL2VtYWlsIjoieWFlc3Bvc2lAY2lzY28uY29tIiwiaHR0cHM6XC9cL3NjaGVtYXMuY2lzY28uY29tXC9pcm9oXC9pZGVudGl0eVwvY2xhaW1zXC91c2VyXC9zY29wZXMiOlsiaXJvaC1hZG1pbiIsImludGVncmF0aW9uIiwicHJpdmF0ZS1pbnRlbCIsImFkbWluIiwicHJvZmlsZSIsImluc3BlY3QiLCJpcm9oLWF1dGgiLCJzc2UiLCJ1c2VycyIsImNpc2NvIiwiY2FzZWJvb2siLCJvcmJpdGFsIiwiZW5yaWNoIiwib2F1dGgiLCJnbG9iYWwtaW50ZWwiLCJjb2xsZWN0IiwicmVzcG9uc2UiLCJ1aS1zZXR0aW5ncyJdLCJodHRwczpcL1wvc2NoZW1hcy5jaXNjby5jb21cL2lyb2hcL2lkZW50aXR5XC9jbGFpbXNcL3VzZXJcL25pY2siOiJZYW5uIEVzcG9zaXRvIiwiZW1haWwiOiJ5YWVzcG9zaUBjaXNjby5jb20iLCJzdWIiOiJmMDAxMDkyNC1lMWJjLTRiMDMtYjYwMC04OWM2Y2Y1Mjc1N2MiLCJpc3MiOiJJUk9IIEF1dGgiLCJodHRwczpcL1wvc2NoZW1hcy5jaXNjby5jb21cL2lyb2hcL2lkZW50aXR5XC9jbGFpbXNcL3Njb3BlcyI6WyJwcm9maWxlIiwiaW5zcGVjdCJdLCJleHAiOjE1NjQxMzA5NzMsImh0dHBzOlwvXC9zY2hlbWFzLmNpc2NvLmNvbVwvaXJvaFwvaWRlbnRpdHlcL2NsYWltc1wvb2F1dGhcL3VzZXJcL2lkIjoiZjAwMTA5MjQtZTFiYy00YjAzLWI2MDAtODljNmNmNTI3NTdjIiwiaHR0cHM6XC9cL3NjaGVtYXMuY2lzY28uY29tXC9pcm9oXC9pZGVudGl0eVwvY2xhaW1zXC9vcmdcL2lkIjoiZjQ3YTg5YmYtNWQyZS00MzkyLWI3NzAtYWQ0ODIxYTgyYWNmIiwiaHR0cHM6XC9cL3NjaGVtYXMuY2lzY28uY29tXC9pcm9oXC9pZGVudGl0eVwvY2xhaW1zXC9vYXV0aFwvZ3JhbnQiOiJhdXRoLWNvZGUiLCJqdGkiOiI1Y2Y1NGRkMi0zMmNlLTRkOTctODEzYy0wZWFiYzZlZWI1MjEiLCJuYmYiOjE1NjQxMzAzMTMsImh0dHBzOlwvXC9zY2hlbWFzLmNpc2NvLmNvbVwvaXJvaFwvaWRlbnRpdHlcL2NsYWltc1wvb2F1dGhcL3Njb3BlcyI6WyJwcm9maWxlIiwiaW5zcGVjdCJdLCJodHRwczpcL1wvc2NoZW1hcy5jaXNjby5jb21cL2lyb2hcL2lkZW50aXR5XC9jbGFpbXNcL3VzZXJcL25hbWUiOiJZYW5uIEVzcG9zaXRvIiwiaHR0cHM6XC9cL3NjaGVtYXMuY2lzY28uY29tXC9pcm9oXC9pZGVudGl0eVwvY2xhaW1zXC91c2VyXC9pZCI6ImYwMDEwOTI0LWUxYmMtNGIwMy1iNjAwLTg5YzZjZjUyNzU3YyIsImh0dHBzOlwvXC9zY2hlbWFzLmNpc2NvLmNvbVwvaXJvaFwvaWRlbnRpdHlcL2NsYWltc1wvb2F1dGhcL2NsaWVudFwvaWQiOiJjbGllbnQtM2JiMWU3ODctMzgxZC00ZjEyLWJmMzItZTExNThmMjAwZGRjIiwiaHR0cHM6XC9cL3NjaGVtYXMuY2lzY28uY29tXC9pcm9oXC9pZGVudGl0eVwvY2xhaW1zXC92ZXJzaW9uIjoidjEuMjAuMC1kZjgxNGU3YjYyODMwZGRkNTc2ZCIsImlhdCI6MTU2NDEzMDM3MywiaHR0cHM6XC9cL3NjaGVtYXMuY2lzY28uY29tXC9pcm9oXC9pZGVudGl0eVwvY2xhaW1zXC9vYXV0aFwva2luZCI6ImFjY2Vzcy10b2tlbiJ9.tZ75vCYYst9gSbnZl7LZ3GiVXRpAmOFy9cmUs9wGkSw7XSdRN-4sqwUkcCoNq161piZedf17PrGRMurEtq9x8cW1_YuU_5pi9mDMH1ayQYNXJXkk6G_PJTbzyBLosdp3IAc_GN7DrCZoHx9-oveCy0MfXTbgrjtsx7BoELynECbjTPAfi8CU_rPRCnIyrxLTFMJdqLHsUVP_MDyXEvV43EPw1uRUn9ZBf-dBAswdFsEhH8RF4IFtZyDxb49HTpoWHA54jFWiYAP3cISyS6IKI8H1aVQHAUDbdSzunx0Rp5U9xJysZiAZzVkiSUGTJqXQt_00000000000000000000",
   "refresh_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJodHRwczpcL1wvc2NoZW1hcy5jaXNjby5jb21cL2lyb2hcL2lkZW50aXR5XC9jbGFpbXNcL3VzZXJcL2VtYWlsIjoieWFlc3Bvc2lAY2lzY28uY29tIiwiaHR0cHM6XC9cL3NjaGVtYXMuY2lzY28uY29tXC9pcm9oXC9pZGVudGl0eVwvY2xhaW1zXC91c2VyXC9zY29wZXMiOlsiaXJvaC1hZG1pbiIsImludGVncmF0aW9uIiwicHJpdmF0ZS1pbnRlbCIsImFkbWluIiwicHJvZmlsZSIsImluc3BlY3QiLCJpcm9oLWF1dGgiLCJzc2UiLCJ1c2VycyIsImNpc2NvIiwiY2FzZWJvb2siLCJvcmJpdGFsIiwiZW5yaWNoIiwib2F1dGgiLCJnbG9iYWwtaW50ZWwiLCJjb2xsZWN0IiwicmVzcG9uc2UiLCJ1aS1zZXR0aW5ncyJdLCJodHRwczpcL1wvc2NoZW1hcy5jaXNjby5jb21cL2lyb2hcL2lkZW50aXR5XC9jbGFpbXNcL3VzZXJcL25pY2siOiJZYW5uIEVzcG9zaXRvIiwiZW1haWwiOiJ5YWVzcG9zaUBjaXNjby5jb20iLCJpc3MiOiJJUk9IIEF1dGgiLCJodHRwczpcL1wvc2NoZW1hcy5jaXNjby5jb21cL2lyb2hcL2lkZW50aXR5XC9jbGFpbXNcL3Njb3BlcyI6WyJwcm9maWxlIiwiaW5zcGVjdCJdLCJleHAiOjE3NTE0MTQ0MDAwLCJodHRwczpcL1wvc2NoZW1hcy5jaXNjby5jb21cL2lyb2hcL2lkZW50aXR5XC9jbGFpbXNcL29hdXRoXC91c2VyXC9pZCI6ImYwMDEwOTI0LWUxYmMtNGIwMy1iNjAwLTg5YzZjZjUyNzU3YyIsImh0dHBzOlwvXC9zY2hlbWFzLmNpc2NvLmNvbVwvaXJvaFwvaWRlbnRpdHlcL2NsYWltc1wvb3JnXC9pZCI6ImY0N2E4OWJmLTVkMmUtNDM5Mi1iNzcwLWFkNDgyMWE4MmFjZiIsImh0dHBzOlwvXC9zY2hlbWFzLmNpc2NvLmNvbVwvaXJvaFwvaWRlbnRpdHlcL2NsYWltc1wvb2F1dGhcL2dyYW50IjoiYXV0aC1jb2RlIiwianRpIjoiMjc0YjkwYTAtZDlhNi00YmI2LWJiN2UtMDkzYTY4MzllMTUyIiwibmJmIjoxNTY0MTMwMzEzLCJodHRwczpcL1wvc2NoZW1hcy5jaXNjby5jb21cL2lyb2hcL2lkZW50aXR5XC9jbGFpbXNcL29hdXRoXC9zY29wZXMiOlsicHJvZmlsZSIsImluc3BlY3QiXSwiaHR0cHM6XC9cL3NjaGVtYXMuY2lzY28uY29tXC9pcm9oXC9pZGVudGl0eVwvY2xhaW1zXC91c2VyXC9uYW1lIjoiWWFubiBFc3Bvc2l0byIsImh0dHBzOlwvXC9zY2hlbWFzLmNpc2NvLmNvbVwvaXJvaFwvaWRlbnRpdHlcL2NsYWltc1wvdXNlclwvaWQiOiJmMDAxMDkyNC1lMWJjLTRiMDMtYjYwMC04OWM2Y2Y1Mjc1N2MiLCJodHRwczpcL1wvc2NoZW1hcy5jaXNjby5jb21cL2lyb2hcL2lkZW50aXR5XC9jbGFpbXNcL29hdXRoXC9jbGllbnRcL2lkIjoiY2xpZW50LTNiYjFlNzg3LTM4MWQtNGYxMi1iZjMyLWUxMTU4ZjIwMGRkYyIsImlhdCI6MTU2NDEzMDM3MywiaHR0cHM6XC9cL3NjaGVtYXMuY2lzY28uY29tXC9pcm9oXC9pZGVudGl0eVwvY2xhaW1zXC9vYXV0aFwva2luZCI6InJlZnJlc2gtdG9rZW4ifQ.abtBzZmX64XDTB7OJkcyCsOrGnXj-c6tSg89qg9ENnHSeBs-e4AhQMzHO5ZF5Cb4e7c8z34k0gxatuBqLTtLTztV32ktJGZ1IwFA4k7bpPrW1qdrSJQfZjOBBdLG3DSDMqo7dihqh_4VkfZGHDUNfao12xHTXCbzzfKiZNr6f8UJ0lzEvNZ2tQFkIMjdLVrN7OSk5K56-4SwEL6-X7LHRjF8M0FrGq9QU2lztuRyGXfbPOIal4wJdcfZ-Z2S1_fC82y-rE2mEDEX-diCI_oC_01wFiBbklJLoUEYK6Ry0000000000000000000000000000000000000000000000",
   "token_type": "bearer",
   "expires_in": 600,
   "scope": "profile inspect"
}

Notes:

  • The -u of the cURL command automatically encodes the $client_id:$client_password to base64 and adds it to the header as Basic Auth. If the request is not made with cURL, the Authorization header needs to be Basic Auth, which contains Basic followed by a base64 encoded CLIENT-ID:CLIENT-PASSWORD.

  • The body is not JSON. The Content-Type is application/x-www-form-urlencoded.

  • The access token will expires in 600 seconds.

  • Both the access_token and refresh_token are JWT.

  • Refresh Token

The refresh token is a JWT that once decoded contains:

{
   "https://schemas.cisco.com/iroh/identity/claims/user/email":"dev.null@cisco.com",
   "https://schemas.cisco.com/iroh/identity/claims/user/nick":"Yann Esposito",
   "email":"dev.null@cisco.com",
   "iss":"IROH Auth",
   "https://schemas.cisco.com/iroh/identity/claims/scopes":[
       "profile",
       "inspect"
   ],
   "exp":17514144000,
   "https://schemas.cisco.com/iroh/identity/claims/oauth/user/id":"f0010924-e1bc-4b03-b600-000000000000",
   "https://schemas.cisco.com/iroh/identity/claims/org/id":"f47a89bf-5d2e-4392-b770-000000000000",
   "https://schemas.cisco.com/iroh/identity/claims/oauth/grant":"auth-code",
   "jti":"64aae4a3-b99b-4215-8f63-c8bf46a4d4b5",
   "nbf":1564130650,
   "https://schemas.cisco.com/iroh/identity/claims/user/name":"Yann Esposito",
   "https://schemas.cisco.com/iroh/identity/claims/user/id":"f0010924-e1bc-4b03-b600-000000000000",
   "https://schemas.cisco.com/iroh/identity/claims/oauth/client/id":"client-3bb1e787-381d-4f12-00000000000000000",
   "iat":1564130710,
   "https://schemas.cisco.com/iroh/identity/claims/oauth/kind":"refresh-token"
}

Your application must save this refresh token for this user.

  • Access Token

The access token is also a JWT that you can use to make API requests. In our example, the client asked for the profile scope that grants access to the route /iroh/profile/whoami.

ACCESS_TOKEN="eyJhbGciO..."
curl -X 'GET' \
   -H 'Accept: application/json' \
   -H "Authorization: Bearer $ACCESS_TOKEN" \
   'https://visibility.amp.cisco.com/iroh/profile/whoami'

Here is an example response from the /iroh/profile/whoami API:

{
   "user":{
       "scopes":[
           "integration",
           "private-intel",
           "admin",
           "profile",
           "inspect",
           "iroh-auth",
           "sse",
           "users",
           "cisco",
           "casebook",
           "enrich",
           "oauth",
           "global-intel:read",
           "collect",
           "response",
           "ui-settings"
       ],
       "updated-at":"2019-07-25T14:53:21.721Z",
       "user-email":"dev.null@cisco.com",
       "user-name":"Yann Esposito",
       "org-id":"f47a89bf-5d2e-4392-b770-000000000000",
       "user-id":"f0010924-e1bc-4b03-b600-000000000000",
       "idp-mappings":[
           {
               "idp":"idb-amp",
               "user-identity-id":"f0010924-e1bc-4b03-b600-000000000000",
               "organization-id":"f47a89bf-5d2e-4392-b770-000000000000"
           }
       ],
       "enabled?":true,
       "last-logged-at":[
           "2019-07-25T14:53:22.183Z",
           "2019-07-25T13:05:50.488Z",
           "2019-07-19T14:37:09.021Z",
           "2019-07-18T12:11:51.297Z",
           "2019-07-12T14:58:36.694Z"
       ],
       "created-at":"2018-09-21T14:52:38.079Z",
       "user-nick":"Yann Esposito"
   },
   "org":{
       "scim-status":"activated",
       "name":"Cisco - IROH Team",
       "updated-at":"2019-07-22T15:27:10.845Z",
       "enabled?":true,
       "additional-scopes":[
           "integration",
           "admin",
           "sse"
       ],
       "settings":{
           "allow-all-role-to-login":false
       },
       "id":"f47a89bf-5d2e-4392-b770-000000000000",
       "created-at":"2018-09-06T04:44:12.512Z"
   }
}
  • Get a new access token with the refresh token

After a few minutes (10 minutes by default), the access token will expire. At that time, you will need to get a new access token, but you should not ask the user to authorize your application again in IROH.

You can get a new access token by using the /iroh/oauth2/token API with the refresh token for that user and your client credentials (return line here is for readability only):

client_id="client-38bbc74d..."
client_password="FIz1FDf40..."
curl -X POST \
   -u "$client_id:$client_password" \
   -H 'Accept: application/json' \
   -H 'Content-Type: application/x-www-form-urlencoded' \
   -H 'User-Agent: ob-http' \
   -d 'grant_type=refresh_token
      &scope=profile%2533inspect
      &refresh_token=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJodHRwczpcL1wvc2NoZW1hcy5jaXNjby5jb21cL2lyb2hcL2lkZW50aXR5XC9jbGFpbXNcL3VzZXJcL2VtYWlsIjoieWFlc3Bvc2lAY2lzY28uY29tIiwiaHR0cHM6XC9cL3NjaGVtYXMuY2lzY28uY29tXC9pcm9oXC9pZGVudGl0eVwvY2xhaW1zXC91c2VyXC9zY29wZXMiOlsiaXJvaC1hZG1pbiIsImludGVncmF0aW9uIiwicHJpdmF0ZS1pbnRlbCIsImFkbWluIiwicHJvZmlsZSIsImluc3BlY3QiLCJpcm9oLWF1dGgiLCJzc2UiLCJ1c2VycyIsImNpc2NvIiwiY2FzZWJvb2siLCJvcmJpdGFsIiwiZW5yaWNoIiwib2F1dGgiLCJnbG9iYWwtaW50ZWwiLCJjb2xsZWN0IiwicmVzcG9uc2UiLCJ1aS1zZXR0aW5ncyJdLCJodHRwczpcL1wvc2NoZW1hcy5jaXNjby5jb21cL2lyb2hcL2lkZW50aXR5XC9jbGFpbXNcL3VzZXJcL25pY2siOiJZYW5uIEVzcG9zaXRvIiwiZW1haWwiOiJ5YWVzcG9zaUBjaXNjby5jb20iLCJpc3MiOiJJUk9IIEF1dGgiLCJodHRwczpcL1wvc2NoZW1hcy5jaXNjby5jb21cL2lyb2hcL2lkZW50aXR5XC9jbGFpbXNcL3Njb3BlcyI6WyJwcm9maWxlIiwiaW5zcGVjdCJdLCJleHAiOjE3NTE0MTQ0MDAwLCJodHRwczpcL1wvc2NoZW1hcy5jaXNjby5jb21cL2lyb2hcL2lkZW50aXR5XC9jbGFpbXNcL29hdXRoXC91c2VyXC9pZCI6ImYwMDEwOTI0LWUxYmMtNGIwMy1iNjAwLTg5YzZjZjUyNzU3YyIsImh0dHBzOlwvXC9zY2hlbWFzLmNpc2NvLmNvbVwvaXJvaFwvaWRlbnRpdHlcL2NsYWltc1wvb3JnXC9pZCI6ImY0N2E4OWJmLTVkMmUtNDM5Mi1iNzcwLWFkNDgyMWE4MmFjZiIsImh0dHBzOlwvXC9zY2hlbWFzLmNpc2NvLmNvbVwvaXJvaFwvaWRlbnRpdHlcL2NsYWltc1wvb2F1dGhcL2dyYW50IjoiYXV0aC1jb2RlIiwianRpIjoiMjc0YjkwYTAtZDlhNi00YmI2LWJiN2UtMDkzYTY4MzllMTUyIiwibmJmIjoxNTY0MTMwMzEzLCJodHRwczpcL1wvc2NoZW1hcy5jaXNjby5jb21cL2lyb2hcL2lkZW50aXR5XC9jbGFpbXNcL29hdXRoXC9zY29wZXMiOlsicHJvZmlsZSIsImluc3BlY3QiXSwiaHR0cHM6XC9cL3NjaGVtYXMuY2lzY28uY29tXC9pcm9oXC9pZGVudGl0eVwvY2xhaW1zXC91c2VyXC9uYW1lIjoiWWFubiBFc3Bvc2l0byIsImh0dHBzOlwvXC9zY2hlbWFzLmNpc2NvLmNvbVwvaXJvaFwvaWRlbnRpdHlcL2NsYWltc1wvdXNlclwvaWQiOiJmMDAxMDkyNC1lMWJjLTRiMDMtYjYwMC04OWM2Y2Y1Mjc1N2MiLCJodHRwczpcL1wvc2NoZW1hcy5jaXNjby5jb21cL2lyb2hcL2lkZW50aXR5XC9jbGFpbXNcL29hdXRoXC9jbGllbnRcL2lkIjoiY2xpZW50LTNiYjFlNzg3LTM4MWQtNGYxMi1iZjMyLWUxMTU4ZjIwMGRkYyIsImlhdCI6MTU2NDEzMDM3MywiaHR0cHM6XC9cL3NjaGVtYXMuY2lzY28uY29tXC9pcm9oXC9pZGVudGl0eVwvY2xhaW1zXC9vYXV0aFwva2luZCI6InJlZnJlc2gtdG9rZW4ifQ.abtBzZmX64XDTB7OJkcyCsOrGnXj-c6tSg89qg9ENnHSeBs-e4AhQMzHO5ZF5Cb4e7c8z34k0gxatuBqLTtLTztV32ktJGZ1IwFA4k7bpPrW1qdrSJQfZjOBBdLG3DSDMqo7dihqh_4VkfZGHDUNfao12xHTXCbzzfKiZNr6f8UJ0lzEvNZ2tQFkIMjdLVrN7OSk5K56-4SwEL6-X7LHRjF8M0FrGq9QU2lztuRyGXfbPOIal4wJdcfZ-Z2S1_fC82y-rE2mEDEX-diCI_oC_01wFiBbklJLoUEYK6RylEQ9lIMgYsUNsw07nM3IWua2cq5O6rNWEe9yJJzo5TIuQg'
   'https://visibility.amp.cisco.com/iroh/oauth2/token'

The following is an example response from the /iroh/oauth2/token API:

{
   "access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJodHRwczpcL1wvc2NoZW1hcy5jaXNjby5jb21cL2lyb2hcL2lkZW50aXR5XC9jbGFpbXNcL3VzZXJcL2VtYWlsIjoieWFlc3Bvc2lAY2lzY28uY29tIiwiaHR0cHM6XC9cL3NjaGVtYXMuY2lzY28uY29tXC9pcm9oXC9pZGVudGl0eVwvY2xhaW1zXC91c2VyXC9zY29wZXMiOlsiaXJvaC1hZG1pbiIsImludGVncmF0aW9uIiwicHJpdmF0ZS1pbnRlbCIsImFkbWluIiwicHJvZmlsZSIsImluc3BlY3QiLCJpcm9oLWF1dGgiLCJzc2UiLCJ1c2VycyIsImNpc2NvIiwiY2FzZWJvb2siLCJvcmJpdGFsIiwiZW5yaWNoIiwib2F1dGgiLCJnbG9iYWwtaW50ZWwiLCJjb2xsZWN0IiwicmVzcG9uc2UiLCJ1aS1zZXR0aW5ncyJdLCJodHRwczpcL1wvc2NoZW1hcy5jaXNjby5jb21cL2lyb2hcL2lkZW50aXR5XC9jbGFpbXNcL3VzZXJcL25pY2siOiJZYW5uIEVzcG9zaXRvIiwiZW1haWwiOiJ5YWVzcG9zaUBjaXNjby5jb20iLCJzdWIiOiJmMDAxMDkyNC1lMWJjLTRiMDMtYjYwMC04OWM2Y2Y1Mjc1N2MiLCJpc3MiOiJJUk9IIEF1dGgiLCJodHRwczpcL1wvc2NoZW1hcy5jaXNjby5jb21cL2lyb2hcL2lkZW50aXR5XC9jbGFpbXNcL3Njb3BlcyI6WyJwcm9maWxlIiwiaW5zcGVjdCJdLCJleHAiOjE1NjQxMzQxODksImh0dHBzOlwvXC9zY2hlbWFzLmNpc2NvLmNvbVwvaXJvaFwvaWRlbnRpdHlcL2NsYWltc1wvb2F1dGhcL3VzZXJcL2lkIjoiZjAwMTA5MjQtZTFiYy00YjAzLWI2MDAtODljNmNmNTI3NTdjIiwiaHR0cHM6XC9cL3NjaGVtYXMuY2lzY28uY29tXC9pcm9oXC9pZGVudGl0eVwvY2xhaW1zXC9vcmdcL2lkIjoiZjQ3YTg5YmYtNWQyZS00MzkyLWI3NzAtYWQ0ODIxYTgyYWNmIiwiaHR0cHM6XC9cL3NjaGVtYXMuY2lzY28uY29tXC9pcm9oXC9pZGVudGl0eVwvY2xhaW1zXC9vYXV0aFwvZ3JhbnQiOiJhdXRoLWNvZGUiLCJqdGkiOiIzNmY4YzgxNi1jN2E1LTQ0ZWMtYWZhNS1iMDI4OGIzMzJkZDkiLCJuYmYiOjE1NjQxMzM1MjksImh0dHBzOlwvXC9zY2hlbWFzLmNpc2NvLmNvbVwvaXJvaFwvaWRlbnRpdHlcL2NsYWltc1wvb2F1dGhcL3Njb3BlcyI6WyJwcm9maWxlIiwiaW5zcGVjdCJdLCJodHRwczpcL1wvc2NoZW1hcy5jaXNjby5jb21cL2lyb2hcL2lkZW50aXR5XC9jbGFpbXNcL3VzZXJcL25hbWUiOiJZYW5uIEVzcG9zaXRvIiwiaHR0cHM6XC9cL3NjaGVtYXMuY2lzY28uY29tXC9pcm9oXC9pZGVudGl0eVwvY2xhaW1zXC91c2VyXC9pZCI6ImYwMDEwOTI0LWUxYmMtNGIwMy1iNjAwLTg5YzZjZjUyNzU3YyIsImh0dHBzOlwvXC9zY2hlbWFzLmNpc2NvLmNvbVwvaXJvaFwvaWRlbnRpdHlcL2NsYWltc1wvb2F1dGhcL2NsaWVudFwvaWQiOiJjbGllbnQtM2JiMWU3ODctMzgxZC00ZjEyLWJmMzItZTExNThmMjAwZGRjIiwiaHR0cHM6XC9cL3NjaGVtYXMuY2lzY28uY29tXC9pcm9oXC9pZGVudGl0eVwvY2xhaW1zXC92ZXJzaW9uIjoidjEuMjAuMC1kZjgxNGU3YjYyODMwZGRkNTc2ZCIsImlhdCI6MTU2NDEzMzU4OSwiaHR0cHM6XC9cL3NjaGVtYXMuY2lzY28uY29tXC9pcm9oXC9pZGVudGl0eVwvY2xhaW1zXC9vYXV0aFwva2luZCI6ImFjY2Vzcy10b2tlbiJ9.t8f5cwIBYMYlKSewpCAv2Sgh3xOhQS_MkQqFd14Xz2j9eZD_SpfLRSdYCt5glW9NMiMuUHqtzkYroK46zYeFpy5XoEx3gLZLJC4eJaVdIxRqRxt2IcJ5F7R31Xt_R5Cbkrgncl6NxynTeRyb--4UoQXlTVNmwXQxEGbM1bc9EU7iFabevJVswpj_no9Ah5zp2-BRtvszPzuF9-Ii5AUwmsAoVziH--uezFQQv5xhQNBA17fXjIn5D3oBiK50_vZEaAgdHE3SLDDPqw4BiPzeNipvE6oGuA486Bo3XET_O7DkgzzsEakwZe2HF2DKAstBLJSeMdRjA-fhBrRCLxHJSQ",
   "token_type": "bearer",
   "expires_in": 600,
   "scope": "profile inspect"
}

This is a very similar request to the one that was used with the code token. The only differences are:

  • It uses the refresh_token instead of the code token.
  • It uses the refresh_token for the grant_type parameter.

You must use Basic Auth with your client id and password for authorization, and specify a Content-Type of application/x-www-form-urlencoded.

Run Demo on localhost

For security, IROH does not allow clients with non https redirect URIs to be approved automatically.

In order to serve HTTPS locally, you should follow the instructions to create a new self-signed certificate.

git clone https://github.com/yogsototh/oauth2-client-demo
cd cert
./gen-new-root-cert.sh
./gen-new-cert.sh rootCA
cd ..

You should serve the site/ directory using the created server.crt and server.key.

A possible tool is Simple Web Server (sws). The easiest way to install it is to first install stack and then execute stack install sws.

You may also need to modify your browser to trust the self-signed certificate.

Checklist

⚠ To verify your integration, follow the Client Checklist.