Open Closed

"Error retrieving discovery document: Endpoint does not use HTTPS: http://authserver.mydomain.dev/connect/authorize", #9849


User avatar
0
rogercprops created
  • Template: microservice
  • Created ABP Studio Version: 1.0.2
  • Current ABP Studio Version: 1.2.1
  • Multi-Tenancy: Yes
  • UI Framework: mvc
  • Theme: leptonx
  • Theme Style: system
  • Theme Menu Placement: side
  • Run Install Libs: Yes
  • Database Provider: ef
  • Database Management System: sqlserver
  • Mobile Framework: none
  • Public Website: No
  • Social Login: Yes
  • Include Tests: Yes
  • Dynamic Localization: Yes
  • Kubernetes Configuration: Yes
  • Grafana Dashboard: Yes
  • Use Local References: No
  • Optional Modules:
    • GDPR
    • TextTemplateManagement
    • AuditLogging
    • OpenIddictAdmin
  • Selected Languages: English, English (United Kingdom), Español
  • Default Language: English
  • Create Command: abp new CloverleafCMS -t microservice --ui-framework mvc --database-provider ef --database-management-system sqlserver --theme leptonx --skip-migrator --without-cms-kit --dont-run-bundling -no-file-management -no-language-management
  • Exception message and full stack trace:
