customer/internal/utils/authenticator.go

73 lines
2.0 KiB
Go
Raw Normal View History

2023-06-22 09:36:43 +00:00
package utils
import (
"context"
"fmt"
"net/http"
"strings"
"github.com/deepmap/oapi-codegen/pkg/middleware"
"github.com/getkin/kin-openapi/openapi3filter"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/errors"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/models"
)
const (
prefix = "Bearer "
)
func NewAuthenticator(jwtUtil *JWT) openapi3filter.AuthenticationFunc {
return func(ctx context.Context, input *openapi3filter.AuthenticationInput) error {
if jwtUtil == nil {
return errors.New(
fmt.Errorf("jwt util is nil: %w", errors.ErrInvalidArgs),
errors.ErrInvalidArgs,
)
}
return authenticate(ctx, jwtUtil, input)
}
}
func authenticate(ctx context.Context, jwtUtil *JWT, input *openapi3filter.AuthenticationInput) error {
if input.SecuritySchemeName != "Bearer" {
return fmt.Errorf("security scheme %s != 'Bearer'", input.SecuritySchemeName)
}
// Now, we need to get the JWS from the request, to match the request expectations
// against request contents.
jws, err := parseJWSFromRequest(input.RequestValidationInput.Request)
if err != nil {
return err
}
// if the JWS is valid, we have a JWT, which will contain a bunch of claims.
2023-06-29 14:50:48 +00:00
userID, validateErr := jwtUtil.Validate(jws)
2023-06-22 09:36:43 +00:00
if validateErr != nil {
return validateErr
}
// Set the property on the echo context so the handler is able to
// access the claims data we generate in here.
echoCtx := middleware.GetEchoContext(ctx)
2023-06-29 14:50:48 +00:00
echoCtx.Set(models.AuthJWTDecodedUserIDKey, userID)
echoCtx.Set(models.AuthJWTDecodedAccessTokenKey, jws)
2023-06-22 09:36:43 +00:00
return nil
}
// extracts a JWS string from an Authorization: Bearer <jws> header.
func parseJWSFromRequest(request *http.Request) (string, errors.Error) {
header := request.Header.Get("Authorization")
if header == "" || !strings.HasPrefix(header, prefix) {
return "", errors.New(
fmt.Errorf("failed to parse jws from request header: %s", header),
errors.ErrNoAccess,
)
}
return strings.TrimPrefix(header, prefix), nil
}