IdentityServer4 给出堆栈溢出错误

Posted

技术标签:

【中文标题】IdentityServer4 给出堆栈溢出错误【英文标题】:IdentityServer4 gives stack overflow error 【发布时间】:2021-12-14 23:19:01 【问题描述】:

我有一个 SPA (Angular 9) 并使用一个身份站点(.NET Core 3.1 和 identity4)。两个站点都运行良好,但是如果用户长时间停止浏览并尝试再次导航,身份站点会给出 503 错误(堆栈溢出错误)。

这是我在 Angular 9 上的配置,angular-oauth2-oidc。

// app.component.ts
// ----------------------------

export const authConfig: AuthConfig = 
  issuer: environment.authority,
  redirectUri: environment.redirectUrl,
  clientId: environment.clientId,
  scope: "openid profile offline_access",
  disablePKCE: false,
  responseType: "code",
  requireHttps: false,
  logoutUrl: environment.authority + "/Account/Logout"


@Component(
  selector: 'app-root',
  templateUrl: './app.component.html'
)
export class AppComponent implements OnInit 
  title = 'app';
  public isAuthenticated: Observable<boolean>;
  public configs = null;

  constructor(
    private ouathService: OAuthService,
    private storage: SessionStorageService
  ) 
    this.ouathService.configure(authConfig);
    this.ouathService.tokenValidationHandler = new JwksValidationHandler();
  


// Authguard.js
// ----------------------------

export class AuthGuard implements CanActivate 
    constructor(..)  
    canActivate(..): boolean 
        if (this.oauthService.hasValidAccessToken()) 
            console.log("Token validado");
            let token = this.oauthService.getAccessToken();
            //...
            return true;
         else 
            console.log("Inicia flujo");
            this.oauthService.initImplicitFlow();
            this.oauthService.loadDiscoveryDocumentAndTryLogin();   
        
    


app.module.ts
----------------------------
@NgModule(
  declarations: [..],
  imports: [
    //..
    OAuthModule.forRoot(),
    RouterModule.forRoot([
       path: '', component: StartComponent ,
       path: 'logout', component: LoginComponent ,
       path: 'home', component: HomeComponent, canActivate: [AuthGuard, AppGuard] ,      
    ])
  ],
  providers: [
    LoaderService,
     provide: HTTP_INTERCEPTORS, useClass: TokenInterceptor, multi: true 
  ],
  bootstrap: [AppComponent]
)

这是我在 Identity 站点上的配置:.NET Core 3.1 和 identity4。

// Config
// ----------------------------
public IEnumerable<IdentityResource> GetIdentityResources() 
    return new List<IdentityResource> 
        new IdentityResources.OpenId(),
        new IdentityResources.Profile()
    ;


public IEnumerable<Client> GetClients() 
    var client = _conf["URL_fronted"];
    return new[] 
        new Client 
            ClientId = "..",
            ClientName = "..",
            AllowedGrantTypes = GrantTypes.Code,
            RequireClientSecret = false,
            RequirePkce = true,
            RedirectUris =  $"client" ,
            FrontChannelLogoutUri = $"client",
            PostLogoutRedirectUris =  $"client/logout" ,
            AllowOfflineAccess = true,
            AllowedScopes =  "openid","profile", "offline_access" ,                    
        
    ;


// Startup
// ----------------------------
services.AddIdentity<ApplicationUser, IdentityRole>()
  .AddEntityFrameworkStores<ApplicationDbContext>()
  .AddDefaultTokenProviders();

services.Configure<IISServerOptions>(iis =>

  iis.AuthenticationDisplayName = "Windows";
  iis.AutomaticAuthentication = true;
);

var confIdentity = new ConfigIdentity(Configuration);

