Я внедряю собственный авторизатор для AWS API Gateway, используя 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
из lib верификатора okta в журналах CloudWatch я вижу, что она выдает следующую ошибку: token is not valid: the tokens header does not appear to be a base64 encoded string
.В lib это происходит в на этом шаге и на этом шаге .
Я также использую стартер приложения 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 работает нормально.Кажется, это проблема lib .