Reputation: 46720
I have the "Server application accessing a web API" scenario.
The web site uses OIDC and authenticates no problem.
However, I have a use case for accessing some of the web API without a user context and for that, I use client_credentials.
The server app has a client ID and the secret key.
So assume the web API URL is:
https://my-pc/WebService/api/my-api/
The web API has the RP identifier:
https://my-pc/WebService/api/my-api/
Access control policy is:
Permit everyone
I have one claim rule:
c:[] => issue(claim = c);
Client permissions is set to:
"All clients" with scope of openid and user_impersonation.
The code is:
AuthenticationContext ac = new AuthenticationContext("https://my-adfs/adfs/", false);
// ClientCredential contains client_id and secret key
AuthenticationResult result = await ac.AcquireTokenAsync("https://my-pc/WebService/api/my-api/", clientCredential);
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, "https://my-pc/WebService/api/my-api/");
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", result.AccessToken);
HttpContent content = new FormUrlEncodedContent(new[] { new KeyValuePair<string, string>("foo", "blah"), new KeyValuePair<string, string>("foo1", "blah1") });
request.Content = content;
HttpResponseMessage response = await client.SendAsync(request);
ADFS returns the access token no problem but when I call the web api, I keep getting a 401 - Unauthenticated.
Any ideas?
Upvotes: 0
Views: 1261
Reputation: 46720
Finally figured this out and wrote it up.
The two pieces of code:
using Microsoft.IdentityModel.Clients.ActiveDirectory;
ClientCredential clientCredential = new ClientCredential(clientId, secretKey);
AuthenticationContext ac = new AuthenticationContext("https://my-adfs/adfs/", false);
AuthenticationResult result = await ac.AcquireTokenAsync("https://my-pc/WebService",
clientCredential);
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post,
"https://my-pc/WebService/api/my-api/");
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", result.AccessToken);
HttpContent content = new FormUrlEncodedContent(new[] { new KeyValuePair<string,
string>("foo", "blah"), new KeyValuePair<string, string>("foo1", "blah1") });
request.Content = content;
HttpResponseMessage response = await client.SendAsync(request);
if (response.IsSuccessStatusCode)
// etc
And in Startup.Auth.cs
app.UseActiveDirectoryFederationServicesBearerAuthentication(
new ActiveDirectoryFederationServicesBearerAuthenticationOptions
{
TokenValidationParameters = new TokenValidationParameters()
{
SaveSigninToken = true,
ValidAudience = "https://my-pc/WebService"
},
MetadataEndpoint = "https://my-adfs/FederationMetadata/2007-06/FederationMetadata.xml"
});
Took me a while!
Upvotes: 1
Reputation: 1
Since you don't get the user principal in the access token, you have no user session attached to a principal. When the Web API looks for the principal in the cookie(or Authorization header if you're sending access token) it doesn't find the principal and you will still be an anonymous user.
Upvotes: 0