Accessing protected API on IdentityServer4 with Bearer Token

旧城冷巷雨未停 提交于 2020-08-06 12:52:47

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!