Feb 07 2024 04:08 AM - edited Feb 07 2024 04:14 AM
Hi There,
I have a scenario where we use OKTA as identity provider . We want to put the OKTA M2M token endpoint behind API management and cache the token until expires (1 hour). We are using API management external cache to store the token. So that consumers can't request fresh OKTA tokens again and again. The problem arises when OKTA changes its signing key. Anytime OKTA can change the signing key and old token may be present in the cache which will no longer be valid. I need a suggestion to remove the cached token when the validate-jwt policy fails due to signing key changes.
OKTA token Endpoint:https://myorganization.oktapreview.com/oauth2/default/v1/token
CURL: curl --location 'https://myorganization.oktapreview.com/oauth2/default/v1/token' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--header 'Authorization: Basic {username:password}' \
--data-urlencode 'grant_type=client_credentials' \
--data-urlencode 'scope=clientcredential'
Below is my APIM policy code.
<policies>
<inbound>
<set-variable name="OktaCacheKey" value="@((context.Request.Headers.GetValueOrDefault("Authorization", "")))" />
<cache-lookup-value key="@((string)context.Variables["OktaCacheKey"])" variable-name="OKTAResponseCache" />
<choose>
<when condition="@(context.Variables.ContainsKey("OKTAResponseCache"))">
<set-variable name="token" value="@{
string cachedOKTAResponse = (string)context.Variables["OKTAResponseCache"];
var parsedJson = (Newtonsoft.Json.Linq.JObject)JsonConvert.DeserializeObject(cachedOKTAResponse);
string access_token = (string)parsedJson["access_token"];
return access_token;
}" />
<validate-jwt token-value="@((string)context.Variables["token"])" failed-validation-httpcode="401" failed-validation-error-message="Invalid Token!" output-token-variable-name="api.Auth.Token">
<openid-config url="https://myorg.oktapreview.com/oauth2/default/.well-known/openid-configuration" />
<audiences>
<audience>api://default</audience>
</audiences>
<issuers>
<issuer>https://myorg.oktapreview.com/oauth2/default</issuer>
</issuers>
<required-claims>
<claim name="scp" match="any">
<value>clientcredential</value>
</claim>
</required-claims>
</validate-jwt>
</when>
</choose>
<choose>
<when condition="@(context.Variables.ContainsKey("OKTAResponseCache"))">
<return-response>
<set-status code="200" reason="description" />
<set-header name="Content-Type" exists-action="override">
<value>application/json</value>
</set-header>
<set-body>@((string)context.Variables["OKTAResponseCache"])</set-body>
</return-response>
</when>
</choose>
</inbound>
<backend>
<!--base: Begin Global scope-->
<forward-request />
<!--base: End Global scope-->
</backend>
<outbound>
<choose>
<!--base: End Global scope-->
<choose>
<when condition="@(context.Response.StatusCode == 200)">
<set-variable name="responseValue" value="@(context.Response.Body.As<string>(preserveContent: true))" />
<cache-store-value key="@((string)context.Variables["OktaCacheKey"])" value="@((string)context.Variables["responseValue"])" duration="3600" />
</when>
</choose>
</outbound>
<on-error>
<choose>
<when condition="@(context.LastError.Source == "validate-jwt")">
<cache-remove-value key="@((string)context.Variables["OktaCacheKey"])" caching-type="internal" />
<return-response>
<set-status code="@(context.Response.StatusCode)" />
<set-body>Cached Access token is invalid. Please request a new token.</set-body>
</return-response>
</when>
</choose>
</on-error>
</policies>