I have implemented the suggested modifications (like ensuring the openid scope is present), but the issue persists. The login loop continues, and tokens are deleted from local storage immediately after the redirect.
Provide us with the following info: ABP Framework version: [Please specify your ABP version, e.g., v8.1.0]
UI Type: Angular
Database Provider: [Please specify your DB provider, e.g., EF Core / SQL Server]
Tiered (Y/N): Yes
Authentication: OpenIddict
📜 Exception message and full stack trace: There is no explicit exception thrown. The error is observed in the browser: after a successful login and redirect from the auth server, the local storage tokens (access_token, id_token, etc.) are set for a fraction of a second and then immediately cleared. The browser's developer console does not show any errors during this process.
🔁 Steps to reproduce the issue: Deploy the application to a test server with HTTPS enabled for both the Angular client and the backend hosts.
Angular client is hosted at: https://dev-qitaf.yk-bank.com:9982
Auth server is hosted at: https://auth-qitaf.yk-bank.com:9981
Navigate to the Angular frontend URL.
Click the "Sign In" button.
Enter valid credentials on the Auth Server's login page.
After successful authentication, the user is redirected back to the Angular app.
Result: The app fails to recognize the user as authenticated and remains on the "Sign In" page, creating an infinite redirect loop if "Sign In" is clicked again.
📝 Detailed Problem Description: I am facing an OIDC login issue where the currentUser is not authenticated after a successful login. This problem only occurs in our deployed test environment and works perfectly on localhost.
The expected behavior is that after logging in, I should be redirected to the main application page (e.g., dashboard) and be fully authenticated.
The actual behavior is that the Angular app does not recognize the login and gets stuck. The authentication-related keys in local storage are deleted almost instantly after the redirect from the auth server, preventing the session from being established.
💻 Relevant Code Snippets: ⚠️ IMPORTANT: I have removed sensitive information.
- Angular Configuration (environment.ts and other files) <details> <summary>Click to expand Angular Code</summary>
environment.ts
TypeScript
import { Environment } from '@abp/ng.core';
const baseUrl = 'https://qitaf-dev.yk-bank.com:9982';
const oAuthConfig = { issuer: 'https://auth-qitaf-dev.yk-bank.com:9981/', redirectUri: baseUrl, clientId: 'QitafPlatform_App', responseType: 'code', scope: 'offline_access QitafPlatform', // Note: Also tested with 'openid profile email offline_access QitafPlatform' with the same result. requireHttps: true, strictDiscoveryDocumentValidation: false };
export const environment = { production: false, application: { baseUrl, name: 'QitafPlatform', }, oAuthConfig, apis: { default: { url: 'https://qitaf-dev.yk-bank.com:9982', rootNamespace: 'QitafPlatform', }, AbpAccountPublic: { url: oAuthConfig.issuer, rootNamespace: 'AbpAccountPublic', }, }, } as Environment; app.module.ts
TypeScript
import { CoreModule, provideAbpCore, withOptions } from '@abp/ng.core'; import { NgModule } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; import { provideAbpOAuth } from '@abp/ng.oauth'; // ... other imports import { environment } from '../environments/environment'; import { AppRoutingModule } from './app-routing.module'; import { AppComponent } from './app.component'; // ... other imports
@NgModule({ declarations: [AppComponent], imports: [ BrowserModule, BrowserAnimationsModule, AppRoutingModule, CoreModule.forRoot(), ThemeSharedModule.forRoot(), HomeModule, ThemeLeptonXModule.forRoot(), SideMenuLayoutModule.forRoot(), AccountLayoutModule.forRoot(), GdprConfigModule, ], providers: [ APP_ROUTE_PROVIDER, provideAbpCore( withOptions({ environment, registerLocaleFn: registerLocale(), }), ), provideAbpOAuth(), // ... other providers ], bootstrap: [AppComponent], }) export class AppModule {} app.component.ts
TypeScript
import { Component } from '@angular/core';
@Component({
standalone: false,
selector: 'app-root',
template: <abp-loader-bar></abp-loader-bar> <abp-dynamic-layout></abp-dynamic-layout> <abp-gdpr-cookie-consent></abp-gdpr-cookie-consent>
,
})
export class AppComponent {}
app-routing.module.ts
TypeScript
import { authGuard, permissionGuard } from '@abp/ng.core'; import { NgModule } from '@angular/core'; import { RouterModule, Routes } from '@angular/router';
const routes: Routes = [ { path: '', pathMatch: 'full', loadChildren: () => import('./home/home.module').then(m => m.HomeModule), }, { path: 'dashboard', loadChildren: () => import('./dashboard/dashboard.module').then(m => m.DashboardModule), canActivate: [authGuard, permissionGuard], }, // ... other routes ];
@NgModule({ imports: [RouterModule.forRoot(routes, {})], exports: [RouterModule], }) export class AppRoutingModule {} </details>
- Auth Server Module (QitafPlatformAuthServerModule.cs) <details> <summary>Click to expand Auth Server Code</summary>
C#
namespace QitafPlatform;
[DependsOn(/.../)] public class QitafPlatformAuthServerModule : AbpModule { public override void PreConfigureServices(ServiceConfigurationContext context) { var hostingEnvironment = context.Services.GetHostingEnvironment(); var configuration = context.Services.GetConfiguration();
PreConfigure<OpenIddictBuilder>(builder =>
{
builder.AddValidation(options =>
{
options.AddAudiences("QitafPlatform");
options.UseLocalServer();
options.UseAspNetCore();
});
builder.Services.ConfigureApplicationCookie(options =>
{
options.Cookie.SameSite = SameSiteMode.None;
options.Cookie.SecurePolicy = CookieSecurePolicy.Always;
});
});
if (!hostingEnvironment.IsDevelopment())
{
PreConfigure<AbpOpenIddictAspNetCoreOptions>(options =>
{
options.AddDevelopmentEncryptionAndSigningCertificate = false;
});
PreConfigure<OpenIddictServerBuilder>(serverBuilder =>
{
serverBuilder.AddProductionEncryptionAndSigningCertificate("openiddict.pfx", configuration["AuthServer:CertificatePassPhrase"]!);
serverBuilder.SetIssuer(new Uri(configuration["AuthServer:Authority"]!.EnsureEndsWith('/')));
});
}
}
public override void ConfigureServices(ServiceConfigurationContext context)
{
var configuration = context.Services.GetConfiguration();
// ...
context.Services.AddCors(options =>
{
options.AddDefaultPolicy(builder =>
{
builder
.WithOrigins(
configuration["App:CorsOrigins"]?
.Split(",", StringSplitOptions.RemoveEmptyEntries)
.Select(o => o.Trim().RemovePostFix("/"))
.ToArray() ?? Array.Empty<string>()
)
.WithAbpExposedHeaders()
.SetIsOriginAllowedToAllowWildcardSubdomains()
.AllowAnyHeader()
.AllowAnyMethod()
.AllowCredentials();
});
});
// ... Authentication, Swagger, etc.
}
public override void OnApplicationInitialization(ApplicationInitializationContext context)
{
var app = context.GetApplicationBuilder();
var env = context.GetEnvironment();
var forwardingOptions = new ForwardedHeadersOptions()
{
ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto
};
forwardingOptions.KnownNetworks.Clear();
forwardingOptions.KnownProxies.Clear();
app.UseForwardedHeaders(forwardingOptions);
// ...
app.UseCors();
app.UseAuthentication();
app.UseAbpOpenIddictValidation();
// ...
}
} </details>
- API Host Module (QitafPlatformHttpApiHostModule.cs) <details> <summary>Click to expand API Host Code</summary>
C#
namespace QitafPlatform;
[DependsOn(/.../)] public class QitafPlatformHttpApiHostModule : AbpModule { public override void ConfigureServices(ServiceConfigurationContext context) { var configuration = context.Services.GetConfiguration();
context.Services.ConfigureApplicationCookie(options =>
{
options.Cookie.SameSite = SameSiteMode.None;
options.Cookie.SecurePolicy = CookieSecurePolicy.Always;
});
ConfigureAuthentication(context, configuration);
ConfigureCors(context, configuration);
// ...
}
private void ConfigureAuthentication(ServiceConfigurationContext context, IConfiguration configuration)
{
context.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddAbpJwtBearer(options =>
{
options.Authority = configuration["AuthServer:Authority"]!.Trim().EnsureEndsWith('/');
options.RequireHttpsMetadata = configuration.GetValue<bool>("AuthServer:RequireHttpsMetadata");
options.Audience = "QitafPlatform";
// In our deployed environment, we use a JWT Key for validation
var jwtKey = configuration["AuthServer:JwtKey"];
if (!string.IsNullOrEmpty(jwtKey))
{
var modulus = Base64UrlDecode(jwtKey);
var exponent = Base64UrlDecode("AQAB");
var rsaParameters = new RSAParameters { Modulus = modulus, Exponent = exponent };
var rsa = new RSACryptoServiceProvider();
rsa.ImportParameters(rsaParameters);
var signingKey = new RsaSecurityKey(rsa);
options.TokenValidationParameters.IssuerSigningKey = signingKey;
options.TokenValidationParameters.ValidateIssuerSigningKey = true;
options.TokenValidationParameters.ValidIssuers = new[]
{
configuration["AuthServer:MetaAddress"]?.Trim().EnsureEndsWith('/'),
configuration["AuthServer:Authority"]?.Trim().EnsureEndsWith('/')
};
}
});
}
// ...
public override void OnApplicationInitialization(ApplicationInitializationContext context)
{
var app = context.GetApplicationBuilder();
var forwardingOptions = new ForwardedHeadersOptions()
{
ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto
};
forwardingOptions.KnownNetworks.Clear();
forwardingOptions.KnownProxies.Clear();
app.UseForwardedHeaders(forwardingOptions);
// ...
app.UseCors();
app.UseAuthentication();
// ...
}
} </details>
- appsettings.json (Relevant Sections) JSON
// [ Please provide the relevant sections from your deployed appsettings.json for both AuthServer and HttpApiHost. ] // Example of what is needed: { "App": { "SelfUrl": "https://auth-qitaf.yk-bank.com:9981", // For AuthServer "CorsOrigins": "https://dev-qitaf.yk-bank.com:9982", "AngularUrl": "https://dev-qitaf.yk-bank.com:9982" }, "AuthServer": { "Authority": "https://auth-qitaf.yk-bank.com:9981", "RequireHttpsMetadata": "true" } }
1 Answer(s)
-
0
hi
Please share full
logs.txt
files of AuthServer and API website.Remember to set the log level to Debug
https://abp.io/support/questions/8622/How-to-enable-Debug-logs-for-troubleshoot-problems
liming.ma@volosoft.com
Thanks