I have attempted to search for a solution to this problem, but have not found the right search text.
My question is, how can I configure my IdentityServer so that it will also accept/authorize Api Requests with BearerTokens?
I have an IdentityServer4 configured and running. I also have configured a Test API on my IdentityServer like below:
[Authorize]
[HttpGet]
public IActionResult Get()
{
return new JsonResult(from c in User.Claims select new { c.Type, c.Value });
}
In my startup.cs ConfigureServices() is as follows:
public IServiceProvider ConfigureServices(IServiceCollection services)
{
...
// configure identity server with stores, keys, clients and scopes
services.AddIdentityServer()
.AddCertificateFromStore(Configuration.GetSection("AuthorizationSettings"), loggerFactory.CreateLogger("Startup.ConfigureServices.AddCertificateFromStore"))
// this adds the config data from DB (clients, resources)
.AddConfigurationStore(options =>
{
options.DefaultSchema = "auth";
options.ConfigureDbContext = builder =>
{
builder.UseSqlServer(databaseSettings.MsSqlConnString,
sql => sql.MigrationsAssembly(migrationsAssembly));
};
})
// this adds the operational data from DB (codes, tokens, consents)
.AddOperationalStore(options =>
{
options.DefaultSchema = "auth";
options.ConfigureDbContext = builder =>
builder.UseSqlServer(databaseSettings.MsSqlConnString,
sql => sql.MigrationsAssembly(migrationsAssembly));
// this enables automatic token cleanup. this is optional.
options.EnableTokenCleanup = true;
options.TokenCleanupInterval = 30;
})
// this uses Asp Net Identity for user stores
.AddAspNetIdentity<ApplicationUser>()
.AddProfileService<AppProfileService>()
;
services.AddAuthentication(IdentityServerAuthenticationDefaults.AuthenticationScheme)
.AddIdentityServerAuthentication(options =>
{
options.Authority = authSettings.AuthorityUrl;
options.RequireHttpsMetadata = authSettings.RequireHttpsMetadata;
options.ApiName = authSettings.ResourceName;
})
and Configure() is as follows:
// NOTE: 'UseAuthentication' is not needed, since 'UseIdentityServer' adds the authentication middleware
// app.UseAuthentication();
app.UseIdentityServer();
I have a client configured to allow Implicit grant types and have included the configured ApiName as one of the AllowedScopes:
new Client
{
ClientId = "47DBAA4D-FADD-4FAD-AC76-B2267ECB7850",
ClientName = "MyTest.Web",
AllowedGrantTypes = GrantTypes.Implicit,
RequireConsent = false,
RedirectUris = { "http://localhost:6200/assets/oidc-login-redirect.html", "http://localhost:6200/assets/silent-redirect.html" },
PostLogoutRedirectUris = { "http://localhost:6200/?postLogout=true" },
AllowedCorsOrigins = { "http://localhost:6200" },
AllowedScopes =
{
IdentityServerConstants.StandardScopes.OpenId,
IdentityServerConstants.StandardScopes.Profile,
IdentityServerConstants.StandardScopes.Email,
"dev.api",
"dev.auth" // <- ApiName for IdentityServer authorization
},
AllowAccessTokensViaBrowser = true,
AllowOfflineAccess = true,
AccessTokenLifetime = 18000,
},
When I use Postman to access the protected API but it always redirects to the Login page even though a valid Bearer Token has been added to the Request header.
Commenting out the [Authorize] attribute will correctly return a response, but of course the User.Claims are empty.
When logging into the IdentityServer (via a browser) and then accessing the API (via the browser) it will also return a response. This time, the User.Claims are available.
Bearer tokens enable requests to authenticate using an access key, such as a JSON Web Token (JWT). The token is a text string, included in the request header. In the request Authorization tab, select Bearer Token from the Type dropdown list. In the Token field, enter your API key value.
When using reference tokens - IdentityServer will store the contents of the token in a data store and will only issue a unique identifier for this token back to the client. The API receiving this reference must then open a back-channel communication to IdentityServer to validate the token.
A bearer token is an encoded value that generally contains the user ID, authenticated token and a timetamp. It is most commonly used in REST APIs. If the API supports OAuth2 then it'll use a bearer token. The user (or client app) sends credentials to the server to authenticate.
There is an example co-hosting a protected API inside IdentityServer: IdentityServerAndApi
I quick comparison between their startup and yours is that they are calling AddJwtBearer
instead of AddIdentityServerAuthentication
:
services.AddAuthentication()
.AddJwtBearer(jwt => {
jwt.Authority = "http://localhost:5000";
jwt.RequireHttpsMetadata = false;
jwt.Audience = "api1";
});
TheAuthorize
attribute also sets the authentication scheme:
[Authorize(AuthenticationSchemes = "Bearer")]
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With