[13:23:05 INF] Request starting HTTP/1.1 POST http://cloverleafcms-dev-apps-token/api/token - application/json 661
[13:23:05 INF] Executing endpoint 'TokenService.Tokens.TokenController.GetAccessToken (CloverleafCMS.TokenService)'
[13:23:05 INF] Route matched with {area = "token", action = "GetAccessToken", controller = "Token", page = ""}. Executing controller action with signature System.Threading.Tasks.Task`1[TokenService.Tokens.TokenResponseDto] GetAccessToken(TokenService.Tokens.TokenRequestDto) on controller TokenService.Tokens.TokenController (CloverleafCMS.TokenService).
Endpoint does not use HTTPS: http://authserver.mydomain.dev/connect/authorize
[13:23:06 WRN] ---------- RemoteServiceErrorInfo ----------
{
  "code": null,
  "message": "Error retrieving discovery document: Endpoint does not use HTTPS: http://authserver.mydomain.dev/connect/authorize",
  "details": null,
  "data": {},
  "validationErrors": null
}
[13:23:06 WRN] Error retrieving discovery document: Endpoint does not use HTTPS: http://authserver.mydomain.dev/connect/authorize
Volo.Abp.UserFriendlyException: Error retrieving discovery document: Endpoint does not use HTTPS: http://authserver.mydomain.dev/connect/authorize
   at CloverleafCMS.TokenService.TokenService.TokenAppService.GetAccessToken(String Tenant, String clientId, String clientSecret, String userName, String password, String[] scopes) in D:\CodeRepositories\CloverleafCMS-Microservices-Abp\services\token\CloverleafCMS.TokenService\Tokens\TokenAppService.cs:line 39
   at Castle.DynamicProxy.AsyncInterceptorBase.ProceedAsynchronous[TResult](IInvocation invocation, IInvocationProceedInfo proceedInfo)
   at Volo.Abp.Castle.DynamicProxy.CastleAbpMethodInvocationAdapterWithReturnValue`1.ProceedAsync()
   at Volo.Abp.GlobalFeatures.GlobalFeatureInterceptor.InterceptAsync(IAbpMethodInvocation invocation)
   at Volo.Abp.Castle.DynamicProxy.CastleAsyncAbpInterceptorAdapter`1.InterceptAsync[TResult](IInvocation invocation, IInvocationProceedInfo proceedInfo, Func`3 proceed)
   at Castle.DynamicProxy.AsyncInterceptorBase.ProceedAsynchronous[TResult](IInvocation invocation, IInvocationProceedInfo proceedInfo)
   at Volo.Abp.Castle.DynamicProxy.CastleAbpMethodInvocationAdapterWithReturnValue`1.ProceedAsync()
   at Volo.Abp.Validation.ValidationInterceptor.InterceptAsync(IAbpMethodInvocation invocation)
   at Volo.Abp.Castle.DynamicProxy.CastleAsyncAbpInterceptorAdapter`1.InterceptAsync[TResult](IInvocation invocation, IInvocationProceedInfo proceedInfo, Func`3 proceed)
   at Castle.DynamicProxy.AsyncInterceptorBase.ProceedAsynchronous[TResult](IInvocation invocation, IInvocationProceedInfo proceedInfo)
   at Volo.Abp.Castle.DynamicProxy.CastleAbpMethodInvocationAdapterWithReturnValue`1.ProceedAsync()
   at Volo.Abp.Auditing.AuditingInterceptor.ProceedByLoggingAsync(IAbpMethodInvocation invocation, AbpAuditingOptions options, IAuditingHelper auditingHelper, IAuditLogScope auditLogScope)
   at Volo.Abp.Auditing.AuditingInterceptor.InterceptAsync(IAbpMethodInvocation invocation)
   at Volo.Abp.Castle.DynamicProxy.CastleAsyncAbpInterceptorAdapter`1.InterceptAsync[TResult](IInvocation invocation, IInvocationProceedInfo proceedInfo, Func`3 proceed)
   at Castle.DynamicProxy.AsyncInterceptorBase.ProceedAsynchronous[TResult](IInvocation invocation, IInvocationProceedInfo proceedInfo)
   at Volo.Abp.Castle.DynamicProxy.CastleAbpMethodInvocationAdapterWithReturnValue`1.ProceedAsync()
   at Volo.Abp.Uow.UnitOfWorkInterceptor.InterceptAsync(IAbpMethodInvocation invocation)
   at Volo.Abp.Castle.DynamicProxy.CastleAsyncAbpInterceptorAdapter`1.InterceptAsync[TResult](IInvocation invocation, IInvocationProceedInfo proceedInfo, Func`3 proceed)
   at TokenService.Tokens.TokenController.GetAccessToken(TokenRequestDto input) in D:\CodeRepositories\CloverleafCMS-Microservices-Abp\services\token\CloverleafCMS.TokenService\Controllers\TokenController.cs:line 25
   at lambda_method2378(Closure, Object)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor.AwaitableObjectResultExecutor.Execute(ActionContext actionContext, IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeActionMethodAsync>g__Awaited|12_0(ControllerActionInvoker invoker, ValueTask`1 actionResultValueTask)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeNextActionFilterAsync>g__Awaited|10_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Rethrow(ActionExecutedContextSealed context)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeInnerFilterAsync>g__Awaited|13_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextExceptionFilterAsync>g__Awaited|26_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
[13:23:06 INF] Executing ObjectResult, writing value of type 'Volo.Abp.Http.RemoteServiceErrorResponse'.
[13:23:06 INF] Executed action TokenService.Tokens.TokenController.GetAccessToken (CloverleafCMS.TokenService) in 984.4926ms
[13:23:06 INF] Executed endpoint 'TokenService.Tokens.TokenController.GetAccessToken (CloverleafCMS.TokenService)'
[13:23:06 INF] Request finished HTTP/1.1 POST http://cloverleafcms-dev-apps-token/api/token - 403 null application/json; charset=utf-8 1042.2538ms

  • Steps to reproduce the issue: We're using the authserver application from the Microservice template and have a micro service to retrieve a token. Both are running as pods in AKS and we have the web gateway routing to the authserver service via ingress-nginx.

Following is the code in the token app service

using Duende.IdentityModel.Client;
using Volo.Abp;
using TokenService.Tokens;
using Volo.Abp.Application.Services;

namespace CloverleafCMS.TokenService.TokenService;

public class TokenAppService : ApplicationService, ITokenAppService
{
    private readonly IConfiguration _configuration;

