问题
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.
回答1:
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")]
回答2:
Found a better solution, configure in the Startup.cs:
services.AddAuthentication()
.AddLocalApi();
services.AddAuthorization(options =>
{
options.AddPolicy(IdentityServerConstants.LocalApi.PolicyName, policy =>
{
policy.AddAuthenticationSchemes(IdentityServerConstants.LocalApi.AuthenticationScheme);
policy.RequireAuthenticatedUser();
});
});
And use in controllers:
[Authorize(IdentityServerConstants.LocalApi.PolicyName)]
public class UserInfoController : Controller
{
...
}
来源:https://stackoverflow.com/questions/52765570/accessing-protected-api-on-identityserver4-with-bearer-token