Invoking HOTP over REST

HOTP Introduction

An excellent article about the core OpenAM HOTP capability is: Use HOTP for two factor authentication

Building on the article, we show here a typical REST-based programmatic interaction when invoking HOTP from a client, such as a Portal.

Configuration in OpenAM

Setup HOTP as REQUISITE after DataStore under a realm called “levels”. You could choose not to use realms and create the authentication chain at the top level realm. However, you would modify the REST URL for all the ensuing calls.

Using PostMan, invoke a POST on the realm=/levels

Body-

Empty

Response-

{ "authId": "eyAiYWxnIjogIkhTMjU2IiwgInR5cCI6ICJqd3QiIH0.eyAib3RrIjogIm05ZWVpdjltNmsxdGRoN2dkdGM4MG5qdWFmIiwgInNlc3Npb25JZCI6ICJBUUlDNXdNMkxZNFNmY3hieHYzZjI0aXlzNDlEaG9NUlU3VENhMkU3dFdfcXY1Zy4qQUFKVFNRQUNNREVBQWxOTEFCUXROelU0TmpBME1UZzJNVFl5TWpnNU5EWXdOZy4uKiIsICJyZWFsbSI6ICJvPWxldmVscyxvdT1zZXJ2aWNlcyxkYz1vcGVuYW0sZGM9Zm9yZ2Vyb2NrLGRjPW9yZyIgfQ.SsOE-9DyAZ6apnj5SXaD9ED28T_RDFfpjV8hslHP99g", "template": "", "stage": "DataStore1", "callbacks": [ { "type": "NameCallback", "output": [ { "name": "prompt", "value": " User Name: " } ], "input": [ { "name": "IDToken1", "value": "" } ] }, { "type": "PasswordCallback", "output": [ { "name": "prompt", "value": " Password: " } ], "input": [ { "name": "IDToken2", "value": "" } ] } ] }

 

Add in the username and password as shown below:

Body (from the screenshot above)-

{ "authId": "eyAiYWxnIjogIkhTMjU2IiwgInR5cCI6ICJqd3QiIH0.eyAib3RrIjogIjl2Mm1lZGQ3NmpwdXViZGlncGkyZjFtNzk5IiwgInNlc3Npb25JZCI6ICJBUUlDNXdNMkxZNFNmY3d1amwzczR4TXdyMHI0S3paMFI2Qmk3LV9aTHMxcnRQby4qQUFKVFNRQUNNREVBQWxOTEFCTXlOelE1TmpJeU5qUTBOVFUwTlRreE5EQTMqIiwgInJlYWxtIjogIm89bGV2ZWxzLG91PXNlcnZpY2VzLGRjPW9wZW5hbSxkYz1mb3JnZXJvY2ssZGM9b3JnIiB9.WGemKm2u0O-vbhAkAClg0l0rndGEhDbhS3pncAsn6PA", "template": "", "stage": "DataStore1", "callbacks": [ { "type": "NameCallback", "output": [ { "name": "prompt", "value": " User Name: " } ], "input": [ { "name": "IDToken1", "value": "user.4" } ] }, { "type": "PasswordCallback", "output": [ { "name": "prompt", "value": " Password: " } ], "input": [ { "name": "IDToken2", "value": "Password2" } ] } ] }

 

Response

{ "authId": "eyAiYWxnIjogIkhTMjU2IiwgInR5cCI6ICJqd3QiIH0.eyAib3RrIjogIjl2Mm1lZGQ3NmpwdXViZGlncGkyZjFtNzk5IiwgInNlc3Npb25JZCI6ICJBUUlDNXdNMkxZNFNmY3d1amwzczR4TXdyMHI0S3paMFI2Qmk3LV9aTHMxcnRQby4qQUFKVFNRQUNNREVBQWxOTEFCTXlOelE1TmpJeU5qUTBOVFUwTlRreE5EQTMqIiwgInJlYWxtIjogIm89bGV2ZWxzLG91PXNlcnZpY2VzLGRjPW9wZW5hbSxkYz1mb3JnZXJvY2ssZGM9b3JnIiB9.WGemKm2u0O-vbhAkAClg0l0rndGEhDbhS3pncAsn6PA", "template": "", "stage": "HOTP2", "callbacks": [ { "type": "PasswordCallback", "output": [ { "name": "prompt", "value": " Enter OTP " } ], "input": [ { "name": "IDToken1", "value": "" } ] }, { "type": "ConfirmationCallback", "output": [ { "name": "prompt", "value": "" }, { "name": "messageType", "value": 0 }, { "name": "options", "value": [ " Submit OTP ", " Request OTP " ] }, { "name": "optionType", "value": -1 }, { "name": "defaultOption", "value": 0 } ], "input": [ { "name": "IDToken2", "value": 0 } ] } ] }

 

Set IDToken2 to value “1”, and re submit as a POST. OpenAM will generate the OTP code and send it to the user.

 

Body-