var builder = services.AddIdentityServer(options =>

  options.Events.RaiseErrorEvents = true;
  options.Events.RaiseInformationEvents = true;
  options.Events.RaiseFailureEvents = true;
  options.Events.RaiseSuccessEvents = true;
)
  .AddInMemoryIdentityResources(confIdentity.GetIdentityResources())
  .AddInMemoryClients(confIdentity.GetClients())
  .AddProfileService<IdentityWithAdditionalClaimsProfileService>();
builder.AddDeveloperSigningCredential();
services.AddCors(options =>

  options.AddPolicy("CorsPolicy",
      builder => builder.AllowAnyOrigin()
      .AllowAnyMethod()
      .AllowAnyHeader());
);
// IdentityWithAdditionalClaimsProfileService
// -----------------------------------------------

public class IdentityWithAdditionalClaimsProfileService : IProfileService
    
        private readonly IUserClaimsPrincipalFactory<ApplicationUser> _claimsFactory;
        private readonly UserManager<ApplicationUser> _userManager;
        private ILogger<IdentityWithAdditionalClaimsProfileService> _logger;

        private ApplicationDbContext _ctx;
        public IdentityWithAdditionalClaimsProfileService(UserManager<ApplicationUser> userManager,
        IUserClaimsPrincipalFactory<ApplicationUser> claimsFactory,
        ILogger<IdentityWithAdditionalClaimsProfileService> logger,
        ApplicationDbContext context)
        
            _userManager = userManager;
            _claimsFactory = claimsFactory;
            _logger = logger;
            _ctx = context;
        

        public async Task GetProfileDataAsync(ProfileDataRequestContext context)
        
            var sub = context.Subject.GetSubjectId();            
            var user = _ctx.users.Where(..).FirstOrDefault();
            if (user == null)
            
                throw new Exception("No se encontro usuario para perfilar");
            

            var claims = new List<Claim>();
            claims.Add(new Claim(ClaimTypes.Name, user.Names));
            claims.Add(new Claim(ClaimTypes.Email, user.Email));

            if (user.RoleId != null)
            
                var rolGlobal = _ctx.roles.Where(..).FirstOrDefault();
                if (rolGlobal != null)
                
                    claims.Add(new Claim(ClaimTypes.Role, rolGlobal.AzureGroup));
                
            

            context.IssuedClaims = claims;

        

        public async Task IsActiveAsync(IsActiveContext context)
        
            context.IsActive = true;
        
    

这是日志:

20:41:12 Debug] IdentityServer4.Hosting.EndpointRouter
Request path /.well-known/openid-configuration/jwks matched to endpoint type Discovery

[20:41:12 Debug] IdentityServer4.Hosting.EndpointRouter
Endpoint enabled: Discovery, successfully created handler: IdentityServer4.Endpoints.DiscoveryKeyEndpoint

[20:41:12 Information] IdentityServer4.Hosting.IdentityServerMiddleware
Invoking IdentityServer endpoint: IdentityServer4.Endpoints.DiscoveryKeyEndpoint for /.well-known/openid-configuration/jwks

[20:41:12 Debug] IdentityServer4.Endpoints.DiscoveryKeyEndpoint
Start key discovery request

[21:31:23 Debug] IdentityServer4.Hosting.CorsPolicyProvider
CORS request made for path: /.well-known/openid-configuration from origin: http://localhost:4200

[21:31:23 Debug] IdentityServer4.Services.InMemoryCorsPolicyService
Client list checked and origin: http://localhost:4200 is not allowed

[21:31:23 Warning] IdentityServer4.Hosting.CorsPolicyProvider
CorsPolicyService did not allow origin: http://localhost:4200

[21:31:23 Debug] IdentityServer4.Hosting.EndpointRouter
Request path /.well-known/openid-configuration matched to endpoint type Discovery

[21:31:23 Debug] IdentityServer4.Hosting.EndpointRouter
Endpoint enabled: Discovery, successfully created handler: IdentityServer4.Endpoints.DiscoveryEndpoint