    public TokenAppService(IConfiguration configuration)
    {
        _configuration = configuration;
    }

    public async Task<TokenResponseDto> GetAccessToken(
        string? Tenant,
        string clientId,
        string clientSecret,
        string userName,
        string password,
        string[] scopes
    )
    {
        Check.NotNull(clientId, nameof(clientId));
        Check.NotNull(clientSecret, nameof(clientSecret));
        Check.NotNull(userName, nameof(userName));
        Check.NotNull(password, nameof(password));

        var apiEndpoint = _configuration.GetValue<string>("AuthServer:Authority");
        var scope = string.Join(" ", scopes);
        var discoveryCache = new DiscoveryCache(apiEndpoint);
        var disco = await discoveryCache.GetAsync();

        if (disco.IsError)
        {
            Console.WriteLine(disco.Error);
            throw new UserFriendlyException($"Error retrieving discovery document: {disco.Error}");
        }

        var client = new HttpClient();

        var passwordTokenRequest = new PasswordTokenRequest
        {
            Address = disco.TokenEndpoint,
            ClientId = clientId,
            ClientSecret = clientSecret,
            UserName = userName,
            Password = password,
            Scope = scope
        };

        if (Tenant != null) passwordTokenRequest.Headers.Add("tenant", Tenant);
        var tokenResponse = await client.RequestPasswordTokenAsync(passwordTokenRequest);

        TokenResponseDto tokenRequestResponse = new();

        if (tokenResponse.IsError)
        {
            Console.WriteLine("error", tokenResponse);
            throw new UserFriendlyException($"Error retrieving token: {tokenResponse.ErrorDescription}");
        }
        else
        {
            tokenRequestResponse.AccessToken = tokenResponse.AccessToken;
            tokenRequestResponse.RefreshToken = tokenResponse.RefreshToken;
            tokenRequestResponse.ExpiresIn = tokenResponse.ExpiresIn;
        }

        return tokenRequestResponse;
    }

}

When I call the token I get the error.

curl --location 'https://webgateway.mydomain.dev/api/token' \
--header 'Content-Type: application/json' \
--data-raw '{
    "clientId": "CloverleafAPI",
    "clientSecret": "*****",
    "userName": "****",
    "password": "****",
    "scopes": ["address","email","phone","profile","roles","ActionItemService","AdministrationService","AIService","AuditLoggingService","AuthServer","ClientService","ClientServicesQuery","CommunicationsTemplateService","ContactService","DocTemplateService","DocumentService","EngagementLogService","FinancialService","GdprService","GuardianshipService","HousingService","HudService","IdentityService","LanguageService","MemberConfigService","NoteService","SaasService","ServicesService","StaffService","TokenService","WorkshopService"]
}'
{"error":{"code":null,"message":"Error retrieving discovery document: Endpoint does not use HTTPS: http://authserver.mydomain.dev/connect/authorize","details":null,"data":{},"validationErrors":null}}%   ```


When I examine the authserver pod log it appears the configuration was created successfully but that's where it ends

```cs
[13:23:05 INF] Request starting HTTP/1.1 GET http://authserver.mydomain.dev/.well-known/openid-configuration - null null
[13:23:05 WRN] Unknown proxy: [::ffff:10.244.2.61]:41130
[13:23:05 INF] The request URI matched a server endpoint: Configuration.
[13:23:05 INF] The configuration request was successfully extracted: {}.
[13:23:05 INF] The configuration request was successfully validated.
[13:23:06 INF] The response was successfully returned as a JSON document: {
  "issuer": "https://authserver.mydomain.dev/",
  "authorization_endpoint": "http://authserver.mydomain.dev/connect/authorize",
  "token_endpoint": "http://authserver.mydomain.dev/connect/token",
  "introspection_endpoint": "http://authserver.mydomain.dev/connect/introspect",
  "end_session_endpoint": "http://authserver.mydomain.dev/connect/endsession",
  "revocation_endpoint": "http://authserver.mydomain.dev/connect/revocat",
  "userinfo_endpoint": "http://authserver.mydomain.dev/connect/userinfo",
  "device_authorization_endpoint": "http://authserver.mydomain.dev/device",
  "pushed_authorization_request_endpoint": "http://authserver.mydomain.dev/connect/par",
  "jwks_uri": "http://authserver.mydomain.dev/.well-known/jwks",
  "grant_types_supported": [
    "authorization_code",
    "implicit",
    "password",
    "client_credentials",
    "refresh_token",
    "urn:ietf:params:oauth:grant-type:device_code",
    "LinkLogin",
    "Impersonation"
  ],
  "response_types_supported": [
    "code",
    "code id_token",
    "code id_token token",
    "code token",
    "id_token",
    "id_token token",
    "token",
    "none"
  ],
  "response_modes_supported": [
    "query",
    "form_post",
    "fragment"
  ],
  "scopes_supported": [
    "openid",
    "offline_access",
    "email",
    "profile",
    "phone",
    "roles",
    "address",
    "ActionItemService",
    "AdministrationService",
    "AIService",
    "AuditLoggingService",
    "AuthServer",
    "ClientService",
    "ClientServicesQuery",
    "CommunicationsTemplateService",
    "ContactService",
    "DocTemplateService",
    "DocumentService",
    "EngagementLogService",
    "FinancialService",
    "GdprService",
    "GuardianshipService",
    "HousingService",
    "HudService",
    "IdentityService",
    "LanguageService",
    "MemberConfigService",
    "NoteService",
    "SaasService",
    "ServicesService",
    "SMSService",
    "StaffService",
    "TokenService",
    "WorkshopService"
  ],
  "claims_supported": [
    "aud",
    "exp",
    "iat",
    "iss",
    "sub"
  ],
  "id_token_signing_alg_values_supported": [
    "RS256"
  ],
  "code_challenge_methods_supported": [
    "plain",
    "S256"
  ],
  "subject_types_supported": [
    "public"
  ],
  "prompt_values_supported": [
    "consent",
    "login",
    "none",
    "select_account"
  ],
  "token_endpoint_auth_methods_supported": [
    "client_secret_post",
    "private_key_jwt",
    "client_secret_basic"
  ],
  "introspection_endpoint_auth_methods_supported": [
    "client_secret_post",
    "private_key_jwt",
    "client_secret_basic"
  ],
  "revocation_endpoint_auth_methods_supported": [
    "client_secret_post",
    "private_key_jwt",
    "client_secret_basic"
  ],
  "device_authorization_endpoint_auth_methods_supported": [
    "client_secret_post",
    "private_key_jwt",
    "client_secret_basic"
  ],
  "pushed_authorization_request_endpoint_auth_methods_supported": [
    "client_secret_post",
    "private_key_jwt",
    "client_secret_basic"
  ],
  "require_pushed_authorization_requests": false,
  "claims_parameter_supported": false,
  "request_parameter_supported": false,
  "request_uri_parameter_supported": false,
  "tls_client_certificate_bound_access_tokens": false,
  "authorization_response_iss_parameter_supported": true
}.
[13:23:06 INF] Request finished HTTP/1.1 GET http://authserver.mydomain.dev/.well-known/openid-configuration - 200 3354 application/json;charset=UTF-8 900.7678ms

We have what I think is the exact same setup running in another cluster with no problem right now. However, this problem keeps popping up when we update the deployment. We use the same helm charts in both clusters and only change the values for the variables that are different between environments.


