首页 > 解决方案 > Okta JWT 令牌解码问题

问题描述

我正在使用 Okta 的okta-jwt-verifier-golang.

我的 serverless.yml 看起来像这样......

functions:
  myfunc:
    handler: bin/myfunc
    events:
      - http:
          path: myfunc
          method: post
          authorizer: app-auth
          cors: true
  app-auth:
    handler: bin/auth/app

我的授权人看起来像这样......

# app-auth/main.go
package main

import (
    "context"
    "errors"
    "fmt"

    "myapi/utils"
    "github.com/aws/aws-lambda-go/events"
    "github.com/aws/aws-lambda-go/lambda"
)

func Handler(ctx context.Context, event events.APIGatewayCustomAuthorizerRequest) (events.APIGatewayCustomAuthorizerResponse, error) {
    bearerToken := event.AuthorizationToken
    fmt.Println("Token:" + bearerToken)

    _, err := utils.VerifyAccessToken(bearerToken)

    fmt.Println("error:" + err.Error())
    if err != nil {
        fmt.Println("error not null")
        return events.APIGatewayCustomAuthorizerResponse{}, errors.New("Unauthorized")
    }

    return utils.GeneratePolicy("user", "Allow", event.MethodArn), nil
}

func main() {
    lambda.Start(Handler)
}
# utils/okta.go
package utils

import (
    "os"
    "fmt"
    verifier "github.com/okta/okta-jwt-verifier-golang"
)


func VerifyAccessToken(bearerToken string) (*verifier.Jwt, error) {
    tv := map[string]string{}
    tv["aud"] = "api://default"
    tv["cid"] = os.Getenv("CLIENT_ID")
    jv := verifier.JwtVerifier{
        Issuer:           os.Getenv("ISSUER"),
        ClaimsToValidate: tv,
    }
    jv.SetLeeway(60) //seconds
    fmt.Println("")
    return jv.New().VerifyAccessToken(bearerToken)
}

VerifyAccessToken从 CloudWatch 日志中的 okta 验证程序库调用func 时,我可以看到它抛出以下错误: token is not valid: the tokens header does not appear to be a base64 encoded string. 在库中,这发生在这一步这一步

我还在使用 okta React 应用程序启动器并使用 accessToken 发布到我的端点。

try {
      const urlParams = decode(window.location.search.substr(1));
      const user = await this.props.auth.getUser()
      /* global fetch */
      const payload = {
        ...urlParams,
        user_id: user.sub
      }
      const response = await fetch(config.resourceServer.messagesUrl + "/v1/myfunc", {
        method: "POST",
        body: JSON.stringify(payload),
        // credentials: 'include',
        headers: {
          'Content-Type': 'application/json',
          'Authorization': `Bearer ${ await this.props.auth.getAccessToken() }`,
        },
      });

在客户端上,由于此错误,我得到了正确的 401,但是,即使cors: true我的端点设置"Access-Control-Allow-Origin": "*",我得到以下客户端错误。

Access to fetch at 'https://myhost.com/v1/myfunc' from origin 'http://localhost:8080' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.

但是,我认为这个问题将在解码问题得到解决后得到解决。

我试图自己解码它,它实际上似乎没有正确解码,所以令牌可能没有正确编码?也许客户端应用程序做错了什么?我已经检查过并仔细遵循了文档,但似乎无法自己解决这个问题。

有小费吗?

更新 1:看起来令牌分为 3 个部分。第 1 部分是引发解码错误的标头。整个令牌使用https://www.jsonwebtoken.io/正确解码,标题部分也是如此。在库代码的此步骤中,这可能是一个问题:

parts := strings.Split(jwt, ".")
    header := parts[0]
    header = padHeader(header)
    headerDecoded, err := base64.StdEncoding.DecodeString(header)

    if err != nil {
        return false, fmt.Errorf("the tokens header does not appear to be a base64 encoded string")
    }

更新 2:因此,base64.StdEncoding.DecodeString创建以下错误illegal base64 data at input byte 88。但是,在 jsonwebtoken.io 上解码工作正常。这似乎是一个库问题

标签: aws-lambdajwtaws-api-gatewayserverlessokta

解决方案


所以看起来event.AuthorizationToken来自授权处理程序的 没有解析Bearer出来并且正在搞乱解码。

bearerToken := event.AuthorizationToken
token := strings.Replace(bearerToken, "Bearer ", "", -1)

_, err := utils.VerifyAccessToken(token)

推荐阅读