1

I'm using MSAL with ADFS2019 and I try to call an internal API on behalf of the authenticated user of my web app. I have a valid access token with some additional claims to identify the user :

{
  "aud": "https://SRV",
  "iss": "[***REMOVED***]",
  "iat": 1687181262,
  "nbf": 1687181262,
  "exp": 1687184862,
  "email": "user1@mydomain.com",
  "winaccountname": "user1@mydomain.com",
  "anchor": "sub",
  "sub": "user1@mydomain.com",
  "apptype": "Confidential",
  "appid": "https://SRV",
  "authmethod": "http://schemas.microsoft.com/ws/2008/06/identity/authenticationmethod/windows",
  "auth_time": "2023-06-19T12:11:56.653Z",
  "ver": "1.0",
  "scp": "email user_impersonation profile openid"
}

I use that token as UserAssertion when I'm calling the AcquireTokenOnBehalfOf method. The call is successful but there's absolutely no claims in the received token to help me identify the user (only the app) calling the API:

{
  "aud": "api://API",
  "iss": "[***REMOVED***]",
  "iat": 1687181215,
  "nbf": 1687181215,
  "exp": 1687184815,
  "apptype": "Confidential",
  "appid": "https://SRV",
  "auth_time": "2023-06-19T12:11:56.653Z",
  "authmethod": "http://schemas.microsoft.com/ws/2008/06/identity/authenticationmethod/windows",
  "ver": "1.0",
  "scp": "profile user_impersonation openid email"
}

Here's the code I use to generate the second token :

var token = await HttpContext.GetTokenAsync("access_token");
var resource = _configuration["ADFS:Resource"];

var client = ConfidentialClientApplicationBuilder.Create(_configuration["ADFS:ClientID"]).
            WithAdfsAuthority(_configuration["ADFS:Instance"]).
            WithClientSecret(_configuration["ADFS:ClientSecret"]).Build();
var userAssertion = new UserAssertion(token, "urn:ietf:params:oauth:grant-type:jwt-bearer");
var result = await client.AcquireTokenOnBehalfOf(new[] { $"{resource}/openid", $"{resource}/email" , $"{resource}/user_impersonation" }, userAssertion)
            .WithClaims("sub, upn")
            .ExecuteAsync();

var httpClient = _httpClientFactory.CreateClient("WebAPI");
httpClient.BaseAddress = new Uri(_configuration["ServiceUrl"]);
httpClient.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("bearer", result.AccessToken);
Weather = await httpClient.GetFromJsonAsync<IEnumerable<WeatherServiceResponse>>("/WeatherForecast");

return;

What am I missing ? It's probably a stupid mistake but I'm new to all this and there's not a lot of good documentation on how to fix the problem with ADFS (but a lot with AAD).

Thanks.

mberube.Net
  • 2,120
  • 2
  • 29
  • 39
  • We don't post images of text here. It's the fastest way I've seen other than spam for a question to be downvoted and then closed or ignored. – Joel Coehoorn Jun 19 '23 at 14:50
  • Also, what is the result returned to the `Weather` variable when you try to run this? – Joel Coehoorn Jun 19 '23 at 14:54
  • Thanks for the info @JoelCoehoorn, I'll fix that quickly – mberube.Net Jun 19 '23 at 15:00
  • The result of the Weather variable is the return value of the API. It's not the problem here. The problem is that when I call the API, I've no way to identify the user calling the weather API because there's no claim with user identifiable value. – mberube.Net Jun 19 '23 at 15:01
  • Typically these APIs infer the user from the bearer token provided via the header, but other than that it doesn't seem the api cares. – Joel Coehoorn Jun 19 '23 at 16:18
  • What do you mean by that ? How can the API "infer" the user from the bearer token if there's no claim to identify the user ? – mberube.Net Jun 19 '23 at 17:02
  • When the API server verifies the token, part of that will involve matching it to the account for which it was issued. – Joel Coehoorn Jun 19 '23 at 19:06

0 Answers0