Open Closed

Authenticatoni after Login Fails in Deployed Environment But Works on Localhost #9871


User avatar
0
KamalHassan created

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.

  1. 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>

  1. 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&lt;OpenIddictBuilder&gt;(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&lt;AbpOpenIddictAspNetCoreOptions&gt;(options =>
        {
            options.AddDevelopmentEncryptionAndSigningCertificate = false;
        });
        PreConfigure&lt;OpenIddictServerBuilder&gt;(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&lt;string&gt;()
                )
                .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>

  1. 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&lt;bool&gt;("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>

  1. 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)
  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    hi

    Please share full logs.txtfiles 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

Learn More, Pay Less
33% OFF
All Trainings!
Get Your Deal
Mastering ABP Framework Book
The Official Guide
Mastering
ABP Framework
Learn More
Mastering ABP Framework Book
Made with ❤️ on ABP v10.0.0-preview. Updated on September 10, 2025, 06:30