简体   繁体   中英

System.InvalidOperationException: idp claim is missing Identity server 4.1.1 Asp.net core 3

Here is the setup for the Identity server configuration

var builder = services.AddIdentityServer(options =>
                {
                    options.Events.RaiseErrorEvents = true;
                    options.Events.RaiseInformationEvents = true;
                    options.Events.RaiseFailureEvents = true;
                    options.Events.RaiseSuccessEvents = true;
                    options.EmitStaticAudienceClaim = true;
                })
                .AddProfileService<ProfileService>()
                // this adds the config data from DB (clients, resources, CORS)
                .AddConfigurationStore(options =>
                {
                    options.ConfigureDbContext = builder =>
                        builder.UseSqlServer(configuration.GetConnectionString("DefaultConnection"),
                            sql => sql.MigrationsAssembly(migrationsAssembly));
                })
                // this adds the operational data from DB (codes, tokens, consents)
                .AddOperationalStore(options =>
                {
                    options.ConfigureDbContext = builder =>
                        builder.UseSqlServer(configuration.GetConnectionString("DefaultConnection"),
                            sql => sql.MigrationsAssembly(migrationsAssembly));
                    // this enables automatic token cleanup. this is optional.
                    options.EnableTokenCleanup = true;
                });
            services.AddDbContext<ApplicationDbContext>(options =>
                options.UseSqlServer(
                    configuration.GetConnectionString("DefaultConnection"),
                    b => b.MigrationsAssembly("Falcon-Identity")));
            services.AddIdentity<ApplicationUser, IdentityRole>(
                    options =>
                    {
                        options.SignIn.RequireConfirmedAccount = true;
                        options.Password.RequireDigit = false;
                        options.Password.RequiredLength = 8;
                        options.Password.RequireLowercase = true;
                        options.Password.RequireUppercase = false;
                    })
                .AddEntityFrameworkStores<ApplicationDbContext>();

            // not recommended for production - you need to store your key material somewhere secure
            builder.AddDeveloperSigningCredential();
            builder.AddInMemoryApiScopes(Config.ApiScopes);

            // Register the IConfiguration instance which options binds against.
            services.Configure<IdentityServerViewModel>(configuration.GetSection("IdentityServer"));

app configuration

    app.UseRouting();
    app.UseIdentityServer();
    app.UseAuthorization();

Client configuration

public static IEnumerable<Client> Clients(IConfiguration configuration) =>
            new Client[]
            {
                new Client
                {
                    ClientId = configuration.GetSection("IdentityServer:Client:ClientId").Value,
                    ClientName = configuration.GetSection("IdentityServer:Client:ClientName").Value,
                    //AllowedCorsOrigins = new List<string> { "http://localhost:4200","https://localhost:4200" },
                    AllowedGrantTypes = GrantTypes.Code,
                    AllowAccessTokensViaBrowser = bool.Parse(configuration.GetSection("IdentityServer:Client:AllowAccessTokensViaBrowser").Value),
                    AccessTokenLifetime=86400,
                    RequireConsent = bool.Parse(configuration.GetSection("IdentityServer:Client:RequireConsent").Value),
                    UpdateAccessTokenClaimsOnRefresh = bool.Parse(configuration.GetSection("IdentityServer:Client:UpdateAccessTokenClaimsOnRefresh").Value),
                    RedirectUris = LocalRedirectUris(configuration),
                    PostLogoutRedirectUris = LocalRedirectUris(configuration),
                    AllowedScopes = AllowedScopes(),
                    AllowOfflineAccess = bool.Parse(configuration.GetSection("IdentityServer:Client:AllowOfflineAccess").Value),
                    AccessTokenType = AccessTokenType.Jwt,
                    RequireClientSecret = bool.Parse(configuration.GetSection("IdentityServer:Client:RequireClientSecret").Value),
                    RequirePkce = bool.Parse(configuration.GetSection("IdentityServer:Client:RequirePkce").Value),
                    //AllowRememberConsent = true
                }
            };
        
        private static ICollection<string> AllowedScopes()
        {
            return new List<string>
            {
                IdentityServerConstants.StandardScopes.OpenId,
                IdentityServerConstants.StandardScopes.Profile,
                IdentityServerConstants.StandardScopes.Email,
                AuthorizePolicy.apiScope
            };
        }
        
        // API scopes represent values that describe scope of access and can be requested by the scope parameter (OAuth)
        public static readonly IEnumerable<ApiScope> ApiScopes =
            new[]
            {
                new ApiScope(IdentityServerConstants.StandardScopes.OpenId),
                new ApiScope(IdentityServerConstants.StandardScopes.Profile),
                new ApiScope(IdentityServerConstants.StandardScopes.Email),
                new ApiScope(AuthorizePolicy.apiScope),
            };

Account controller

 if (ModelState.IsValid)
            {
                // validate username/password against in-memory store
                var result = await _signInManager.PasswordSignInAsync(model.Username, model.Password,
                    model.RememberLogin, lockoutOnFailure: true);
                // validate username/password against in-memory store
                if (result.Succeeded)
                {
                    var user = await _userManager.FindByNameAsync(model.Username);
                    await _events.RaiseAsync(new UserLoginSuccessEvent(user.UserName, user.Id, user.Email, clientId: context?.Client.ClientId));

                    // only set explicit expiration here if user chooses "remember me". 
                    // otherwise we rely upon expiration configured in cookie middleware.
                    AuthenticationProperties props = null;
                    if (AccountOptions.AllowRememberLogin && model.RememberLogin)
                    {
                        props = new AuthenticationProperties
                        {
                            IsPersistent = true,
                            ExpiresUtc = DateTimeOffset.UtcNow.Add(AccountOptions.RememberMeLoginDuration)
                        };
                    };
    
                    // Add the additional claim to the Identity and token
                    var principal = await _claimsFactory.CreateAsync(user);
                    var claims = principal.Claims.ToList();
                    
                    // issue authentication cookie with subject ID and username
                    var isuser = new IdentityServerUser(user.Id)
                    {
                        DisplayName = user.UserName,
                        AdditionalClaims = claims    
                    };

                    await HttpContext.SignInAsync(isuser, props);

                    if (context != null)
                    {
                        if (context.IsNativeClient())
                        {
                            // The client is native, so this change in how to
                            // return the response is for better UX for the end user.
                            return this.LoadingPage("Redirect", model.ReturnUrl);
                        }

                        // we can trust model.ReturnUrl since GetAuthorizationContextAsync returned non-null
                        return Redirect(model.ReturnUrl);
                    }

                    // request for a local page
                    if (Url.IsLocalUrl(model.ReturnUrl))
                    {
                        return Redirect(model.ReturnUrl);
                    }
                    else if (string.IsNullOrEmpty(model.ReturnUrl))
                    {
                        return Redirect("~/");
                    }
                    else
                    {
                        // user might have clicked on a malicious link - should be logged
                        throw new Exception("invalid return URL");
                    }
                }

                await _events.RaiseAsync(new UserLoginFailureEvent(model.Username, "invalid credentials", clientId:context?.Client.ClientId));
                ModelState.AddModelError(string.Empty, AccountOptions.InvalidCredentialsErrorMessage);
            }

Error

System.InvalidOperationException: idp claim is missing
   at IdentityServer4.Extensions.PrincipalExtensions.GetIdentityProvider(IIdentity identity)
   at IdentityServer4.Extensions.PrincipalExtensions.GetIdentityProvider(IPrincipal principal)
   at IdentityServer4.ResponseHandling.AuthorizeInteractionResponseGenerator.ProcessLoginAsync(ValidatedAuthorizeRequest request)
   at IdentityServer4.ResponseHandling.AuthorizeInteractionResponseGenerator.ProcessInteractionAsync(ValidatedAuthorizeRequest request, ConsentResponse consent)
   at IdentityServer4.Endpoints.AuthorizeEndpointBase.ProcessAuthorizeRequestAsync(NameValueCollection parameters, ClaimsPrincipal user, ConsentResponse consent)
   at IdentityServer4.Endpoints.AuthorizeEndpoint.ProcessAsync(HttpContext context)
   at IdentityServer4.Hosting.IdentityServerMiddleware.Invoke(HttpContext context, IEndpointRouter router, IUserSession session, IEventService events, IBackChannelLogoutService backChannelLogoutService)
