将 OIDC 添加到我的 SPA 后反向代理错误网关

Posted

技术标签:

【中文标题】将 OIDC 添加到我的 SPA 后反向代理错误网关【英文标题】:Reverse Proxy Bad Gateway after adding OIDC to my SPA 【发布时间】:2022-01-14 11:50:59 【问题描述】:

我正在将 keycloak 添加到我公司现有的用 Angular 编写的 SPA 中。

由于初始身份验证运行良好,我已经设法从 keycloak 获取 acess_token,但是当我尝试与我的 API 通信时,大约一半的请求会引发 502 bad gateway 错误。

当我在本地测试一切运行良好且完美无缺时,我现在正在我们的开发 kubernetes 集群上对其进行测试。

方案是这样的:

Web 应用程序(由 nginx 服务器提供的 angular SPA),nginx 服务器充当反向代理来与我的 api 对话

Api 服务器(用 nestJS 编写,带有对我的访问令牌的服务器端验证)

NGINX 服务器使用 clusterIP kubernetes 服务与 Api 服务器通信。

我相信问题来自 api 上的令牌验证,由于某种原因有时无法正常工作或需要太长时间,从而引发错误。

这就是它的样子:

@Injectable()
export class ownKeycloakStrategy extends PassportStrategy(BearerStrategy, 'keycloak') 
  
  constructor(private readonly openidService: OpenidService, private readonly staffService:StaffService,
    private readonly adminService:AdminService) 
    
    super(
      (token, done) => this.validate(token, done)
    );
  

  async validate(token, done): Promise<any> 
   var userInKC = null
    try 
      userInKC =  await this.openidService.validateToken(token);
     catch (e) 
      return done(e)
    
    // get Info from KC, if you cant means either user doesnt exist or token is not valid
    //console.log(userInKC)
    if(!userInKC) return done(new UnauthorizedException('Token not valid'))
    // complete user object with info from our db
    const userX: any = await Promise.all([
              // here searches for user in own db
              
          ]).then(x => x.find(e => e !== null));
    if (!userX) return done(new NotFoundException('User not found'))
    // here we set up the user of the rerquest so our service can work properly
    const user = 
      ...userInKC,
      _id: userX,
      status: userX.status
    
    return done(null, user, scope: 'all');
  

我的 validateToken 函数:

public async validateToken(token) 
        try 
            const public_key = await this.public_key()
            if(public_key) 
                const decrypt = await this.keycloak.jwt.verifyOffline(token, public_key);
                return decrypt.content
            
         catch(e) 
            return this.keycloak.jwt.verify(token);
        
    

我尝试了什么:

更改我的 nginx conf 的代理缓冲以允许更大的 access_token 标头 尝试直接调用我的 api(我也收到错误的网关错误,这次我相信来自 traefik(我的集群负载均衡器)

感谢您提供的任何帮助,如果您需要知道什么,请告诉我

谢谢

【问题讨论】:

【参考方案1】:

这感觉就像您应该首先确保这不是 API 错误处理问题。首先测试失败场景,使用 curl 工具,然后在本地运行 API:

在没有授权标头的情况下调用 API 使用“xxx”等无效令牌调用 API
curl -i http://localhost:3000/somepath \
-H "Authorization: Bearer xxx'

然后,您应该得到一个受控响应,例如错误对象,以及 401 的 HTTP 状态。响应可能需要一个 Access-Control-Allow-Origin 标头,以便 SPA 能够读取响应并采取正确的行动。

可靠的 JWT 验证

以下是 API 最常见的两种 JWT 故障场景:

客户端发送无效或过期的令牌 - 这将发生,因此 API 必须处理这种情况并返回 401 API 下载令牌签名公钥失败 - 在这种情况下,API 必须返回 500,因为 SPA 无法解决此问题并需要显示错误

比较的东西

如果有帮助,请查看 this Node.js code example of mine 并注意它旨在返回适用于客户端的错误响应以及 API 中的日志记录详细信息。

NGINX

值得了解这是在做什么。最常见的设置是仅使用 proxy-path directive 传递整个请求和响应,包括所有标头。

INFRA

也许存在更深层次的基础设施问题,例如负载平衡器或 NGINX 路由到不健康的 API 服务器。不过,您应该能够遵循这种科学方法:

没有 API 日志,因此请求未到达 API 没有 NGINX 日志,因此请求没有到达反向代理 因此这是基础设施人员必须解决的问题

【讨论】:

以上是关于将 OIDC 添加到我的 SPA 后反向代理错误网关的主要内容,如果未能解决你的问题,请参考以下文章

ID4 ADFS 3.0 和 oidc-client (vue spa) - 回调实现

具有基本身份验证的 Apache 反向代理

我的 Apache 反向代理将代码添加到从 head 标记获取的 HTML 文件的正文中

POST 参数不是从我的反向代理传递到我的后端服务器

nginx自动添加内网端口

SPA + API + OIDC:仅提供 ACCESS 令牌时如何验证 API 调用者?