{ "authId": "eyAiYWxnIjogIkhTMjU2IiwgInR5cCI6ICJqd3QiIH0.eyAib3RrIjogImYwZW5xYTI2aHZla3Q0bG5tc24wbDFlbTI5IiwgInNlc3Npb25JZCI6ICJBUUlDNXdNMkxZNFNmY3k4cllnb2V3MDBWNkpOUW5rR1RjLVoyVjZmcjZFMS11US4qQUFKVFNRQUNNREVBQWxOTEFCTTRNak01TXpRMU9EazROekl4TlRnNU16UXkqIiwgInJlYWxtIjogIm89bGV2ZWxzLG91PXNlcnZpY2VzLGRjPW9wZW5hbSxkYz1mb3JnZXJvY2ssZGM9b3JnIiB9.Dfxj7bAtxHEenVPA_9t3iCFhu92zqk8lXAqxmQD1COU", "template": "", "stage": "HOTP2", "callbacks": [ { "type": "PasswordCallback", "output": [ { "name": "prompt", "value": " Enter OTP " } ], "input": [ { "name": "IDToken1", "value": "" } ] }, { "type": "ConfirmationCallback", "output": [ { "name": "prompt", "value": "" }, { "name": "messageType", "value": 0 }, { "name": "options", "value": [ " Submit OTP ", " Request OTP " ] }, { "name": "optionType", "value": -1 }, { "name": "defaultOption", "value": 0 } ], "input": [ { "name": "IDToken2", "value": 1 } ] } ] }

 

Response-

{ "authId": "eyAiYWxnIjogIkhTMjU2IiwgInR5cCI6ICJqd3QiIH0.eyAib3RrIjogImYwZW5xYTI2aHZla3Q0bG5tc24wbDFlbTI5IiwgInNlc3Npb25JZCI6ICJBUUlDNXdNMkxZNFNmY3k4cllnb2V3MDBWNkpOUW5rR1RjLVoyVjZmcjZFMS11US4qQUFKVFNRQUNNREVBQWxOTEFCTTRNak01TXpRMU9EazROekl4TlRnNU16UXkqIiwgInJlYWxtIjogIm89bGV2ZWxzLG91PXNlcnZpY2VzLGRjPW9wZW5hbSxkYz1mb3JnZXJvY2ssZGM9b3JnIiB9.Dfxj7bAtxHEenVPA_9t3iCFhu92zqk8lXAqxmQD1COU", "template": "", "stage": "HOTP2", "callbacks": [ { "type": "PasswordCallback", "output": [ { "name": "prompt", "value": " Enter OTP " } ], "input": [ { "name": "IDToken1", "value": "" } ] }, { "type": "ConfirmationCallback", "output": [ { "name": "prompt", "value": "" }, { "name": "messageType", "value": 0 }, { "name": "options", "value": [ " Submit OTP ", " Request OTP " ] }, { "name": "optionType", "value": -1 }, { "name": "defaultOption", "value": 0 } ], "input": [ { "name": "IDToken2", "value": 1 } ] } ] }

 

Supply OTP Code

Change IDToken2 to value “0” and this time have the user supply the OTP code s/he received:

 

Body-

{ "authId": "eyAiYWxnIjogIkhTMjU2IiwgInR5cCI6ICJqd3QiIH0.eyAib3RrIjogImYwZW5xYTI2aHZla3Q0bG5tc24wbDFlbTI5IiwgInNlc3Npb25JZCI6ICJBUUlDNXdNMkxZNFNmY3k4cllnb2V3MDBWNkpOUW5rR1RjLVoyVjZmcjZFMS11US4qQUFKVFNRQUNNREVBQWxOTEFCTTRNak01TXpRMU9EazROekl4TlRnNU16UXkqIiwgInJlYWxtIjogIm89bGV2ZWxzLG91PXNlcnZpY2VzLGRjPW9wZW5hbSxkYz1mb3JnZXJvY2ssZGM9b3JnIiB9.Dfxj7bAtxHEenVPA_9t3iCFhu92zqk8lXAqxmQD1COU", "template": "", "stage": "HOTP2", "callbacks": [ { "type": "PasswordCallback", "output": [ { "name": "prompt", "value": " Enter OTP " } ], "input": [ { "name": "IDToken1", "value": "86848280" } ] }, { "type": "ConfirmationCallback", "output": [ { "name": "prompt", "value": "" }, { "name": "messageType", "value": 0 }, { "name": "options", "value": [ " Submit OTP ", " Request OTP " ] }, { "name": "optionType", "value": -1}, { "name": "defaultOption", "value": 0 } ], "input": [ { "name": "IDToken2", "value": 0 } ] } ] }

 

At this time, if the OTP code was correct, the user will be logged into OpenAM.

The value of the iPlanetDirectoryPro cookie will be returned as tokenId.

 

Response-

{ "tokenId": "AQIC5wM2LY4Sfcyt-pO9V3hEMYK924cDC2_SlWLROXUBpsc.*AAJTSQACMDEAAlNLABQtMTcyMDQ4ODk5NTU0ODUzNTQ4MQ..*", "successUrl": "/openam/console" }

 

The iPlanetDirectoryPro can then be used to do other stuff, such as list user data values over REST: