From 645daae946907c039f14f0be63d1f99dadec68a6 Mon Sep 17 00:00:00 2001 From: Maxim Lebedev Date: Wed, 8 May 2024 19:24:23 +0500 Subject: [PATCH] :bug: Fixed parsing actions in token HTTP delivery --- internal/token/delivery/http/token_http.go | 59 +++++-------------- .../token/delivery/http/token_http_schema.go | 58 +++++++++++++++--- 2 files changed, 65 insertions(+), 52 deletions(-) diff --git a/internal/token/delivery/http/token_http.go b/internal/token/delivery/http/token_http.go index 23e3967..353807f 100644 --- a/internal/token/delivery/http/token_http.go +++ b/internal/token/delivery/http/token_http.go @@ -3,20 +3,18 @@ package http import ( "encoding/json" "net/http" - - "github.com/lestrrat-go/jwx/v2/jwa" + "strings" "source.toby3d.me/toby3d/auth/internal/common" "source.toby3d.me/toby3d/auth/internal/domain" "source.toby3d.me/toby3d/auth/internal/domain/action" - "source.toby3d.me/toby3d/auth/internal/middleware" "source.toby3d.me/toby3d/auth/internal/token" pathutil "source.toby3d.me/toby3d/auth/internal/util/path" ) type Handler struct { - config domain.Config tokens token.UseCase + config domain.Config } func NewHandler(tokens token.UseCase, config domain.Config) *Handler { @@ -27,22 +25,6 @@ func NewHandler(tokens token.UseCase, config domain.Config) *Handler { } func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) { - chain := middleware.Chain{ - //nolint:exhaustivestruct - middleware.JWTWithConfig(middleware.JWTConfig{ - Skipper: func(_ http.ResponseWriter, r *http.Request) bool { - head, _ := pathutil.Shift(r.URL.Path) - - return head == "token" - }, - SigningKey: []byte(h.config.JWT.Secret), - SigningMethod: jwa.SignatureAlgorithm(h.config.JWT.Algorithm), - ContextKey: "token", - TokenLookup: "form:token," + "header:" + common.HeaderAuthorization + ":Bearer ", - AuthScheme: "Bearer", - }), - } - if r.Method != http.MethodPost { http.Error(w, http.StatusText(http.StatusMethodNotAllowed), http.StatusMethodNotAllowed) @@ -56,11 +38,11 @@ func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) { default: http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound) case "token": - chain.Handler(h.handleAction).ServeHTTP(w, r) + h.handleAction(w, r) case "introspect": - chain.Handler(h.handleIntrospect).ServeHTTP(w, r) + h.handleIntrospect(w, r) case "revocation": - chain.Handler(h.handleRevokation).ServeHTTP(w, r) + h.handleRevocation(w, r) } } @@ -95,14 +77,7 @@ func (h *Handler) handleIntrospect(w http.ResponseWriter, r *http.Request) { return } - _ = encoder.Encode(&TokenIntrospectResponse{ - Active: true, - ClientID: tkn.ClientID.String(), - Exp: tkn.Expiry.Unix(), - Iat: tkn.CreatedAt.Unix(), - Me: tkn.Me.String(), - Scope: tkn.Scope.String(), - }) + _ = encoder.Encode(NewTokenIntrospectResponse(tkn)) w.WriteHeader(http.StatusOK) } @@ -114,6 +89,12 @@ func (h *Handler) handleAction(w http.ResponseWriter, r *http.Request) { return } + if err := r.ParseForm(); err != nil { + http.Error(w, err.Error(), http.StatusBadRequest) + + return + } + w.Header().Set(common.HeaderContentType, common.MIMEApplicationJSONCharsetUTF8) encoder := json.NewEncoder(w) @@ -130,7 +111,7 @@ func (h *Handler) handleAction(w http.ResponseWriter, r *http.Request) { return } - a, err := action.Parse(r.PostForm.Get("action")) + a, err := action.Parse(strings.ToLower(r.PostForm.Get("action"))) if err != nil { w.WriteHeader(http.StatusBadRequest) @@ -141,7 +122,7 @@ func (h *Handler) handleAction(w http.ResponseWriter, r *http.Request) { switch a { case action.Revoke: - h.handleRevokation(w, r) + h.handleRevocation(w, r) } } } @@ -181,20 +162,12 @@ func (h *Handler) handleExchange(w http.ResponseWriter, r *http.Request) { return } - resp := &TokenExchangeResponse{ - AccessToken: token.AccessToken, - ExpiresIn: token.Expiry.Unix(), - Me: token.Me.String(), - Profile: NewTokenProfileResponse(profile), - RefreshToken: "", // TODO(toby3d) - } - - _ = encoder.Encode(resp) + _ = encoder.Encode(NewTokenExchangeResponse(*token, profile)) w.WriteHeader(http.StatusOK) } -func (h *Handler) handleRevokation(w http.ResponseWriter, r *http.Request) { +func (h *Handler) handleRevocation(w http.ResponseWriter, r *http.Request) { if r.Method != http.MethodPost { http.Error(w, http.StatusText(http.StatusMethodNotAllowed), http.StatusMethodNotAllowed) diff --git a/internal/token/delivery/http/token_http_schema.go b/internal/token/delivery/http/token_http_schema.go index 86ea9f6..08caebf 100644 --- a/internal/token/delivery/http/token_http_schema.go +++ b/internal/token/delivery/http/token_http_schema.go @@ -2,6 +2,7 @@ package http import ( "errors" + "fmt" "net/http" "source.toby3d.me/toby3d/auth/internal/domain" @@ -124,16 +125,16 @@ func NewTokenProfileResponse(in *domain.Profile) *TokenProfileResponse { out.Name = in.Name - if in.URL != nil { - out.URL = in.URL.String() - } + for dst, src := range map[*string]fmt.Stringer{ + &out.Email: in.Email, + &out.Photo: in.Photo, + &out.URL: in.URL, + } { + if src == nil { + continue + } - if in.Photo != nil { - out.Photo = in.Photo.String() - } - - if in.Email != nil { - out.Email = in.Email.String() + *dst = src.String() } return out @@ -216,3 +217,42 @@ func (r *TokenIntrospectRequest) bind(req *http.Request) error { return nil } + +func NewTokenExchangeResponse(token domain.Token, profile *domain.Profile) *TokenExchangeResponse { + out := &TokenExchangeResponse{ + Profile: NewTokenProfileResponse(profile), + AccessToken: token.AccessToken, + Me: token.Me.String(), + RefreshToken: token.RefreshToken, + ExpiresIn: 0, + } + + if !token.Expiry.IsZero() { + out.ExpiresIn = token.Expiry.Unix() + } + + return out +} + +func NewTokenIntrospectResponse(token *domain.Token) *TokenIntrospectResponse { + out := new(TokenIntrospectResponse) + + if token == nil { + return out + } + + out.Active = true + out.Me = token.Me.String() + out.ClientID = token.ClientID.String() + out.Scope = token.Scope.String() + + if !token.CreatedAt.IsZero() { + out.Iat = token.CreatedAt.Unix() + } + + if !token.Expiry.IsZero() { + out.Exp = token.Expiry.Unix() + } + + return out +}