Several clients have asked to implement the functionality of registering a device using a mobile/native application. When a user logs into the application the first time, the application gets an OAuth access token (using authorization code flow), which will redirect the request to the end user for them to authenticate with username/password, and upon successful authentication the application then gets an access token, which will be used to authenticate requests from this application/device. The first time an application/device uses that token, the device will be unregistered, and after completion of a step-up authentication the device will then be registered. If the username/password gets compromised, then an unauthorized user could impersonate the user on a different device and try to use the application by completing the authorization code flow with the stolen username/password. The solution described in this article helps stop this kind of unauthorized access by requesting a second factor authentication when trying to access the application from a new device.
ISAM provides the capabilities to register a web browser as described in this blog entry by my colleague Shane Weeden:
Shane Weeden's Browser Registration article
The solution explained above works for registering web browsers using a persistent cookie, but some additional steps are required to implement a similar model for mobile client applications or self-contained web applications that use REST APIS. This article builds up upon the model described in Shane’s blog, but focuses on documenting the steps used to perform a similar device registration using REST API calls that can be implemented in such a mobile client or self-contained web application.
In the blog mentioned above, the web browser executes the info.js script which collects the device attributes and posts those attributes to the Attribute Collector (AC) service in ISAM. When using REST API’s, the application is responsible for collecting the device attributes/values to be used to register the device, and then post those attributes to the AC service as shown in steps 2 and 3 below; once the AC service gets these values the data is indexed by a session index, which the application needs to use to set the value of ac.uuid cookie for all subsequent requests.
Steps for the device registration:
- Obtain an OAuth token which will be used to authenticate all subsequent requests. This can be done using any of the OAuth standard flows; deciding which flow to use will depend on the specific details of your implementation, but for API’s the most commonly used flows are Authorization code (if your application can send a redirect request to the end user), or ROPC-Resource Owner Password Credentials if the client is a trusted client. For native mobile applications or single page applications using javascript, you may want to look into using the Authorization code with PKCE flow, this flow is designed to minimize the risk of unauthorized access should the application client secret be compromised.
Sample Postman request to get an OAuth token using ROPC flow:
- Request Headers:
- Request Body:
- Response Body:
- Use the token obtained in step 1, to send a request to the AC service to get the session index which will be used to set the value of ac.uuid cookie:
Authorization: Bearer {{token}}
Accept: application/json
POST
/mga/sps/ac
{}
Sample Postman request to get value of ac.uuid cookie:
- Request Headers:
- Request Body:
- Response Body:
- Response Cookies:
- Use the token obtained in step 1, and the session index value obtained in step 2 to send device attribute/value pairs which will be used to register the device to the AC service. Make sure to send a cookie named ac.uuid in the request with the value of the session index obtained in the previous step.
Authorization: Bearer {{token}}
Accept: application/json
POST
/mga/sps/ac/REST/{{session_index}}
- Body:
- List of device attribute/value pairs to be used to register the device in the request body as JSON. i.e.:
{
"ac.uuid" : "6bb5acca-6948-4c97-8584-b3914e7ceee7",
"geoLocation" : "41.40338, 2.17403",
"deviceName" : "Test API Client 1"
}
Sample Postman request to set value of device registration attributes:
- Request Headers:
- Request Body:
- Request Cookies:
- Response Body:
- Response Cookies:
- GET /protected.html. This can be any URL that is protected with a context-based Access Control policy that contains the “Register Device” obligation. Make sure the cookie name sent in the request is ac.uuid. This step may have 2 different responses, if you get the actual protected.html page, it means you're authenticated and don't need to take any further action. If the response you get is a 302 redirect to a URL like /mga/sps/apiauthsvc?TransactionId=c2ab-e580-422a-9f42-a88185cb6327 (or the User error page) it means you need to complete an additional authentication policy as defined in the context-based Access Control policy.
Sample Postman request to get a protected resource (/protected.html):
- Request Headers:
- Response Body:
- If a step-up authentication is required, after successfully completing the additional authentication, resending the GET /protected.html request will complete the device registration.
To validate the device has been registered, you can send a GET request to get the list of devices registered to that user as shown below.
Sample Postman request to get the list of all devices registered to a user:
- Request Headers and Response:
And using the device id shown in the response to the previous request, the request below will show the details of the attribute/values associated with that specific device:
Sample Postman request to get the details of a specific device registered to a user:
- Request Headers and Response:
This completes the full use case cycle, with a mobile application having registered and is able to retrieve that registration.
These steps can be implemented using many frameworks to develop mobile applications and to perform device registrations by adding the device signature into the runtime database.
You can click the link below to download the sample postman collection I created to implement/test this use case:
Postman Collection