首页 > 解决方案 > 具有值的reference_token授权:[object Object]在商店中找不到

问题描述

我正在使用带有 oidc 护照策略的 NestJs 和 identityserver,如下所示。

import { UnauthorizedException } from '@nestjs/common';
import { PassportStrategy } from '@nestjs/passport';
import { Strategy, Client, UserinfoResponse, TokenSet, Issuer } from 'openid-client';
import { AuthService } from './auth.service';

export const buildOpenIdClient = async () => {
  const TrustIssuer = await Issuer.discover(`http://localhost:5001/.well-known/openid-configuration`);
  const client = new TrustIssuer.Client({
    client_id: 'mvc',
    //client_secret: 'K7gNU3sdo+OL0wNhqoVWhr3g6s1xYv72ol/pe/Unols=',
    client_secret: 'secret',
    redirect_uris: ['http://localhost:3100/api/callback'],
    post_logout_redirect_uris: ['http://localhost:3100/signout-callback-oidc'],
    token_endpoint_auth_method: 'client_secret_post',
  });
  return client;
};

export class OidcStrategy extends PassportStrategy(Strategy, 'oidc') {
  client: Client;

  constructor(private readonly authService: AuthService, client: Client) {
    super({
      client: client,
      params: {
        redirect_uri: 'http://localhost:3100/api/callback',
        scope: 'openid profile api1',
      },
      passReqToCallback: true,
      usePKCE: false,
    });

    this.client = client;
  }

  async validate(tokenset: TokenSet): Promise<any> {
    const userinfo: UserinfoResponse = await this.client.userinfo(tokenset); // HERE IT THROWS ERROR

    try {
      const id_token = tokenset.id_token
      const access_token = tokenset.access_token
      const refresh_token = tokenset.refresh_token
      const user = {
        id_token,
        access_token,
        refresh_token,
        userinfo,
      }
      return user;
    } catch (err) {
      throw new UnauthorizedException();
    }
  }
}

我的身份验证模块如下所示。

// src/auth/auth.module.ts
import { Module } from '@nestjs/common';
import { PassportModule } from '@nestjs/passport';
import { OidcStrategy, buildOpenIdClient } from './oidc.strategy';
import { SessionSerializer } from './session.serializer';
import { AuthService } from './auth.service';
import { AuthController } from './auth.controller';

const OidcStrategyFactory = {
  provide: 'OidcStrategy',
  useFactory: async (authService: AuthService) => {
    const client = await buildOpenIdClient(); // secret sauce! build the dynamic client before injecting it into the strategy for use in the constructor super call.
    const strategy = new OidcStrategy(authService, client);
    return strategy;
  },
  inject: [AuthService]
};

@Module({
  imports: [
    PassportModule.register({ session: true, defaultStrategy: 'oidc' }),
  ],
  controllers: [AuthController],
  providers: [OidcStrategyFactory, SessionSerializer, AuthService],
})
export class AuthModule {}

因此它重定向到身份服务器并使用令牌获取回调,但this.client.userinfo(tokenset)会出现以下错误。

在 Identityserver 上,它会记录以下 2 个错误。

1) reference_token grant with value: [object Object] not found in store.

2) Invalid reference token.
{"ClientId": null, "ClientName": null, "ValidateLifetime": true, "AccessTokenType": "Reference", "ExpectedScope": "openid", "TokenHandle": "[object Object]", "JwtId": null, "Claims": null, "$type": "TokenValidationLog"}

在 NestJs 上,它会记录以下内容。

OPError {error: 'invalid_token', message: 'invalid_token', name: 'OPError', stack: 'OPError: invalid_token

以下是我用作参考的文章。 https://sdoxsee.github.io/blog/2020/02/05/cats-nest-nestjs-mongo-oidc.html

以下是我的身份服务器客户端。

 new Client
                {
                    ClientId = "mvc",
                    ClientSecrets = { new Secret("secret") },
                    RequirePkce = false,

                    AccessTokenType = AccessTokenType.Reference,

                    RequireClientSecret = false,

                    AllowedGrantTypes = GrantTypes.Code,
                    
                    // where to redirect to after login
                    RedirectUris = { "http://localhost:3100/api/callback" },

                    // where to redirect to after logout
                    PostLogoutRedirectUris = { "http://localhost:3100/signout-callback-oidc" },

                    AllowedScopes = new List<string>
                    {
                        IdentityServerConstants.StandardScopes.OpenId,
                        IdentityServerConstants.StandardScopes.Profile,
                        "api1"
                    }
                }

标签: typescriptoauth-2.0identityserver4nestjsopenid-connect

解决方案


好的,我能够调试开源代码,并发现我提到的那篇文章使用了不同的验证方法定义。

似乎 validate 方法的定义已经改变。

所以我将令牌集作为第二个参数而不是第一个参数进行检索(在文章中它是第一个参数)。

所以而不是跟随。

async validate(tokenset: TokenSet): Promise<any> {

我不得不使用以下。

async validate(incomingMessage: IncomingMessage, tokenset: TokenSet): Promise<any> {

似乎打字稿在这种情况下没有帮助......


推荐阅读