#angular #asp.net-core #identityserver4 #angular-oauth2-oidc
#angular #asp.net-ядро #identityserver4 #angular-oauth2-oidc
Вопрос:
У меня есть 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]
})
Это моя конфигурация на сайте идентификации: .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.
Комментарии:
1. У вас есть циклический вызов где-то в службе аутентификации или охране
2. Не могли бы вы также включить исходный код
IdentityWithAdditionalClaimsProfileService
класса в вопрос?3. @AndrewSilver Я включил код IdentityWithAdditionalClaimsProfileService. Сайт SPA, действительный токен, но срок его действия истек, попробуйте обновить и перенаправить на сайт идентификации для нового входа в систему, но сайт отключается.
4. 503 указывает на «служба недоступна», часто временно. Причиной вполне может быть исключение переполнения стека, в любом случае это будет ошибка в вашем коде csharp , а не на вашей интерфейсной стороне. Кроме того, насколько я могу судить, виновник кроется не в коде, который вы разместили здесь. Я не думаю, что мы сможем воспроизвести вашу проблему только с помощью того, что вы опубликовали. — Попробуйте создать минимальный образец настройки и поделиться всеми деталями здесь, если сможете? Удачи!
Ответ №1:
Моя проблема заключалась в установке Identityserver как InMemory:
Startup.cs
var builder = services.AddIdentityServer(options =>
{
//...
})
.AddInMemoryIdentityResources(confIdentity.GetIdentityResources())
.AddInMemoryClients(confIdentity.GetClients())
Этот параметр не работал, когда пользователь надолго прекращал просмотр. Через некоторое время сайт идентификации потерял токен клиента, и при попытке его найти он выдал ошибку stackoverflow
Есть два решения:
1.- Измените конфигурации для использования 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.- Клиент отправляет запрос на обновление токена
app.component.ts
this.ouathService.refreshToken();