Create Self Service AI using Azure Foundry with user token monitoring and limit

Stavros Koureas 16 Reputation points
2026-06-17T15:04:03.5533333+00:00

There is the need to have a process where a user requests access for AI usage, we as administrators approve requests, the users get the api keys, be aware of available APIs and configure them within AI Tools.

The only close way to do this seems to be Azure API Management Service connected with Azure Foundry (aka AI Gateway). There we can define the available APIs like completions, responses, messages, etc and configure polices.

One challenge is that in order this to work the Client should sent the subscription key either via Header or via Query parameter while the Subscription required is set to true.

APIM

This works nice from Postman by sending the subscription key as header Ocp-Apim-Subscription-Key, or as header api-key as long it matches with the configuration in APIM.

But there are some AI Tools like VSCode which emmit the Header as "Authorization" and even this matches with configuration in APIM, it would be unable to parse the key as the Header "Authorization" is combination of "Bearer" and the key, like the below:

Bearer xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

So I tried tone of ways like building an inbound policy like the below, which extracts the key even from "Authorization" header from the part after the Bearer, or from "api-key" header or from "Ocp-Apim-Subscription-Key" header. Then I try to override the Ocp-Apim-Subscription-Key as I need the APIM update the context.Subscription?.Key, but this does not happen.

        <set-variable name="clientKey" value="@{
                var auth = context.Request.Headers.GetValueOrDefault("Authorization", "");
                if (auth.StartsWith("Bearer ")) {
                    var token = auth.Substring(7).Trim();
                    if (token != "") { return token; }
                }

                var apiKey = context.Request.Headers.GetValueOrDefault("api-key", "").Trim();
                if (apiKey != "") { return apiKey; }

                var subKey = context.Request.Headers.GetValueOrDefault("Ocp-Apim-Subscription-Key", "").Trim();
                if (subKey != "") { return subKey; }

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

So for debugging purposes, if we use the below outbound policy, we will see that the clientKey is populated

<return-response>
	<set-status code="200" reason="DEBUG" />
	<set-body>@((string)context.Variables["clientKey"])</set-body>
</return-response>

But if we use the below outbound policy, we will see that the context.Subscription is null

<return-response>
	<set-status code="200" reason="DEBUG" />
	<set-body>
	   @{ return "Subscription Key=" + (context.Subscription?.Key); }
	</set-body>
</return-response>

So it seems that the evaluation of context.Subscription happends before and does not re-evaluated.
As a result apps like VSCode GitHub Copilot will be unable to be validated properly and also monitored.

The policy works to extract subscription key and use it for example to limit the tokens per subscription based on another policy on this variable but it does not contribute into APIMs internal mechanism.

APIM2

Any idea?

Azure API Management
Azure API Management

An Azure service that provides a hybrid, multi-cloud management platform for APIs.


2 answers

Sort by: Most helpful
  1. Alex Burlachenko 25,115 Reputation points MVP Volunteer Moderator
    2026-06-22T13:22:14.7633333+00:00

    Stavros Koureas hi, thx for sharing urs issue here at Q&A portal,

    Yep, ur read is right. APIM resolves context.Subscription before ur inbound policy changes the header, so setting Ocp-Apim-Subscription-Key inside the policy won’t make APIM re-run subscription lookup. In other words, by the time ur policy runs, APIM has already decided if the request has a valid subscription or not. So this part can extract the key fine, but it won’t populate context.Subscription.

    For APIM’s built-in subscription tracking, the client needs to send the key in the configured subscription key header/query param from the start. https://learn.microsoft.com/en-us/azure/api-management/api-management-subscriptions

    For tools that only send Authorization Bearer <key>, best workaround is to set Subscription required = false, parse the Bearer value yourself, then use policies like quota-by-key / rate-limit-by-key with ur extracted clientKey as the counter key. That won’t populate APIM’s native context.Subscription, but u can still meter/limit per user/key. https://learn.microsoft.com/en-us/azure/api-management/quota-by-key-policy

    If u need native APIM subscription analytics, the tool has to send Ocp-Apim-Subscription-Key, api-key, or whatever header u configured in the API settings. Rewriting Authorization into that header inside inbound policy is too late for native subscription matching. For VS Code/Copilot-style clients, check if the tool config lets u add custom headers. If yes, add the APIM subscription key as api-key or Ocp-Apim-Subscription-Key and keep Authorization for whatever the tool expects. If it can’t send custom headers, u prob need custom policy-based metering instead of APIM subscription analytics.

    So yeah, not a bug in ur policy. It’s just APIM pipeline order biting u. Classic ‘works exactly as designed, still hurts’ case.

    rgds,

    Alex

    &

    If my answer was helpful pls mark it and additional thx if u follow me at Q&A portal

    Was this answer helpful?

    0 comments No comments

  2. Anshika Varshney 15,535 Reputation points Microsoft External Staff Moderator
    2026-06-18T18:32:24.99+00:00

    Hi @Stavros Koureas

    Thank you for the detailed feedback and for sharing your findings from testing various AI tools and authentication patterns.

    I understand the challenge you're describing. Many AI clients and IDE integrations (such as OpenAI-compatible tools, coding assistants, and desktop AI applications) commonly send credentials using the:

    Authorization: Bearer <token>
    

    header rather than the subscription key mechanisms traditionally used by API Management subscriptions.

    Given your testing results, it makes sense that additional flexibility in how APIM identifies and maps callers could simplify scenarios involving Azure AI Foundry and other OpenAI-compatible services.

    Your observations regarding:

    • Custom throttling policies based on your own variables rather than context.Subscription
    • Difficulty exposing usage statistics through the Developer Portal
    • The need to support both api-key and Authorization: Bearer authentication patterns
    • Front Door limitations around header transformations

    provide useful real-world feedback for this scenario.

    From a practical standpoint, your current custom throttling approach appears to be a reasonable workaround when subscription-based identification doesn't align with the authentication model used by the client application.

    Since you've already validated that Azure AI Foundry accepts both API key and Bearer token authentication methods, documenting these findings and sharing them as product feedback may help the team better understand the requirements for AI Gateway and OpenAI-compatible client integrations.

    Thank you for sharing the testing results across multiple AI tools and IDE extensions. This additional context is helpful for others who may be implementing similar architectures using Azure AI Foundry, APIM, and AI Gateway capabilities.

    Do let me know if you have any further queries.

    Thankyou!

    Was this answer helpful?


Your answer

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