[21:31:23 Information] IdentityServer4.Hosting.IdentityServerMiddleware
Invoking IdentityServer endpoint: IdentityServer4.Endpoints.DiscoveryEndpoint for /.well-known/openid-configuration

[21:31:23 Debug] IdentityServer4.Endpoints.DiscoveryEndpoint
Start discovery request

[21:31:23 Debug] IdentityServer4.Hosting.CorsPolicyProvider
CORS request made for path: /.well-known/openid-configuration/jwks from origin: http://localhost:4200

[21:31:23 Debug] IdentityServer4.Services.InMemoryCorsPolicyService
Client list checked and origin: http://localhost:4200 is not allowed

[21:31:23 Warning] IdentityServer4.Hosting.CorsPolicyProvider
CorsPolicyService did not allow origin: http://localhost:4200

[21:31:23 Debug] IdentityServer4.Hosting.EndpointRouter
Request path /.well-known/openid-configuration/jwks matched to endpoint type Discovery

[21:31:23 Debug] IdentityServer4.Hosting.EndpointRouter
Endpoint enabled: Discovery, successfully created handler: IdentityServer4.Endpoints.DiscoveryKeyEndpoint

[21:31:23 Information] IdentityServer4.Hosting.IdentityServerMiddleware
Invoking IdentityServer endpoint: IdentityServer4.Endpoints.DiscoveryKeyEndpoint for /.well-known/openid-configuration/jwks

[21:31:23 Debug] IdentityServer4.Endpoints.DiscoveryKeyEndpoint
Start key discovery request

Stack overflow.

【问题讨论】:

您在身份验证服务或警卫的某处进行了循环调用 能否在问题中包含IdentityWithAdditionalClaimsProfileService类的源代码? @AndrewSilver 我包含了代码 IdentityWithAdditionalClaimsProfileService。 SPA 站点,验证令牌,但如何过期,尝试更新并重定向到身份站点以进行新登录,但站点出现故障。 A 503 表示“服务不可用”,通常是暂时的。原因很可能是堆栈溢出异常,无论如何这将是您的 csharp 代码中的错误,而不是您的前端。另外,据我所知,罪魁祸首不在您在此处发布的代码中。我认为我们无法仅使用您发布的内容来重现您的问题。 - 尝试创建一个最小的示例设置并在此处分享所有详细信息,如果可以的话?祝你好运! 【参考方案1】:

我的问题是将 Identityserver 设置为 InMemory:

Startup.cs

var builder = services.AddIdentityServer(options =>

 //...
)
  .AddInMemoryIdentityResources(confIdentity.GetIdentityResources())
  .AddInMemoryClients(confIdentity.GetClients())

当用户长时间停止浏览时,此设置不起作用。一段时间后,身份站点丢失了客户端的令牌,当试图找到它时,它给出了一个 *** 错误

有两种解决方案:

1.- 将配置更改为use entity framework

services.AddIdentityServer()
        // this adds the operational data from DB (codes, tokens, consents)
        .AddOperationalStore(options =>
        
            options.ConfigureDbContext = builder =>
                builder.UseSqlServer(connectionString,
                    sql => sql.MigrationsAssembly(migrationsAssembly));

            // this enables automatic token cleanup. this is optional.
            options.EnableTokenCleanup = true;
            options.TokenCleanupInterval = 3600; // interval in seconds (default is 3600)
        );

2.- 客户端向refresh token发送请求

app.component.ts

this.ouathService.refreshToken();

【讨论】:

以上是关于IdentityServer4 给出堆栈溢出错误的主要内容,如果未能解决你的问题,请参考以下文章

有人可以指出代码“满足给定总和条件的子序列数”的错误,这会导致堆栈溢出错误

winsock 选择函数中的堆栈溢出异常 (0xC00000FD)

分段错误和堆栈溢出有啥区别?

js堆栈溢出错误

尝试在java中使用正则表达式时堆栈溢出

什么是堆栈溢出和缓冲区溢出错误? [复制]