Custom User Activation and Password Reset Flows in Oracle IDCS

Oracle’s Identity Cloud Service is typically associated with its role in acting as the primary identity store for Oracle’s Cloud services – acting as the gatekeeper for administrators and developers, and providing single-sign-on across Oracle services for end users. However, thanks to its API-first design, it is also very capable of acting as a headless OAuth server and user store, providing authenticated access to custom applications and APIs. When these custom applications are customer facing, you will want fine-grained control over your user experience, without them interacting with IDCS directly. In this post we will explore implementing custom user activation and password reset flows; which provides the opportunity to implement pixel perfect UIs, modify the flows for different classes of users, or just do whatever your custom application requires.

To begin with, it is probably helpful to understand the default user activation flow used by IDCS, which will inform where certain customisations need to be implemented.

  1. Initially, when a user is registered (either by an admin, or in a customer facing custom app, by the User Creation API), they receive a ‘Welcome’ email.
  2. This ‘Welcome’ email includes an ‘Activate Your Account’ link which includes a single-use token which can be used to identify the user.
  3. On clicking the link, the user is directed to IDCS to set a password – which both sets their password as well as flags their user as ‘Active’

The Reset Password flow is almost identical, with just the initialisation and email format differing; IDCS in fact uses the same page for both setting an initial password and for resetting a forgotten password.  As part of customising this flow, it is possible to preserve a lot of this default behaviour, while obtaining full control over the customer experience, by retaining the use of the IDCS notification service to send the ‘Welcome’ email, and using the auto-issued single-use token as part of your activation service. As such, customising the user activation flow involves two tasks, customising the ‘Welcome’ email, and building an alternative service which is able to set the user’s password and activate the user. I will briefly touch upon the former, before focussing in more depth upon on the latter.

Customising the Welcome (or Forgotten Password) Email

IDCS supports pretty comprehensive customisation of all the notifications it sends via the console. This can be accessed via the Settings->Notifications item in the side menu. The initial screen allows certain notifications to be enabled or disabled; in a customer facing environment you will probably want to disable some of these, but the real power comes from the ‘Email Templates’ tab, shown below.

WelcomeEmailTemplate

From this screen you can completely customise the emails which get sent out by IDCS, from straightforward changing of the text to completely overhauling the layout and styling by modifying the HTML source via the ‘<> Source’ button, as shown below.

EmailSource

When modifying the email template, one of the points to take note of is the use of placeholder variables in the template, such as ${companyName} and ${user.displayName}. These can be used to personalise the email, but several of them serve an important role in controlling where users are sent to activate their account or reset their password.

In the ‘Welcome’ and ‘Reset Password’ (strictly speaking, the ‘Password Recovery Request’) email templates, users are sent to the password reset page via the ${redirectUrl} placeholder. This is a link to an IDCS page, and includes a generated single-use token. In order to modify this, to redirect users to your custom activation service, you will need to replace the ${redirectUrl} with your custom activation service, post-pended with the single-use token, which is available via the ${userToken} email variable (you can see all available placeholder variables by clicking the ‘Email Variables’ button, just above the email editor). For example, you might include a link to something like the following:

https://app.mycompany.com/activateuser?token=${userToken}

Ultimately, you can use standard HTML and CSS to customise these email notifications to your heart’s content, and provided you leverage the inbuilt placeholder for the user token, this customisation can easily be performed entirely within IDCS. To take control of the rest of the user activation flow, you will need to move out of IDCS, integrating with it via the REST APIs.

Implementing a Custom User Activation/Password Reset Service

Simple proof-of-concept code for this using Express and Node.js is available on my Github, though it only performs user activation – password reset is however discussed below. If you are exploring using this code, ensure you read the comments – there are a lot of potential enhancements.

At a high-level, the user activation flow requires two separate endpoints. The first receives the single-use token, validates it, then either presents a screen for the user to set their password; or shows an invalid token error. The second is invoked from the password set screen, and is responsible for revalidating the token, then using it to set the password and activate the user associated with the token.

Firstly, an application will need to be set up in IDCS to consume the REST APIs required in order to activate the user and set the user’s password. The application will also need the ability to invoke the User Token service in IDCS in order to obtain information about the single-use token which was included in the email, and this is a relatively highly privileged operation (since this allows operations on behalf of users), and so the application will need the ‘User Administrator’ role in IDCS (at time of writing. A more granular role may have been added since then).

In summary, the application needs to be set up as a ‘Confidential Application’ configured as a Client, with at least the following settings:

  • Allowed Grant Types : Client Credentials (though using a client JWT Assertion is better if you want to handle the additional complexity in your consuming client – I actually went into this in another blog.)
  • Grant the client access to Identity Cloud Service Admin APIs: User Administrator

There is no need to configure Resources or a Web Tier Policy. This will provide you with a client ID and secret. If you are using my sample code, you can rename the ‘idcs_config_sample.json’ file to ‘idcs_config.json’ and insert the client id and secret there, as well as updating the other fields with your IDCS instance details, and desired redirect location. I am not going to go into details about how to use the Client ID and Client secret to obtain a client token; you can either inspect the provided code, or read the documentation provided by IDCS here.

The first task that your custom user activation service will need to do is validate the user token which has been issued via the ‘Welcome’ email, and in order to do this, it is worth examining the format of these tokens in more detail. You can retrieve the tokens using the User Tokens endpoints, and in this case, you will need to use the ‘Search Tokens’ API, filtering by the value of the token which was supplied as a query parameter (assuming you used a link format similar to the example given above, of app.mycompany.com/activateuser?token=${userToken}).

This request looks like the following, though take care when implementing this, as I noticed some issues with URI encoding/decoding of the token value (which is provided URI encoded), the %22 is simply a URL encoded quotation character (“). As this is a search, based upon user controlled values (the token query parameter), you probably want add some validation of the provided token.