2021-01-07 07:14:50.419 +00:00 [ERR] An unhandled exception has occurred while executing the request.
System.InvalidOperationException: idp claim is missing
   at IdentityServer4.Extensions.PrincipalExtensions.GetIdentityProvider(IIdentity identity)
   at IdentityServer4.Extensions.PrincipalExtensions.GetIdentityProvider(IPrincipal principal)
   at IdentityServer4.ResponseHandling.AuthorizeInteractionResponseGenerator.ProcessLoginAsync(ValidatedAuthorizeRequest request)
   at IdentityServer4.ResponseHandling.AuthorizeInteractionResponseGenerator.ProcessInteractionAsync(ValidatedAuthorizeRequest request, ConsentResponse consent)
   at IdentityServer4.Endpoints.AuthorizeEndpointBase.ProcessAuthorizeRequestAsync(NameValueCollection parameters, ClaimsPrincipal user, ConsentResponse consent)
   at IdentityServer4.Endpoints.AuthorizeEndpoint.ProcessAsync(HttpContext context)
   at IdentityServer4.Hosting.IdentityServerMiddleware.Invoke(HttpContext context, IEndpointRouter router, IUserSession session, IEventService events, IBackChannelLogoutService backChannelLogoutService)
   at IdentityServer4.Hosting.IdentityServerMiddleware.Invoke(HttpContext context, IEndpointRouter router, IUserSession session, IEventService events, IBackChannelLogoutService backChannelLogoutService)
   at IdentityServer4.Hosting.MutualTlsEndpointMiddleware.Invoke(HttpContext context, IAuthenticationSchemeProvider schemes)
   at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
   at IdentityServer4.Hosting.BaseUrlMiddleware.Invoke(HttpContext context)
   at Swashbuckle.AspNetCore.SwaggerUI.SwaggerUIMiddleware.Invoke(HttpContext httpContext)
   at Swashbuckle.AspNetCore.Swagger.SwaggerMiddleware.Invoke(HttpContext httpContext, ISwaggerProvider swaggerProvider)
   at Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware.<Invoke>g__Awaited|6_0(ExceptionHandlerMiddleware middleware, HttpContext context, Task task)
2021-01-07 08:36:56.305 +00:00 [INF] Starting IdentityServer4 version 4.1.1+cebd52f5bc61bdefc262fd20739d4d087c6f961f
2021-01-07 08:36:56.410 +00:00 [INF] Using the default authentication scheme Identity.Application for IdentityServer
2021-01-07 08:36:56.411 +00:00 [DBG] Using Identity.Application as default ASP.NET Core scheme for authentication
2021-01-07 08:36:56.412 +00:00 [DBG] Using Identity.External as default ASP.NET Core scheme for sign-in
2021-01-07 08:36:56.412 +00:00 [DBG] Using Identity.External as default ASP.NET Core scheme for sign-out
2021-01-07 08:36:56.413 +00:00 [DBG] Using Identity.Application as default ASP.NET Core scheme for challenge
2021-01-07 08:36:56.413 +00:00 [DBG] Using Identity.Application as default ASP.NET Core scheme for forbid
2021-01-07 08:36:56.865 +00:00 [DBG] Login Url: /Account/Login
2021-01-07 08:36:56.872 +00:00 [DBG] Login Return Url Parameter: ReturnUrl
2021-01-07 08:36:56.873 +00:00 [DBG] Logout Url: /Account/Logout
2021-01-07 08:36:56.873 +00:00 [DBG] ConsentUrl Url: /consent
2021-01-07 08:36:56.874 +00:00 [DBG] Consent Return Url Parameter: returnUrl
2021-01-07 08:36:56.875 +00:00 [DBG] Error Url: /home/error
2021-01-07 08:36:56.875 +00:00 [DBG] Error Id Parameter: errorId

Tried the solution from these references, but not working for me.

https://github.com/IdentityServer/IdentityServer4/issues/1792 https://github.com/IdentityServer/IdentityServer4/issues/1878

JWT Token

{
  "nbf": 1610250740,
  "exp": 1610250790,
  "iss": "https://falconidentityserver.azurewebsites.net",
  "aud": "https://falconidentityserver.azurewebsites.net/resources",
  "client_id": "Falcon_Identity_Server",
  "sub": "e413120a-2aa3-43e9-a450-eee670cca321",
  "auth_time": 1610250389,
  "idp": "local",
  "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier": "e413120a-2aa3-43e9-a450-eee670cca321",
  "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name": "admin@local.com",
  "AspNet.Identity.SecurityStamp": "d5fe7709-9d7d-4a08-a246-8e1ae0536bde",
  "IdentityServer": [
    "Read",
    "Create",
    "Update",
    "Delete"
  ],
  "jti": "CA316689F3B2F0F702CF10E63B6F4EA9",
  "sid": "23AF4158F934C003DD6552614E26E600",
  "iat": 1610250740,
  "scope": [
    "openid",
    "profile",
    "email"
  ],
  "amr": [
    "pwd"
  ]
}

Have you tried configuring the SecurityStampValidator to retain the idp claim, following the instructions linked here?

https://github.com/IdentityServer/IdentityServer4/issues/1878

Apparently, ASP.NET Identity drops the idp claims from the cookies after the browser has been idle for some time. To prevent that add the following to the ConfigureServices method in Startup.cs of the ASP.NET Core project.

builder.Services.Configure<SecurityStampValidatorOptions>(opts =>
{
    opts.OnRefreshingPrincipal = SecurityStampValidatorCallback.UpdatePrincipal;
});

(Requires IdentityServer4.AspNetIdentity package)

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