Refreshing access tokens in EPL apps without redeploying

EPL apps provide a way to add your own logic according to the use cases into Cumulocity IoT in the form of a monitor file. One such use case could be talking to HTTP endpoints secured with authorization protocols which involve access tokens. This post talks about the problems and the possible solution for this particular use case.

Usually these access tokens are only valid for a certain period of time and then need to be refreshed with the authorization server once expired. In those scenarios, hard coding the token in an EPL app demands the author to redeploy the app with the updated value of the access token every time the token expires. This post provides a possible solution about how we can refresh the access token in the EPL app without having to manually modify or redeploy the app. Furthermore, we can configure the app to provide an early notification of a token that is about to expire by logging a warning, triggering the refresh-token subroutine, or sending an SMS/email to the personnel responsible for managing the tokens.

To achieve this, we need to introduce a TokenFactory which will be responsible for providing token updates to all the consumers which are interested in various tokens. This TokenFactory itself will be listening for token updates that are POSTed by the token manager (personnel responsible for refreshing the token values). The following flow diagram shows the basic interaction between a token consumer and TokenFactory.

flow diagram

To refresh the access token in a running EPL app, the token manager needs to POST a Cumulocity IoT event with the updated value of the access token to the TokenFactory. To make sure that this event is not stored anywhere and is only forwarded to the Apama-ctrl microservice, we should add the following header to our POST request:

X-Cumulocity-Processing-Mode: CEP

For more information on processing modes, see the Cumulocity IoT – HTTP Usage/Processing modes.

The EPL implementation for the TokenFactory shown above is available as the following GitHub repository: working_with_access_tokens_in_eplapps. Here are some snippets from the repository code with explanation:

The above code expects a token consumer to TokenRegistrar.registerInterest in a particular token with eventType as the unique identifier for the Cumulocity IoT event which will carry the refreshed value of the token of interest. Multiple consumers can register for updates to the same token. Any updates to a particular token via a Cumulocity IoT event will trigger callback notifications to only the interested consumers. If a token does not receive an update and expires, a warning is logged and all consumers get a notification callback with an empty string as the token value, which implies an invalid token. Consumers can take appropriate actions for invalid tokens.

Here is an example of a token consumer:

The above code expects the token publisher to send token updates via a Cumulocity IoT event which should have the following information in the event body:

  • event.type = "uniqueType_for_redirect_uri_ABC"
  • token = "some_token_value"
  • expirationTime = expiry_timestamp_for_token *

* Access tokens are usually provided with an expiration period, for example, 3600 seconds. The expirationTime in the event should be a value equal to the token generation time plus the expiration period. It should be provided as a timestamp value equal to the number of seconds and fractional seconds elapsed since midnight, January 1, 1970 UTC.

Sending a token update to the TokenFactory

Based on the authorization protocol used to secure the endpoint, we can generate an access token using protocol-specific request-response cycles. Then we need to create a Cumulocity IoT event to POST this token as an update to the TokenFactory. For example, we can use curl to create an event:

 

Note the header X-Cumulocity-Processing-Mode: CEP in the curl request. You should use this header to make sure that this event is not stored anywhere and is only forwarded to (or available to) the cep endpoint in the Apama-ctrl microservice.

The <Payload> in the above request is a JSON body. It should contain all required fields for a Cumulocity IoT event as shown below. The type of the event should be set to the eventType that was provided while registering interest in any token. The payload should also contain two extra fields: token and expirationTime which are read in TokenFactory.

For more details on how to create a Cumulocity IoT event, see the Cumulocity IoT – OpenAPI Specification.

If the process of generating a new access token does not require human interaction like in a multi-factor authentication setup, then the process of generating and posting a token update to Apama can be entirely automated as some sort of small script.

Making the TokenFactory available to all EPL apps which use tokens

If we deploy EPL code as an EPL app, that code is not available to other EPL apps. So in order to share the TokenFactory with all other EPL apps, we must upload it as an extension. For details on how to upload an extension, see the section “Uploading a block to Analytics Builder” in the Knowlegde base article Analytics Builder Block SDK which is available from the Tech Community.

Links