Okta JWT 令牌解码问题



我正在使用 Okta 的okta-jwt-verifier-golang为 AWS API 网关实现自定义授权方。

我的无服务器.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)
}

从 CloudWatch 日志中的 okta 验证程序库调用VerifyAccessTokenfunc 时,我可以看到它抛出以下错误: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 上解码工作正常。这似乎是一个库问题。

因此,看起来来自授权处理程序的event.AuthorizationToken没有解析出Bearer并且弄乱了解码。

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

最新更新