- 09 Nov 2022
-
DarkLight
-
PDF
Two Step Token
- Updated on 09 Nov 2022
-
DarkLight
-
PDF
The dynamic Two Step Token process is one of the more common methods for API authentication between systems and has many different varieties which are discussed throughout the authentication articles. Attributes of standard Two Step Token authentication are:
- A username and password to authenticate with the system are provided in the body of an initial token request.
- The user is authenticated by the system which will return a token in the response body.
- This token will then be used in subsequent requests to the system by placing it into a header in the request.
How to set up Two Step Token in Adapters
Two-step token is handled in both the IAP Service Instance Configuration for the adapter and in the adapter endpoint configuration within the .system entity.
You can find the IAP Service Instance Configuration for the adapter within IAP Admin Essentials and the properties we are talking about are in the authentication section. The authentication section includes other properties that are described in detail in the IAP Service Instance Configuration articles.
You can find the endpoint configuration for the adapter within the adapter files on the IAP server. The authentication files are located in the /adapter-home-dir/entities/.system directory.
Two Step Token in IAP Service Instance Configuration for the Adapter
Option | Description |
---|---|
auth_method | Should be set to ”request_token” . Since username and password are used on the first request to get a token, the actual username and password should be provided in their respective properties.The password field can be encoded using IAP's encryption. |
auth_field | Should be set to where the token will be placed in future requests. This is NOT where info is placed on the initial token request. Headers are the most common placement and are referenced with header.headers . Therefore, the Authorization header should be header.headers.Authorization |
auth_field_format | Is the format of the token that will be sent in future requests. This is NOT the format on the initial token request. The adapter library will replace the variables it knows about:{token} |
token_timeout | You can specify how long the token is valid in milliseconds in the "token_timeout" field. This helps to prevent having to use a two-step process on every call. |
token_cache | Should be set to local. The adapter caches the token in memory. |
invalid_token_error | The "invalid_token_error" field tells the adapter what error to expect when the token is not valid. When this happens, the adapter attempts to pull a new token and will then reattempt the request automatically. If the token gets invalidated (typically a 401 error), then the adapter will automatically pull a new token and will attempt the call again instead of failing the call. Where possible, the adapter will attempt to handle authentication errors that occur to ensure successful workflows. |
Example Two Step Token in IAP Service Instance Configuration for the Adapter
"authentication": {
"auth_method": "request_token",
"username": "systemuser",
"password": "systempassword",
"token_timeout": 180000,
"token_cache": "local",
"invalid_token_error": 401,
"auth_field": "header.headers.Authorization",
"auth_field_format": "{token}"
},
Two Step Token in the Endpoint Configuration for the Adapter
Here are some other key pieces of information to know when the two-step token is handled in the .system
entity (located at /adapter-home-dir/entities/.system:
Action.json File - The action.json file tells the Adapter Library how it is going to get the token. The information in the action is:
Property | Description |
---|---|
name | The action name is getToken |
protocol | The protocol within the adapter - this should always be REST |
method | The REST method used to make the request. Supports other REST methods but this will typically be a POST or GET |
entitypath | The path used for the call to get the token. Can use the global adapter variables (e.g. {base_path} and {version} |
requestSchema | The schema used to prepare the data for the external system. Should be a relative path to the schema file. |
responseSchema | The schema used on the response to extract the token. Should be a relative path to the schema file. |
timeout | A timeout on the call if it is different than the attemptTimeout in the Service Instance Configuration. |
sendEmpty | Whether the adapter should send a body even when there is nothing to send. |
requestDatatype | How the data should be sent to the other system. Most common would be JSON and URLENCODE. |
responseDatatype | How the data will be returned to the adapter. Most common would be JSON and PLAIN. |
headers | An object containing extra headers that may need to be sent along with the authentication request. You can also override some of the automatic adapter headers here. |
sso | An object containing a different server used for the authentication request. This replaces the host information in the Service Instance Configuration so that the authentication request goes somewhere else. The SSO configuration needs to include the protocol, host, and port of the system that will be used to authenticate against. |
responseObjects | An object containing information on how to handle the response and also set up mockdata which will be returned when the adapter is run with stub set to true. |
action.json Example
{
"name": "getToken",
"protocol": "REST",
"method": "POST",
"entitypath": "/api/{version}/authentication/signin",
"requestSchema": "schemaTokenReq.json",
"responseSchema": "schemaTokenResp.json",
"timeout": 0,
"sendEmpty": false,
"requestDatatype": "JSON",
"responseDatatype": "JSON",
"headers": {
"Accept": "*/*"
},
"sso": {
"protocol": "",
"host": "",
"port": 0
},
"responseObjects": [
{
"type": "default",
"key": "",
"mockFile": "mockdatafiles/gettoken.json"
}
]
},
Request Schema File - The schemaTokenReq.json file (as named in the action.json) tells the Adapter Library what data should be included in the token request and what fields the data should be in.
Most of the data in this file should be unchanged. The fields that you can alter are mentioned here:
Property | Description |
---|---|
translate | This tells the adapter libraries whether it should translate the data. Whenever field names are changed username->user this is required to be true. |
dynamicfields | This tells the adapter libraries whether it should allow fields that are not defined in the schema to be included in the request. This can be true as well. |
username | This maps to the username in the IAP Service Instance Configuration for the adapter - therefore the name should remain unchanged. The most common change here is to change the external_name within this object to be what the other system expects (common values are: username, user, login, etc) |
password | This maps to the password in the IAP Service Instance Configuration for the adapter - the name should remain unchanged. The most common change here is to change the external_name within this object to be what the other system expects (common values are: password, passwd, pwd, etc) |
Other fields may also be added to this schema for client_id, client_secret and grant_type. They should be similar to the username and password to take advantage of information in the IAP Service Instance Configuration for the adapter. Additional static data sent on the request can be added to the schema and have default data that will be passed with the request.
Request Schema Example
{
"$id": "reqTokenSchema.json",
"type": "object",
"schema": "http://json-schema.org/draft-07/schema#",
"translate": true,
"dynamicfields": true,
"properties": {
"ph_request_type": {
"type": "string",
"description": "type of request(internal to adapter)",
"default": "getToken",
"enum": [
"getToken",
"healthcheck"
],
"external_name": "ph_request_type"
},
"username": {
"type": "string",
"description": "username to login with",
"external_name": "user"
},
"password": {
"type": "string",
"decription": "password to login with",
"external_name": "passwd"
}
},
"definitions": {}
}
Response Schema File - The schemaTokenResp.json file (as named in the action.json) tells the Adapter Library what data is included in the token response and what field the token should be in.
Most of the data in this file should be unchanged. The fields that you can alter are mentioned here:
Property | Description |
---|---|
translate | This tells the adapter libraries whether it should translate the data. Whenever field names are changed access_token->token this is required to be true. |
dynamicfields | This tells the adapter libraries whether it should allow fields that are not defined in the schema to be included in the request. This can generally be true as well. |
token | This provides the information for where the token can be found in the response. The most common change here is to change the external_name within this object to be what the other system sends (common values are: token, access_token, etc) |
tokenp2 | This provides the information for where another piece of information can be found in the response. This is not often required but when it is you would need to change the external_name within this object to be what the other system sends (common values are: session_id, etc) |
Response Schema Example
{
"$id": "respTokenSchema.json",
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"translate": true,
"properties": {
"ph_request_type": {
"type": "string",
"description": "type of request(internal to adapter)",
"default": "getToken",
"enum": [
"getToken"
],
"external_name": "ph_request_type"
},
"token": {
"type": "string",
"description": "the token returned from system",
"external_name": "access_token"
}
},
"definitions": {}
}
Other Options for Two Step Token
There are many variations of two-step token. The adapters service instance and entity configurations are flexible enough to handle many variations including:
Option | Description |
---|---|
Token in a different header field | Change the value of "auth_field" to "header.headers.X-AUTH-TOKEN" . |
Token in a different location | To locate in the url path (before query parameters), set "auth_field" to "urlpath" .To locate in the url query (after the ?), set "auth_field" to "url" .To locate in the body, set "auth_field" to "body.field” . |
Different format of auth data | Want to just send the token, use ”{token}” .Can also set the "auth_field_format" to “Bearer {token}” . |
The tokens can timeout at different times | The adapter allows you to configure different token_timeout values. |
Different way to send the request | Many systems want to receive the credentials in a urlencoded format. The adapter supports this through requestDatatype which can be JSON, XML, PLAIN, FORM, URLENCODE, or URLQUERY |
Different way to get the response | Many systems will send the response their way. The adapter supports this through responseDatatype which can be JSON, XML, PLAIN, or XML2JSON |
Data sent or received in different fields | Changes to the external_name fields in the schemaTokenReq.json or schemaTokenResp.json files (not shown below) |
Default Headers Override | You may need to override default headers like Accept so that instead of sending application/json or plain/text we say we accept anything (/) |
Adding an SSO Server | You may need to authenticate against a different system. So, you need to provide that system's information to the adapter in the sso object. |
Other Options Examples
Sample Properties
"authentication": {
"auth_method": "request_token",
"username": "systemuser",
"password": "systempassword",
"token_timeout": 3600000,
"token_cache": "local",
"invalid_token_error": 401,
"auth_field": "header.headers.X-AUTH-TOKEN",
"auth_field_format": "Bearer {token}"
},
action.json Example
{
"name": "getToken",
"protocol": "REST",
"method": "POST",
"entitypath": "/api/{version}/authentication/signin",
"requestSchema": "schemaTokenReq.json",
"responseSchema": "schemaTokenResp.json",
"timeout": 0,
"sendEmpty": false,
"requestDatatype": "URLENCODE",
"responseDatatype": "PLAIN",
"headers": {
"Accept": "*/*"
},
"sso": {
"protocol": "https",
"host": "DNSname or IP",
"port": 443
},
"responseObjects": [
{
"type": "default",
"key": "",
"mockFile": "mockdatafiles/gettoken.json"
}
]
},