我正在使用Nestjs和keycloak实现授权代码流,我已经将登录请求重定向到keycloak登录页面,我收到了授权代码,当将帖子发送到回调url时,我得到以下错误:
将循环结构转换为JSON→从带有构造函数'ClientRequest'的对象开始|属性'socket' ->具有构造函数'Socket'的对象——property '_httpMessage'关闭圆圈
我注意到只有在将授权码作为参数传递后才会发生此错误:
遵循代码:
import { HttpException, HttpService, Injectable } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { KeycloakConnectModule } from 'nest-keycloak-connect';
import * as queryString from 'querystring'
import { catchError } from 'rxjs/operators';
@Injectable()
export class AuthService {
private keycloakLoginUri: string;
private keycloakResponseType: string;
private keycloakScope: string;
private keycloakRedirectUri: string;
private keycloakGrantType: string;
private keycloakClientId: string;
private keycloakClientSecret: string;
private keycloakTokenUri: string;
constructor( readonly _config: ConfigService, private readonly _http: HttpService) {
this.keycloakLoginUri = _config.get('KEYCLOAK_LOGIN_URI');
this.keycloakResponseType = _config.get('KEYCLOAK_RESPONSE_TYPE');
this.keycloakScope = _config.get('KEYCLOAK_SCOPE');
this.keycloakRedirectUri = _config.get('KEYCLOAK_REDIRECT_URI');
this.keycloakGrantType = 'authorization_code';
this.keycloakClientId = _config.get('KEYCLOAK_CLIENT_ID');
this.keycloakClientSecret = _config.get('KEYCLOAK_CLIENT_SECRET');
this.keycloakTokenUri = this._config.get('KEYCLOAK_TOKEN_URI');
}
getLoginUrl(): any {
return { url: `${this.keycloakLoginUri}`
+`?client_id=${this.keycloakClientId}`
+`&response_type=${this.keycloakResponseType}`
+`&scope=${this.keycloakScope}`
+`&redirect_uri=${this.keycloakRedirectUri}`
}
}
getKeyCloakToken(code: string){
const params = {
grant_type: this.keycloakGrantType,
client_id: this.keycloakClientId,
client_secret: this.keycloakClientSecret,
code: code,
redirect_uri: this.keycloakRedirectUri
};
const config = {
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
}
return this._http.post(
this.keycloakTokenUri,
queryString.stringify(params),
config)
.pipe(catchError(e => {
throw new HttpException(e.response.data, e.response.status);
}));
}
}
.env上定义的环境变量
KEYCLOAK_LOGIN_URI=http://localhost:8080/auth/realms/onboarding-arqt/protocol/openid-connect/auth
KEYCLOAK_AUTH_URI=http://localhost:8080/auth
KEYCLOAK_TOKEN_URI=http://localhost:8080/auth/realms/onboarding-arqt/protocol/openid-connect/token?
KEYCLOAK_GRANT_TYPE=authorization_code
KEYCLOAK_REALM=my-realm
KEYCLOAK_CLIENT_ID=my-id
KEYCLOAK_CLIENT_SECRET=my-secret
KEYCLOAK_REDIRECT_URI=http://localhost:3000/callback
KEYCLOAK_SCOPE=profile
KEYCLOAK_RESPONSE_TYPE=code
您应该映射httpService
的响应。Axios (HttpService
在底层使用的)返回一个圆形对象,因此您需要将其映射到您所期望的对象。最有可能的是,在pipe
中添加这一行将修复它
import { map } from 'rxjs/operators';
...
return this._http.post(whatever).pipe(
map((res) => res.data),
catchError(e => { throw new HttpException(e.response.data, e.response.status);}),
);
...
顺便说一下,现在您已经公开发布了您的keycloak信息,请确保旋转密钥并生成新的安全数据。否则,您的应用程序可能根本没有身份验证,并完全被泄露。