最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

.net core - OpenIddict Token Introspection Returns "active": false – Issuer Mismatch in Docker Environment? -

programmeradmin2浏览0评论

I'm running an application in Docker with two services: an identity service (using OpenIddict to issue tokens) and an api service (using OpenIddict validation middleware). The services are defined in my Docker Compose files as follows:

docker-compose.yml

services:
  api:
    image: ${DOCKER_REGISTRY-}api
    networks:
      - documentmanagement
    build:
      context: .
      dockerfile: Api/Dockerfile

  identity:
    image: ${DOCKER_REGISTRY-}identity
    depends_on:
      - db
    build:
      context: .
      dockerfile: Identity/Dockerfile
    networks:
      - documentmanagement

networks:
  documentmanagement:
    name: documentmanagement

docker-compose.override.yml

services:
  api:
    environment:
      - ASPNETCORE_ENVIRONMENT=Development
      - ASPNETCORE_HTTP_PORTS=7002
      - ASPNETCORE_HTTPS_PORTS=7001
    ports:
      - "64589:7001"
      - "64590:7002"
    volumes:
      - ${APPDATA}/Microsoft/UserSecrets:/home/app/.microsoft/usersecrets:ro
      - ${APPDATA}/ASP.NET/Https:/home/app/.aspnet/https:ro

  identity:
    container_name: identity
    environment:
      - ASPNETCORE_ENVIRONMENT=Development
      - ASPNETCORE_HTTP_PORTS=7004
      - ASPNETCORE_HTTPS_PORTS=7003
    ports:
      - "64587:7003"
      - "64588:7004"
    volumes:
      - ${APPDATA}/Microsoft/UserSecrets:/home/app/.microsoft/usersecrets:ro
      - ${APPDATA}/ASP.NET/Https:/home/app/.aspnet/https:ro

Identity Service (OpenIddict Server Configuration)

public static void AddOpenIddictServices(this IServiceCollection services, IConfiguration configuration, IHostEnvironment env)
{
    services.AddOpenIddict()
        .AddCore(options =>
        {
            options.UseEntityFrameworkCore()
                   .UseDbContext<ApplicationDbContext>();
        })
        .AddServer(options =>
        {
            options
                .SetAuthorizationEndpointUris("connect/authorize")
                .SetLogoutEndpointUris("connect/logout")
                .SetTokenEndpointUris("connect/token")
                .SetIntrospectionEndpointUris("introspect")
                .SetUserinfoEndpointUris("connect/userinfo");

            options.RegisterScopes(Scopes.Email, Scopes.Profile, Scopes.Roles);

            options.AllowAuthorizationCodeFlow()
                   .AllowImplicitFlow()
                   .AllowClientCredentialsFlow();

            options.AddDevelopmentSigningCertificate();
            options.AddDevelopmentEncryptionCertificate();

            options.UseAspNetCore()
                   .DisableTransportSecurityRequirement()
                   .EnableAuthorizationEndpointPassthrough()
                   .EnableTokenEndpointPassthrough()
                   .EnableUserinfoEndpointPassthrough()
                   .EnableLogoutEndpointPassthrough();
        })
        .AddValidation(options =>
        {
            options.UseLocalServer();
            options.UseAspNetCore();
        });
}

Client code

const oidcSettings: VueOidcSettings = {
  authority: "http://localhost:64588",
  scope: "openid profile email api1",
  client_id: "nirvana-cms-spa",
  client_secret: "FCAzGmhIsn3ZbGvpcIvjnstjBSIMW2KU",
  redirect_uri: origin + "/oidc-callback",
  post_logout_redirect_uri: origin + "/signout",
  response_type: "code",
  loadUserInfo: true,
  userStore: new WebStorageStateStore({
    prefix: "vue3-oidc",
    store: window.sessionStorage,
  }),
  automaticSilentRenew: true,
  monitorSession: true,
  silent_redirect_uri: location.origin + "/silent-renew.html",
  onSigninRedirectCallback(user) {
    location.href = unref(state).redirect_uri || "/";
  },
  onBeforeSigninRedirectCallback() {
    setRedirectUri(location.pathname + location.search);
  },
};

API Service (OpenIddict Validation Configuration)

builder.Services.AddOpenIddict()
    .AddValidation(options =>
    {
        options.SetIssuer("http://identity:7004/");
        options.AddAudiences("resource_server_1");

        options.UseIntrospection()
               .SetClientId("resource_server_1")
               .SetClientSecret("846B62D0-DEF9-4215-A99D-86E6B8DAB342");

        options.UseSystemNetHttp();
        options.UseAspNetCore();
    });

The Issue When I call protected API endpoints with a token issued by the identity service, I receive the following error in the API logs:

"error": "invalid_token",
"error_description": "The token was rejected by the remote authentication server.",

The logs indicate that the introspection endpoint is called, and the returned token introspection response is:

{ "active": false }

The log details show different URLs being used:

  • The identity service issues tokens with issuer "http://localhost:64588" (as per client configuration).
  • The API’s validation is set with issuer "http://identity:7004/".

It appears there is a mismatch between the issuer URL embedded in the token and the issuer expected by the API validation.

There is a mismatch between the issuer URL embedded in the token and the issuer expected by the API validation.

How should I configure the identity service's issuer so that both internal (Docker service names) and external (mapped ports) communications work correctly?

What is the recommended configuration for setting up OpenIddict in a Docker environment to avoid this token introspection error?

I'm running an application in Docker with two services: an identity service (using OpenIddict to issue tokens) and an api service (using OpenIddict validation middleware). The services are defined in my Docker Compose files as follows:

docker-compose.yml

services:
  api:
    image: ${DOCKER_REGISTRY-}api
    networks:
      - documentmanagement
    build:
      context: .
      dockerfile: Api/Dockerfile

  identity:
    image: ${DOCKER_REGISTRY-}identity
    depends_on:
      - db
    build:
      context: .
      dockerfile: Identity/Dockerfile
    networks:
      - documentmanagement

networks:
  documentmanagement:
    name: documentmanagement

docker-compose.override.yml

services:
  api:
    environment:
      - ASPNETCORE_ENVIRONMENT=Development
      - ASPNETCORE_HTTP_PORTS=7002
      - ASPNETCORE_HTTPS_PORTS=7001
    ports:
      - "64589:7001"
      - "64590:7002"
    volumes:
      - ${APPDATA}/Microsoft/UserSecrets:/home/app/.microsoft/usersecrets:ro
      - ${APPDATA}/ASP.NET/Https:/home/app/.aspnet/https:ro

  identity:
    container_name: identity
    environment:
      - ASPNETCORE_ENVIRONMENT=Development
      - ASPNETCORE_HTTP_PORTS=7004
      - ASPNETCORE_HTTPS_PORTS=7003
    ports:
      - "64587:7003"
      - "64588:7004"
    volumes:
      - ${APPDATA}/Microsoft/UserSecrets:/home/app/.microsoft/usersecrets:ro
      - ${APPDATA}/ASP.NET/Https:/home/app/.aspnet/https:ro

Identity Service (OpenIddict Server Configuration)

public static void AddOpenIddictServices(this IServiceCollection services, IConfiguration configuration, IHostEnvironment env)
{
    services.AddOpenIddict()
        .AddCore(options =>
        {
            options.UseEntityFrameworkCore()
                   .UseDbContext<ApplicationDbContext>();
        })
        .AddServer(options =>
        {
            options
                .SetAuthorizationEndpointUris("connect/authorize")
                .SetLogoutEndpointUris("connect/logout")
                .SetTokenEndpointUris("connect/token")
                .SetIntrospectionEndpointUris("introspect")
                .SetUserinfoEndpointUris("connect/userinfo");

            options.RegisterScopes(Scopes.Email, Scopes.Profile, Scopes.Roles);

            options.AllowAuthorizationCodeFlow()
                   .AllowImplicitFlow()
                   .AllowClientCredentialsFlow();

            options.AddDevelopmentSigningCertificate();
            options.AddDevelopmentEncryptionCertificate();

            options.UseAspNetCore()
                   .DisableTransportSecurityRequirement()
                   .EnableAuthorizationEndpointPassthrough()
                   .EnableTokenEndpointPassthrough()
                   .EnableUserinfoEndpointPassthrough()
                   .EnableLogoutEndpointPassthrough();
        })
        .AddValidation(options =>
        {
            options.UseLocalServer();
            options.UseAspNetCore();
        });
}

Client code

const oidcSettings: VueOidcSettings = {
  authority: "http://localhost:64588",
  scope: "openid profile email api1",
  client_id: "nirvana-cms-spa",
  client_secret: "FCAzGmhIsn3ZbGvpcIvjnstjBSIMW2KU",
  redirect_uri: origin + "/oidc-callback",
  post_logout_redirect_uri: origin + "/signout",
  response_type: "code",
  loadUserInfo: true,
  userStore: new WebStorageStateStore({
    prefix: "vue3-oidc",
    store: window.sessionStorage,
  }),
  automaticSilentRenew: true,
  monitorSession: true,
  silent_redirect_uri: location.origin + "/silent-renew.html",
  onSigninRedirectCallback(user) {
    location.href = unref(state).redirect_uri || "/";
  },
  onBeforeSigninRedirectCallback() {
    setRedirectUri(location.pathname + location.search);
  },
};

API Service (OpenIddict Validation Configuration)

builder.Services.AddOpenIddict()
    .AddValidation(options =>
    {
        options.SetIssuer("http://identity:7004/");
        options.AddAudiences("resource_server_1");

        options.UseIntrospection()
               .SetClientId("resource_server_1")
               .SetClientSecret("846B62D0-DEF9-4215-A99D-86E6B8DAB342");

        options.UseSystemNetHttp();
        options.UseAspNetCore();
    });

The Issue When I call protected API endpoints with a token issued by the identity service, I receive the following error in the API logs:

"error": "invalid_token",
"error_description": "The token was rejected by the remote authentication server.",

The logs indicate that the introspection endpoint is called, and the returned token introspection response is:

{ "active": false }

The log details show different URLs being used:

  • The identity service issues tokens with issuer "http://localhost:64588" (as per client configuration).
  • The API’s validation is set with issuer "http://identity:7004/".

It appears there is a mismatch between the issuer URL embedded in the token and the issuer expected by the API validation.

There is a mismatch between the issuer URL embedded in the token and the issuer expected by the API validation.

How should I configure the identity service's issuer so that both internal (Docker service names) and external (mapped ports) communications work correctly?

What is the recommended configuration for setting up OpenIddict in a Docker environment to avoid this token introspection error?

Share Improve this question asked Mar 2 at 6:57 User_4373User_4373 2971 gold badge4 silver badges20 bronze badges 1
  • Perhaps my blog post here can give you some ideas nestenius.se/net/identityserver-in-docker-containers-part-1 – Tore Nestenius Commented Mar 3 at 20:09
Add a comment  | 

1 Answer 1

Reset to default 0

I am able to work this with some minor changes, I hope this doesn't cause another problem.

Since the Vue client is running outside the Docker network, it needs to access the identity service using http://localhost:64588.

I Changed the oidcSettings to match the external URL: authority: "http://localhost:64588"

Ensured the API Uses the Same Issuer Modify your API validation to match the issuer:

builder.Services.AddOpenIddict()
.AddValidation(options =>
{
    // Match the issuer with the one set in the Identity service
    options.SetIssuer("http://identity:7004/");
    
    options.AddAudiences("resource_server_1");

    options.UseIntrospection()
           .SetClientId("resource_server_1")
           .SetClientSecret("846B62D0-DEF9-4215-A99D-86E6B8DAB342");

    options.UseSystemNetHttp();
    options.UseAspNetCore();
});

Set the Issuer in the Identity Service

Modified the OpenIddict server configuration:

options.SetIssuer(new Uri("http://identity:7004/"));

Updated Identity Service Configuration:

public static void AddOpenIddictServices(this IServiceCollection services, IConfiguration configuration, IHostEnvironment env)
{
    services.AddOpenIddict()
        .AddCore(options =>
        {
            options.UseEntityFrameworkCore()
                   .UseDbContext<ApplicationDbContext>();
        })
        .AddServer(options =>
        {

            options.SetIssuer(new Uri("http://identity:7004/"))
                .SetAuthorizationEndpointUris("connect/authorize")
                .SetLogoutEndpointUris("connect/logout")
                .SetTokenEndpointUris("connect/token")
                .SetIntrospectionEndpointUris("introspect")
                .SetUserinfoEndpointUris("connect/userinfo");

            options.RegisterScopes(Scopes.Email, Scopes.Profile, Scopes.Roles);

            options.AllowAuthorizationCodeFlow()
                   .AllowImplicitFlow()
                   .AllowClientCredentialsFlow();

            options.AddDevelopmentSigningCertificate();
            options.AddDevelopmentEncryptionCertificate();

            options.UseAspNetCore()
                   .DisableTransportSecurityRequirement()
                   .EnableAuthorizationEndpointPassthrough()
                   .EnableTokenEndpointPassthrough()
                   .EnableUserinfoEndpointPassthrough()
                   .EnableLogoutEndpointPassthrough();
        })
        .AddValidation(options =>
        {
            options.UseLocalServer();
            options.UseAspNetCore();
        });
}

与本文相关的文章

发布评论

评论列表(0)

  1. 暂无评论