Reputation: 11121
My ASP.NET Core 2.2 web site uses OpenIdConnect to connect to an external OIDC provider for authentication. So we get a redirect to the provider, you log in, it returns back to the site. All of this is handled server side and works great.
Our web site uses javascript to communicate to the API backend, which is decorated with an [Authorize] attribute.
Now, we want to share our API with another application. I am having trouble understanding how to make it work with the existing OpenIdConnect provider. If I use Postman to make a call, I add a Bearer token but I am returned the log in screen for my OIDC provider. I understand this, it's set up for OIDC.
I have tried using AddJwtBearer with [Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)] set on my Controller and when I do that I can successfully pass in a Bearer token and call my API from Postman but I can't make a call from a javascript page on my site.
So the ultimate question is, how do I configure this site so that I can call an API from my site itself with OIDC and also call from an external app using a Bearer token?
The code looks like this:
public void ConfigureServices(IServiceCollection services)
{
var authbuilder = services.AddAuthentication(options =>
{
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
});
authbuilder.AddCookie(p =>
{
p.SlidingExpiration = true;
p.Events.OnSigningIn = (context) =>
{
context.CookieOptions.Expires = DateTimeOffset.UtcNow.AddHours(14);
return Task.CompletedTask;
};
});
authbuilder.AddOpenIdConnect(options =>
{
options.Authority = Configuration["OpenIdConnectSettings:AuthorityUrl"];
options.ClientSecret = Configuration["OpenIdConnectSettings:ClientSecret"];
options.ClientId = Configuration["OpenIdConnectSettings:ClientId"];
}
options.SaveTokens = true;
options.ResponseType = OpenIdConnectResponseType.CodeIdToken;
options.GetClaimsFromUserInfoEndpoint = true;
options.Events = new OpenIdConnectEvents
{
OnTokenValidated = context =>
{
// validation logic omitted
}
EDIT: Any external apps will also use the same OIDC provider. It's just a matter of getting my API Controllers to work from the web site itself and being called from another app that uses the same OIDC provider.
EDIT: I think I may have gotten it to work by adding this code:
services.AddAuthorization(options =>
{
var defaultAuthorizationPolicyBuilder = new AuthorizationPolicyBuilder(
JwtBearerDefaults.AuthenticationScheme, OpenIdConnectDefaults.AuthenticationScheme);
defaultAuthorizationPolicyBuilder = defaultAuthorizationPolicyBuilder.RequireAuthenticatedUser();
options.DefaultPolicy = defaultAuthorizationPolicyBuilder.Build();
});
Upvotes: 2
Views: 2004
Reputation: 19921
if the other application is a service/application (not a human facing client) then that application needs to register as a client in your OIDC provider and then preferably use the client credentials flow, to get a token from your OIDC provider and pass it to the API.
The API only trusts access tokens from your OIDC provider (the token issuer), so the application needs to authenticate against the app and to get a proper access token.
Upvotes: 0