简体   繁体   中英

InvalidOperationException when signing in to IdentityServer4 via oidc-client

I'm having some problems getting my authentication flow working between a Vue.js + ASP.NET Core 2.1 web app with IdentityServer4, seems I'm missing something very basic but not sure what. I want to have the following:

  1. REST APIs ( http://localhost:7000 ) are secured via IdentityServer4 ( http://localhost:5000 )
  2. User opens up my asp.net core web app ( http://localhost:6666 ), clicks login
  3. JavaScript submits config and uses signinredirect to send browser to IdentityServer4 app
  4. User enters login details and submits
  5. Browser redirects per configuration to my asp.net core web app with successful login details
  6. User can now access REST APIs via my asp.net core web app

I can get from my vue+web app -> IdentityServer4 quickstart logon UI, and it presents the following login UI:

IdentityServer4 Quickstart UI

I am using the test user accounts "bob" and "alice", after putting in the user id and password for alice and trying to log in, I get the following error:

An unhandled exception occurred while processing the request.

InvalidOperationException: The authentication handler registered for scheme 'Bearer' is 'IdentityServerAuthenticationHandler' which cannot be used for SignInAsync. The registered sign-in schemes are: idsrv, idsrv.external.

Microsoft.AspNetCore.Authentication.AuthenticationService.SignInAsync(HttpContext context, string scheme, ClaimsPrincipal principal, AuthenticationProperties properties)

My Client configuration is:

new Client
    {
        ClientId = "js",
        ClientName = "JavaScript Client",
        AllowedGrantTypes = GrantTypes.Implicit,
        AllowAccessTokensViaBrowser = true,

        RedirectUris =           { "http://localhost:6666/static/account/callback.html" },
        PostLogoutRedirectUris = { "http://localhost:6666" },
        AllowedCorsOrigins =     { "http://localhost:6666" },

        // scopes that client has access to
        AllowedScopes =
        {
            IdentityServerConstants.StandardScopes.OpenId,
            IdentityServerConstants.StandardScopes.Profile,
            "api1"
        }
    }

Configuration for my javascript client is (TypeScript):

// Authentication init code
idConfig: Oidc.UserManagerSettings = {
    authority: "http://localhost:5000",
    client_id: "js",
    redirect_uri: "http://localhost:6666/static/account/callback.html",
    response_type: "id_token token",
    scope: "openid profile castlepoint",
    post_logout_redirect_uri: "http://localhost:6666",
} as Oidc.UserManagerSettings;

and my login javascript code is:

public login() {
    this.userManager.signinRedirect();
}

I get the feeling I am incorrectly combining a client-based login flow with an automated sign-on flow, but I'm not sure...

The logs from ID4 say the same as above basically:

System.InvalidOperationException: The authentication handler registered for scheme 'Bearer' is 'IdentityServerAuthenticationHandler' which cannot be used for SignInAsync. The registered sign-in schemes are: idsrv, idsrv.external.

My ID4 startup.cs has this entry:

public void ConfigureServices(IServiceCollection services)
    {

        // configure identity server with in-memory stores, keys, clients and scopes
        services.AddIdentityServer()
            .AddDeveloperSigningCredential()
            .AddInMemoryApiResources(Config.GetApiResources())
            .AddInMemoryIdentityResources(Config.GetIdentityResources())
            .AddInMemoryClients(Config.GetClients())
            .AddTestUsers(Config.GetUsers());

        services.AddMvcCore()
           .AddAuthorization()
           .AddJsonFormatters();

        services.AddAuthentication("Bearer")
            .AddIdentityServerAuthentication(options =>
            {
                options.Authority = "http://localhost:5000";
                options.RequireHttpsMetadata = false;

                options.ApiName = "api1";
            });

        services.AddCors(options =>
        {
            // this defines a CORS policy called "default"
            options.AddPolicy("default", policy =>
            {
                policy.WithOrigins("http://localhost:6666")
                    .AllowAnyHeader()
                    .AllowAnyMethod();
            });
        });

        services.AddMvc();

}

Sorry about the long code dump... can anyone point out the easy bit I haven't got right? I have got some wires crossed somewhere with the type of authentication I need and the configuration it requires... I think...

OK, I've figured it out finally.

The DI services.AddAuthentication("Bearer") call added the ASP.NET Authentication to Startup.cs in my IdentityServer4 web app, in order to implement "Bearer" access token validation. But this isn't the right spot for it - it should have been in my API web app instead, as this is what the API is meant to use to authenticate calls made to it.

The IdentityServer4 web app is meant to accept user id + password for authentication, but with the DI I had added it was also requiring a Bearer access token as part of the authentication. That basically messed up things, and why it was incompatible with the sign-in scheme. I had the right code, but in the wrong app!

Moving the AddAuthentication("Bearer") to my API web app resolved the whole issue.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM