Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Accessing protected API on IdentityServer4 with Bearer Token

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.

like image 670
mTrilby Avatar asked Oct 11 '18 17:10

mTrilby


People also ask

How do I pass a bearer token in API?

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.

How do I use reference token in identityserver4?

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.

What is API bearer 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.


1 Answers

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")]
like image 71
Richard Avatar answered Oct 11 '22 05:10

Richard