Reputation: 527
This may not be supported but I was thinking about a scenario such as this. Lets say there is an internal endpoint that uses AD authentication. If one were to route an Azure APIM call to this backend, is there a way to get the end user who may have initiated the call to the APIM endpoint? Or is this not the scenario it was meant for? Is APIM meant more for application-to-application type calls and not necessarily something an enduser might initiate?
Thanks in advance, Jake.
Upvotes: 2
Views: 4966
Reputation: 15734
For your requirement, I did lots of test for it. Please refer to my steps below:
As the endpoint uses AD authentication, so user needs to provide a token when request the APIM(to request the endpoint). So we can know the user name by decode the token which provided when request the APIM. Before do it, you need to know only when the user use a grant flow like username/password flow or auth code flow, the token can include user identity. If the user use a grant flow like client credential flow to get the token, the token will not include user identity. So in my solution I assume user use username/password flow or auth code flow to get the token.
The I did some test, I want to get the token in request header of APIM. So I configure "Diagnostic settings" of APIM to stream logs to azure storage(or event hub). Then query the logs in "Logs" tab of APIM. But I found we can not see the headers of the request in the logs, both RequestHeaders
and BackendRequestHeaders
fields are empty (shown in below screenshot).
So I don't think we can get user identity according to the token by normal solution.
But here I provide a workaround for your reference:
I created a azure function with default code, and just add one line.
Then I added a policy in APIM inbound
block.
<policies>
<inbound>
<base />
<send-request mode="new" response-variable-name="tokenstate" timeout="20" ignore-error="true">
<set-url>https://huryxxxxtestfun.azurewebsites.net/api/HttpTrigger6</set-url>
<set-method>POST</set-method>
<set-header name="Content-Type" exists-action="override">
<value>application/json</value>
</set-header>
<set-body>@{
string authHeader = context.Request.Headers.GetValueOrDefault("Authorization", "");
string name = "unknown";
if (authHeader?.Length > 0)
{
string[] authHeaderParts = authHeader.Split(' ');
if (authHeaderParts?.Length == 2 && authHeaderParts[0].Equals("Bearer", StringComparison.InvariantCultureIgnoreCase))
{
Jwt jwt;
if (authHeaderParts[1].TryParseJwt(out jwt))
{
name = (jwt.Claims.GetValueOrDefault("name", "unknown"));
}
}
}
return new JObject(new JProperty("name",name)).ToString();
}</set-body>
</send-request>
</inbound>
<backend>
<base />
</backend>
<outbound>
<base />
</outbound>
<on-error>
<base />
</on-error>
</policies>
The <send-request>
policy is used to request the azure function url. I decode the token in policy and get the user name, send the name to azure function. Then we can see the user name in azure function log.
By the way, we can also get object id of the user by modify the code name = (jwt.Claims.GetValueOrDefault("name", "unknown"));
to name = (jwt.Claims.GetValueOrDefault("oid", "unknown"));
in policy.
Upvotes: 2