GET <idcs-base-url>/admin/v1/UserTokens?filter=token+eq+%22<token_value>%22

Headers:
  Authorization: Bearer <client_token>

This request returns the token information in as part of the ‘Resources’ array and since tokens have unique values, it should return a single item when run with this filter. The token looks similar to this, though I have removed a number of the metadata fields for clarity (‘idcsLastModifiedBy’, ‘idcsCreatedBy’ and ‘meta’).

{
  "data": "username ",
  "id": "3e51ebb4d2d64ab789df28380b67320f",
  "eventId": "admin.user.create.success",
  "userId": "12345678",
  "token": "<token_value>",
  "expiryTime": "2018-10-23T14:08:50.297Z",
  "tokenType": "email",
  "status": 0,
  "schemas": [
    "urn:ietf:params:scim:schemas:oracle:idcs:UserToken"
  ]
}

In order to validate the token, there are a number of potential checks, though the most straightforward are to test the expiry time, and the status. Mechanisms for checking the expiry time should be pretty self-evident, but status needs a little explanation. Simply put, a status of 0 is OK, while a status of 2 is invalid, which means that the token has been used. A status of 1 is possible (and technically indicates ‘sso allowed’), but it is limited to certain types of operations, and in this case, should be considered invalid. In addition, tokens seem to be periodically removed from the response after they have expired, so if the search for the token by token value returns no items, the token has probably expired.

There are a number of possible events which can cause a single-use token to be issued. This token has admin.user.create.success as its eventId, which indicates it was a user created by an administrator, either using the UI or the IDCS APIs. You can validate this identifier if you have separate user activation flows and reset password flows, and don’t want to cross the streams, but it has some utility if you wish to handle both user activation and password reset with the same services, which we will come to shortly.

As a result of this token validation (which must be performed server-side to preserve the confidentiality of your client token), your service will need to serve either an invalid token page to the user, or a page to allow them to set their password.

The specifics of the password set page will be shaped by your design, and can be as complicated or as simple as required. If you want to present a page which performs client-side password complexity validation after retrieving the applicable password policy from the IDCS REST API, go for it. Since you are in control of the page, you can do what you like, though it will need to present the single-use token and desired password to a second endpoint (I used GET /activate and POST /activate).

This second endpoint needs to revalidate the token (since the client presents it back to you, and therefore could have modified it), and activating the user requires you to obtain the userId associated with the token. After validation, there are then several potential paths you could take. The aforementioned eventId from the token can be used to differentiate between a user activation event and a password reset if you are using a single UI for both (as IDCS does). This will then determine if you want to invoke the Activate User API in addition to the Password Set API.

It makes sense to invoke the Password Set API first, before attempting to flag the user as active, since this call is more likely to fail (if for instance, the password doesn’t meet complexity requirements). In order to update the user password, it is advisable to use the MePasswordResetter endpoint, which is able to consume the single-use email token. The significance of doing this is that it updates the token status, making it unable to be re-used. This API invocation is as follows:

POST <idcs-base-url>/admin/v1/MePasswordResetter

Headers:
  Authorization: Bearer <client_token>
  Content-Type: application/scim+json

Body:
  {
    "schemas": [
      "urn:ietf:params:scim:schemas:oracle:idcs:MePasswordResetter"
    ],
    "password":"<new password>",
    "token":"<token>"
  }

Again, take care with URI encoding of the token.

The result of this call is that the token is used to determine the relevant user, their password is updated, and the token is ‘consumed’, so that it cannot be used again. It returns a 201 on success.

After this invocation, if this is a user activation, you can activate the user through the UserStatusChanger API, which requires the user identifier obtained from the previous token lookup. This call looks like the following:

POST <idcs-base-url>/admin/v1/UserStatusChanger/<user identifier>

Headers:
  Authorization: Bearer <client_token>
  Content-Type: application/scim+json

Body:
  {
    "schemas": [
      "urn:ietf:params:scim:schemas:oracle:idcs: UserStatusChanger"
    ],
    "active": true
  }

This call activates the user, returning a 200 on a success. Once this is complete, you can redirect the user to wherever you need to, or serve them with some sort of success page. In my sample code, I just respond with a redirect to whatever URL is specified in the config. It is worth noting that the user doesn’t have an active session at this point, so if you direct them to a protected endpoint, they will probably be prompted to log in with the password that they just set. From a user experience perspective, it may make more sense to direct them to a page with a Welcome message which informs them to use the password they just set to log-in (if it is a user creation event), and to a page which informs them that their password has been reset, and they can now use it to login.

One of the quirks of this approach (using the MePasswordResetter) is that new users get a ‘Your password has been reset’ email, which is a little deceptive, since from their perspective, they just initially set a password, as opposed to resetting one. They also don’t receive the ‘User Activation’ email – though this could be achieved by using the MeActivator endpoint, but this consumes the user token and doesn’t allow setting of the password. This is an option that you could choose to pursue if you have certain notification requirements. Either way, you might want to consider disabling or modifying the notification settings as related to user password reset/activation.

 

I hope this serves as a strong example of how flexible IDCS is, where by design, you can extend or modify most aspects of its default behaviour, and by leveraging a range of IDCS APIs, you can obtain complete control over the user flows and the interfaces with which they interact. This allows you to present pixel perfect pages to your customers, ensuring predictable behaviour and consistency in look and feel. This is complemented by the customisation capabilities of the IDCS notification service, which allows you to completely overhaul the HTML source, including embedding CSS, to extend the look and feel of your organisation to the emails sent out around identity lifecycle events.

Advertisement

One thought on “Custom User Activation and Password Reset Flows in Oracle IDCS”

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: