You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

node-oidc-provider中JWT令牌introspection始终返回active: false求助

Node OIDC Provider中JWT令牌Introspection返回{"active": false}问题

我在node-oidc-provider中启用了JWT令牌introspection功能,但调用该接口时始终返回{"active": false}。需要说明的是,opaque令牌的introspection功能运行正常,且我已在OIDC配置中开启了jwtIntrospection特性。

返回active: false的JWT载荷示例

{
  "realm": "aq",
  "last_password_update": null,
  "jti": "pVMmyVTjmzVqLsl-9p5Ms",
  "sub": "953b49e3-14ee-4278-b818-1666fb0c1f67",
  "iat": 1707926210,
  "exp": 1707928010,
  "client_id": "953b49e3-14ee-4278-b818-1666fb0c1f67",
  "iss": "http://localhost:3080/op",
  "aud": "http://localhost:3080/api/v1/"
}

Opaque令牌的Introspection响应

{
  "active": true,
  "realm": "aq",
  "invitation_token": null,
  "last_password_update": null,
  "client_id": "953b49e3-14ee-4278-b818-1666fb0c1f67",
  "exp": 1707927912,
  "iat": 1707926112,
  "iss": "http://localhost:3080/op",
  "token_type": "Bearer"
}

请问我是否遗漏了某些配置?感谢解答!


补充:OIDC配置及令牌Introspection代码

OIDC配置

private static oidcConfiguration = async (): Promise<Configuration> => ({
  acrValues: getAcrPolicies().map((acrPolicy) => acrPolicy.acrValue),
  conformIdTokenClaims: false,
  extraClientMetadata: {
    properties: [
      'accessTokenLifetime',
      'cancel_logout_redirect_uris',
      'consumedResources',
      'isIntrospectionAllowed',
      'managedResource',
      'pkceRequired',
      'refreshTokenTotalLifetime',
      'serviceId',
    ],
  },
  extraParams: ['sign_in_only', 'sign_up', 'invitation_token', 'sub', 'login_hint'],
  extraTokenClaims,
  scopes: getScopePolicies().map((scope) => scope.scope),
  clients: getClients(),
  cookies: {
    names: {
      interaction: 'op_interaction',
      resume: 'op_interaction_resume',
      session: 'op_session',
      state: 'op_state',
    },
    long: {
      httpOnly: true,
      overwrite: true,
      signed: true,
      secure: process.env.APP_ENV !== 'local',
      sameSite: 'none',
      path: process.env.OP_PATH,
    },
    short: {
      httpOnly: true,
      overwrite: true,
      signed: true,
      secure: process.env.APP_ENV !== 'local',
      sameSite: 'none',
      path: process.env.OP_PATH,
    },
    keys: getMainConfiguration().cookieKeys,
  },
  interactions: {
    policy: await OidcService.getPolicy(),
    url(_, interaction: Interaction) {
      return concatUrl('/op', '/interaction', interaction.uid);
    },
  },
  routes: {
    authorization: '/auth',
    code_verification: '/device',
    device_authorization: '/device/auth',
    end_session: '/session/end',
    introspection: '/token/introspection',
    jwks: '/jwks',
    pushed_authorization_request: '/request',
    registration: '/reg',
    revocation: '/token/revocation',
    token: '/token',
    userinfo: '/me',
  },
  features: {
    // Node OIDC Provider parameters
    backchannelLogout: { enabled: true },
    claimsParameter: { enabled: false },
    clientCredentials: { enabled: true },
    dPoP: { enabled: false },
    devInteractions: { enabled: false },
    deviceFlow: { enabled: false },
    encryption: { enabled: false },
    introspection: {
      enabled: true,
      allowedPolicy: (ctx, client) => {
        const clientMetadata = client.metadata();

        return clientMetadata.isIntrospectionAllowed;
      },
    },
    jwtIntrospection: { enabled: true, ack: 'draft-10' },
    jwtResponseModes: { enabled: false },
    jwtUserinfo: { enabled: false },
    mTLS: { enabled: false },
    pushedAuthorizationRequests: { enabled: false },
    registration: { enabled: false },
    registrationManagement: { enabled: false },
    requestObjects: {},
    resourceIndicators: {
      // enable = true, to activate resourceIndicator
      enabled: true,
      // defaultResource = undefined, to return an access token without audience when no resource is explicitly request during AT request
      defaultResource: (ctx) => undefined,
      getResourceServerInfo: async (ctx, resourceIndicator, client) => {
        return OidcService.getResourceServerInfo(ctx, resourceIndicator, client);
      },
      useGrantedResource: () => false,
    },
    revocation: { enabled: true },
    rpInitiatedLogout: {
      enabled: true,
      logoutSource: async (ctx: KoaContextWithOIDC, form: string): Promise<void> => {
        ctx.body = await logoutPage(ctx, form);
      },
      postLogoutSuccessSource: async (ctx: KoaContextWithOIDC): Promise<void> => {
        ctx.body = await postLogoutSuccessPage(ctx);
      },
    },
    userinfo: { enabled: true },
    webMessageResponseMode: { enabled: false },
  },
  findAccount: (ctx: KoaContextWithOIDC, sub: string): any => AccountService.findAccount(ctx, sub),
  ttl: ttlConfiguration,
  pkce: {
    methods: ['S256'],
    required: (ctx, client) => {
      return client.pkceRequired !== false;
    },
  },
  renderError: (ctx, out, error) => {
    const err = error as errorsType.OIDCProviderError;
    const clientId = ctx.oidc?.client?.clientId;

    return RenderPageUtils.renderError(ctx.req as Request, ctx.res as Response, {
      statusCode: err?.statusCode ? err.statusCode.toString() : '500',
      reason: out.error_description,
      clientId,
    });
  },
});

令牌Introspection代码(Express路由中间件)

const client = await getClientAPI();
const instrospectResponse = await client.introspect(accessToken, 'access_token');

Client信息

{
  "authorization_signed_response_alg": "RS256",
  "client_id": "client-api",
  "grant_types": [
    "authorization_code"
  ],
  "id_token_signed_response_alg": "ES256",
  "introspection_endpoint_auth_method": "private_key_jwt",
  "introspection_endpoint_auth_signing_alg": "ES256",
  "introspection_signed_response_alg": "ES256",
  "response_types": [
    "code"
  ],
  "revocation_endpoint_auth_method": "private_key_jwt",
  "revocation_endpoint_auth_signing_alg": "ES256",
  "token_endpoint_auth_method": "private_key_jwt",
  "token_endpoint_auth_signing_alg": "ES256"
}

内容的提问来源于stack exchange,提问作者Jas

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 05:25:19