10 Answer(s)
  • User Avatar
    0
    AI-Bot created
    Support Team ABP Agent

    Your issue is caused by the OpenID Connect discovery document returning HTTP endpoints (e.g., "authorization_endpoint": "http://authserver.mydomain.dev/connect/authorize") instead of HTTPS, while your clients and security libraries require all endpoints to use HTTPS.

    This typically happens when your AuthServer is running behind a reverse proxy (like ingress-nginx in AKS), and the application itself is listening on HTTP. OpenIddict (or IdentityServer) generates endpoint URLs based on the incoming request's scheme, which is HTTP unless you explicitly handle forwarded headers.

    Solution:

    1. Forwarded Headers Middleware

      In your AuthServer's Startup or module initialization, add the following before any authentication middleware:

    app.UseForwardedHeaders(new ForwardedHeadersOptions
       {
           ForwardedHeaders = ForwardedHeaders.XForwardedProto | ForwardedHeaders.XForwardedFor,
           // Optionally, set KnownProxies or KnownNetworks if needed for security
       });
    

    This ensures the app recognizes the original HTTPS scheme from the proxy.

    1. Force HTTPS Scheme (if needed)

      If the above does not resolve the issue, you can force the request scheme to HTTPS as a workaround:

    app.Use(async (ctx, next) =>
       {
           ctx.Request.Scheme = "https";
           await next();
       });
    

    Place this middleware before authentication and OpenIddict middlewares.

    1. Set OpenIddict Issuer Explicitly

      In your AuthServer module, ensure you set the issuer to your public HTTPS URL:

    PreConfigure<OpenIddictServerBuilder>(builder =>
       {
           builder.SetIssuer(new Uri(configuration["AuthServer:Authority"]!));
       });
    
    1. Check NGINX/Ingress Configuration

      Make sure your ingress-nginx is forwarding the X-Forwarded-Proto header and not stripping it.

    2. Restart and Test

      After making these changes, restart your AuthServer pod and check the discovery document at https://authserver.mydomain.dev/.well-known/openid-configuration. All endpoints should now use HTTPS.

    References:

    • https://abp.io/docs/latest/solution-templates/layered-web-application/deployment/openiddict-deployment
    • https://abp.io/support/questions/9359

    This approach is the recommended and secure way to ensure your OpenIddict endpoints are correctly exposed as HTTPS behind a reverse proxy in Kubernetes.


    This response was generated by AI. If it didn’t solve your problem, feel free to post a new answer — our support team will jump in to help you soon.

  • User Avatar
    0
    rogercprops created

    The above changes didn't solve the problem

  • User Avatar
    0
    rogercprops created

    Updated authserver initialization

    public override void OnApplicationInitialization(ApplicationInitializationContext context)
        {
            var app = context.GetApplicationBuilder();
            var env = context.GetEnvironment();
            var configuration = context.ServiceProvider.GetRequiredService<IConfiguration>();
    
            app.UseForwardedHeaders(new ForwardedHeadersOptions
            {
                ForwardedHeaders = ForwardedHeaders.XForwardedProto | ForwardedHeaders.XForwardedFor,
                // Optionally, set KnownProxies or KnownNetworks if needed for security
            });
    
            app.Use(async (context, next) =>
            {
                context.Request.Scheme = "https";
                await next();
            });
    

    Updated ingress

    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      name: "{{ .Release.Name }}-{{ .Chart.Name }}"
      annotations:
        nginx.ingress.kubernetes.io/rewrite-target: "/"
        nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
        nginx.ingress.kubernetes.io/proxy-buffer-size: "32k"
        nginx.ingress.kubernetes.io/proxy-buffers-number: "8"
        nginx.ingress.kubernetes.io/ssl-redirect: "true"
        nginx.ingress.kubernetes.io/use-forwarded-headers: "true"
        nginx.ingress.kubernetes.io/enable-real-ip: "true"
        nginx.ingress.kubernetes.io/proxy-real-ip-cidr: "0.0.0.0/0"
        cert-manager.io/cluster-issuer: "letsencrypt"
    
  • User Avatar
    0
    rogercprops created

    Don't know what I did but just redeployed and it worked

  • User Avatar
    0
    rogercprops created

    I have no idea what has changed but it's giving the Error retrieving discovery document: Endpoint does not use HTTPS: http://authserver.mydomain.dev/connect/authorize.

    It was working yesterday and now it's not.

  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    hi

    What is the code of the DiscoveryCache class?

    It throws the Endpoint does not use HTTPS: http://authserver.mydomain.dev/connect/authorize

    Thanks.

  • User Avatar
    0
    rogercprops created

    DiscoveryCache is from the Duende.IdentityModel package

    // Copyright (c) Duende Software. All rights reserved.
    // Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information.
    
    using Duende.IdentityModel.Internal;
    
    namespace Duende.IdentityModel.Client;
    
    /// <summary>
    /// Helper for caching discovery documents.
    /// </summary>
    public class DiscoveryCache : IDiscoveryCache
    {
        private DateTime _nextReload = DateTime.MinValue;
        private AsyncLazy<DiscoveryDocumentResponse>? _lazyResponse;
    
        private readonly DiscoveryPolicy _policy;
        private readonly Func<HttpMessageInvoker> _getHttpClient;
        private readonly string _authority;
    
        /// <summary>
        /// Initialize instance of DiscoveryCache with passed authority.
        /// </summary>
        /// <param name="authority">Base address or discovery document endpoint.</param>
        /// <param name="policy">The policy.</param>
        public DiscoveryCache(string authority, DiscoveryPolicy? policy = null)
        {
            _authority = authority;
            _policy = policy ?? new DiscoveryPolicy();
            _getHttpClient = () => new HttpClient();
        }
    
        /// <summary>
        /// Initialize instance of DiscoveryCache with passed authority.
        /// </summary>
        /// <param name="authority">Base address or discovery document endpoint.</param>
        /// <param name="httpClientFunc">The HTTP client function.</param>
        /// <param name="policy">The policy.</param>
        public DiscoveryCache(string authority, Func<HttpMessageInvoker> httpClientFunc, DiscoveryPolicy? policy = null)
        {
            _authority = authority;
            _policy = policy ?? new DiscoveryPolicy();
            _getHttpClient = httpClientFunc ?? throw new ArgumentNullException(nameof(httpClientFunc));
        }
    
        /// <summary>
        /// Frequency to refresh discovery document. Defaults to 24 hours.
        /// </summary>
        public TimeSpan CacheDuration { get; set; } = TimeSpan.FromHours(24);
    
        /// <summary>
        /// Get the DiscoveryResponse either from cache or from discovery endpoint.
        /// </summary>
        /// <returns></returns>
        public Task<DiscoveryDocumentResponse> GetAsync()
        {
            if (_nextReload <= DateTime.UtcNow)
            {
                Refresh();
            }
    
            return _lazyResponse!.Value;
        }
    
        /// <summary>
        /// Marks the discovery document as stale and will trigger a request to the discovery endpoint on the next request to get the DiscoveryResponse.
        /// </summary>
        public void Refresh()
        {
            _lazyResponse = new AsyncLazy<DiscoveryDocumentResponse>(GetResponseAsync);
        }
    
        private async Task<DiscoveryDocumentResponse> GetResponseAsync()
        {
            var result = await _getHttpClient().GetDiscoveryDocumentAsync(new DiscoveryDocumentRequest
            {
                Address = _authority,
                Policy = _policy
            }).ConfigureAwait();
    
            if (result.IsError)
            {
                Refresh();
                _nextReload = DateTime.MinValue;
            }
            else
            {
                _nextReload = DateTime.UtcNow.Add(CacheDuration);
            }
    
            return result;
        }
    }
    
  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    hi

    Set RequireHttps of DiscoveryPolicy to false

    DiscoveryPolicy

    var policy = new DiscoveryPolicy
    {
        RequireHttps = false
    };
    
  • User Avatar
    0
    rogercprops created

    Set it where?

  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    hi

    Set is as your _policy default value or pass it as a parameter.

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 12, 2025, 10:20