Accessing subscription keys that are encoded in JWTs

Jonathan Oren 0 Reputation points
2023-12-17T11:41:31.71+00:00

So basically, the users subscription keys are encrypted and located in my db. The cipher of their keys are decoded into their JWTs. When a user logs into my system, I attach the JWT to the header as Authorization: Bearer {token} for their authentication within my website.

I encoded their APIM subscription keys into the JWT to abstract away a user's handling of keys. However, I am struggling in decrypting them and attaching them as ocp-apim-subscription-key headers for APIM. I initially tried using policies but couldn't find a way to do it with policies. They seem to only execute after a request was received, which they never will without this header. I also couldn't find a way to decrypt AEM with policies.

So now I am trying to add a gateway API in front of APIM, which would do the decryption and attach the ocp-apim-subscription-key header, but this proves very hard to implement correctly due to multiple complexities of HTTP requests, with forms, redirections, streaming, files, etc.

So I wanted to ask - Is there a better way of achieving what I am trying to do? Perhaps I have given up on using policies or something else in the APIM system prematurely? Or could you think of some other tool that could assist me in setting up my requirement?

Thanks a lot!

Azure API Management
Azure API Management
An Azure service that provides a hybrid, multi-cloud management platform for APIs.
2,466 questions
{count} votes

1 answer

Sort by: Most helpful
  1. Sonny Gillissen 3,751 Reputation points Volunteer Moderator
    2024-01-08T10:25:18.2433333+00:00

    Hi Jonathan Oren,

    Thank you for reaching out on Microsoft Q&A!

    Given the fact that you already encrypted the subscription key in the JWT token would leave you the ability to decrypt it as JWT as well. I personally used to do a source determination. So it is doable. My code example is as follows:

    <!-- Set source variable based on token -->
    <set-variable name="SubscriptionKey" value="@{
        // Get authorization header
        string authHeader = context.Request.Headers.GetValueOrDefault("Authorization");
        // Read JWT token
        string jwtToken = authHeader.ToString().Split('.')[1];
        // Fix BASE64 padding
        jwtToken = jwtToken.Replace(" ", "+");
        int mod4 = jwtToken.Length % 4;
        if (mod4 > 0 )
        {
            jwtToken += new string('=', 4 - mod4);
        }
        // Read claims
        string claims = Encoding.UTF8.GetString(Convert.FromBase64String(jwtToken));
        JObject claimsJson = JObject.Parse(claims);
        // Check if roles claim is present
        string source = "";
        if(claimsJson.SelectToken("roles") == null){
            // Return undefined when no roles present
            source = "UNDEFINED";
        }
        else
        {
            // Collect roles claim
            JArray rolesClaimArray = claimsJson.SelectToken("roles").Value<JArray>();
            // Loop over roles
            foreach(string roleClaim in rolesClaimArray) {
                // Check if role contains vendor
                bool vendorRoleFound = roleClaim.Contains("Vendor");
                if(vendorRoleFound) {
                    // Set vendor as source
                    source = roleClaim.Split('.')[1];
                }
            }
            // Check if vendor was found
            if(source == "") {
                // Return undefined when no roles present
                source = "UNDEFINED";
            }
        }
        return source;
    }" />
    

    The above code decrypts the JWT-token and derives information (source in my case) from it to use further on in the process. You can replace "roles" in my claims bit to anything of your liking. Be aware to adjust the processing of the claim as well (roles come in an array, don't know about yours).

    Next, in your case the is sending it through as an 'Ocp-Apim-Subscription-Key' header. So this would the be the next bit of policy:

    <set-header name="Ocp-Apim-Subscription-Key" exists-action="override">
        <value>@(context.Variables["SubscriptionKey"])</value>
    </set-header>
    

    Please click “Accept answer” if you find this helpful. Feel free to drop additional queries in the comments below!

    Kind regards,

    Sonny

    0 comments No comments

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.