One-Time-Authorization-Code for Rest APIs in WSO2 Identity Server

Authorizing the Caller’s Security Context in an API Workflow

Johann Dilantha Nallathamby
4 min readMay 19, 2021

Introduction

WSO2 Identity Server provides many identity management workflows and password management workflows out-of-the-box. E.g. self-registration, user invitations, password recovery, etc. However, it is not atypical to come across situations where you would find that the workflow capabilities provided out-of-the-box in the product is not sufficient to fulfil your business requirement.

In such situations users would generally prefer to take one of the following alternative courses of action, listed in ascending order of complexity:

  1. Combining couple of existing Rest APIs in a specific sequence to produce the expected workflow.
  2. Implementing custom Rest APIs and combining them with existing Rest APIs in a specific sequence to produce the expected workflow. The custom Rest APIs may or may not invoke WSO2 Java services in the backend. The custom Rest API will also be hosted in WSO2 Identity Server.

The user experience will most probably need to be bespoke on top of the customized backend.

One of the cross cutting security requirements in all API workflows is, ensuring the caller’s security context is the same across the workflow. In other words:

“How do we ensure that the caller who is invoking the current Rest API, is the one and the same who invoked the previous Rest API ?”

For the built-in API workflows, this requirement is already addressed. For instance, if we take a look at admin-initiated forced password reset[1] workflow, it consists of two separate Rest APIs; the first one to initiate sending a verifier[2] and the second one to present the verifier and update the password[3]. The “confirmationCode” parameter is used as the verifier to authorize the caller’s security context in the “updatePassword” operation. Similarly, we need a generic mechanism to engage verifiers to any custom API workflow in WSO2 Identity Server.

One-Time-Authorization-Code

The means in which we are going to solve the above problem is using One-Time-Authorization-Code (OTAC) verifiers. Using OTAC for authorizing API access isn’t novelty. This idea has inspirations borrowed from the very popular OAuth 2.0 suite of standards that addresses delegated access control for APIs. In OAuth 2.0, the “authorization code” is an intermediate code that is used to represent the authorization grant given by the “resource owner” to the “client”, issued at the “Authorization endpoint” and verified at the “Token endpoint”. The “authorization code” is in fact a time-bound one-time-code [4]. Similarly, “OAuth 2.0 Threat Model and Security Considerations” (RFC 6819) recommends techniques like using short expiration times [5], one-time usage [6] and use explicitly defined scopes for audience and tokens [7] for “access tokens”.

If you are wondering, OTACs are equally applicable to secured APIs as much as open APIs. Open APIs don’t enforce authentication; however, authorization that is not based on an authenticated subject is still a possibility. Secured APIs on the other hand could also need OTACs because, API authentication only asserts who the caller is; however, it doesn’t assert anything more about the caller’s context.

In terms of implementation of OTACs, using “JSON-Web-Token” (JWT) [8] standard is advantageous as it helps to build a stateless OTAC implementation, so that you don’t need to worry about having a mechanism in place to clean up inactive OTACs, like stored procedures.

Sample User Story: Consumer Onboarding Workflow

In order to understand this problem and its requirements better, let’s look at a sample user story. The sample user story we will take is a consumer onboarding workflow.

Requirement

Imagine we want to compose a consumer onboarding workflow which is going to consist of the following 4 components in order:

  1. Initiate with Invitation workflow
  2. Email address verification
  3. Mobile number verification
  4. Set Password

As you may have already guessed, WSO2 Identity Server doesn’t have a single Rest API that supports the above onboarding workflow out-of-the-box. However, it provides multiple Rest APIs that implement parts of the above workflow. For instance step #1 can be achieved with Invitation workflow [9]; step #2 can be achieved with including the e-mail address verification option [10] to the invitation workflow. #3 and #4 can be achieved with “admin-initiated force password reset” [2] API. Hence, naturally our immediate reaction is to think whether we can combine these Rest APIs in the particular sequence to achieve our end-to-end workflow requirement.

As discussed before, the Invitation workflow with email verification option is a distinct workflow from the admin-initiated forced password reset workflow. Hence, there is a no built-in verifier that is returned in the response from #2 and passed in the request and verified in #3. The challenge we face now is:

“How do we ensure that the caller who is invoking the step #3, is the one and the same who invoked #2?”.

Hence, we are faced with the prospect of introducing a new verifier to the API workflow that is going to be composed from these two Rest APIs.

In my article “Self-service Authorization for Admin Rest APIs in WSO2 Identity Server” [11], I discuss about using the intercepting filter pattern to override the authorization logic of the Admin Rest APIs in WSO2 Identity Server. We will be utilizing the same solution for solving this user story as well.

Solution

  1. Add a new interceptor to the Rest API that will intercept the response of #2 and insert a OTAC to the response as a custom header.
  2. Add a new interceptor to the Rest API that will intercept the request of #3 and verify the OTAC coming in a customer header.

The benefit of using headers to transport the OTAC is, it decouples the security contract from the business API contract. You can find the implementation of OTAC for WSO2 Identity Server here [12].

References

[1] https://is.docs.wso2.com/en/latest/learn/forced-password-reset/

[2] https://medium.com/@isurakarunaratne/admin-initiated-password-reset-feature-in-wso2-identity-server-483dad5163ce

[3] https://is.docs.wso2.com/en/latest/develop/user-information-recovery-service/#updatepassword

[4] https://datatracker.ietf.org/doc/html/rfc6749#section-4.1.2

[5] https://datatracker.ietf.org/doc/html/rfc6819#section-5.1.5.3

[6] https://datatracker.ietf.org/doc/html/rfc6819#section-5.1.5.4

[7] https://datatracker.ietf.org/doc/html/rfc6819#section-5.1.5.6

[8] https://jwt.io/introduction

[9] https://is.docs.wso2.com/en/latest/learn/creating-users-using-the-ask-password-option/

[10] https://is.docs.wso2.com/en/latest/learn/creating-users-using-the-ask-password-option/#on-boarding-with-email-verification

[11] https://johann-nallathamby.medium.com/self-service-authorization-for-admin-rest-apis-in-wso2-identity-server-6b14b2ffafef

[12] https://github.com/johannnallathamby/wso2-is-authz-rest-otac

--

--