typescript - 具有值的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"
}
}
解决方案
好的,我能够调试开源代码,并发现我提到的那篇文章使用了不同的验证方法定义。
似乎 validate 方法的定义已经改变。
所以我将令牌集作为第二个参数而不是第一个参数进行检索(在文章中它是第一个参数)。
所以而不是跟随。
async validate(tokenset: TokenSet): Promise<any> {
我不得不使用以下。
async validate(incomingMessage: IncomingMessage, tokenset: TokenSet): Promise<any> {
似乎打字稿在这种情况下没有帮助......
推荐阅读
- jenkins - 如何使用 jenkins ssh-steps 插件复制远程目录
- firebase - 如何检查文档中是否存在数据firebase颤动
- android - (AsyncTask) 和 (Thread with runOnUiThread) 有什么区别
- ceph - 使用多路径作为 OSD 的正确方法是什么?
- angular - 在 ngSelect 上使用 ngModel 绑定对象不起作用
- react-native - 打印磅签到反应本机热敏打印机( react-native-bluetooth-escpos-printer )
- python - 为什么我的矩形不出现(python 3.8 windows 7)
- javascript - 为什么这个计时器脚本不能按预期工作?
- flutter - 如何使用异步方法返回的值初始化小部件状态中的字段?
- python - “树视图焦点”时如何将图像表单数据库检索到标签?