auth/internal/user/delivery/http/user_http.go

86 lines
2.1 KiB
Go
Raw Normal View History

2022-02-17 16:16:15 +00:00
package http
import (
"net/http"
2022-02-17 16:16:15 +00:00
"strings"
"github.com/goccy/go-json"
"github.com/lestrrat-go/jwx/v2/jwa"
2022-02-17 16:16:15 +00:00
"source.toby3d.me/toby3d/auth/internal/common"
"source.toby3d.me/toby3d/auth/internal/domain"
"source.toby3d.me/toby3d/auth/internal/middleware"
"source.toby3d.me/toby3d/auth/internal/token"
2022-02-17 16:16:15 +00:00
)
type Handler struct {
config *domain.Config
tokens token.UseCase
}
2022-02-17 16:16:15 +00:00
func NewHandler(tokens token.UseCase, config *domain.Config) *Handler {
return &Handler{
2022-02-17 16:16:15 +00:00
tokens: tokens,
config: config,
}
}
func (h *Handler) Handler() http.Handler {
2022-02-17 16:16:15 +00:00
chain := middleware.Chain{
2022-12-26 14:09:34 +00:00
//nolint:exhaustivestruct
2022-02-17 16:16:15 +00:00
middleware.JWTWithConfig(middleware.JWTConfig{
2022-02-25 23:18:04 +00:00
AuthScheme: "Bearer",
ContextKey: "token",
SigningKey: []byte(h.config.JWT.Secret),
SigningMethod: jwa.SignatureAlgorithm(h.config.JWT.Algorithm),
Skipper: middleware.DefaultSkipper,
TokenLookup: "header:" + common.HeaderAuthorization + ":Bearer ",
2022-02-17 16:16:15 +00:00
}),
}
return chain.Handler(h.handleFunc)
2022-02-17 16:16:15 +00:00
}
func (h *Handler) handleFunc(w http.ResponseWriter, r *http.Request) {
if r.Method != "" && r.Method != http.MethodGet {
http.Error(w, http.StatusText(http.StatusMethodNotAllowed), http.StatusMethodNotAllowed)
return
}
w.Header().Set(common.HeaderContentType, common.MIMEApplicationJSONCharsetUTF8)
2022-02-17 16:16:15 +00:00
encoder := json.NewEncoder(w)
2022-02-17 16:16:15 +00:00
tkn, userInfo, err := h.tokens.Verify(r.Context(),
strings.TrimPrefix(r.Header.Get(common.HeaderAuthorization), "Bearer "))
2022-02-17 16:16:15 +00:00
if err != nil || tkn == nil {
// WARN(toby3d): If the token is not valid, the endpoint still
// MUST return a 200 Response.
2022-12-26 14:09:34 +00:00
_ = encoder.Encode(err) //nolint:errchkjson
w.WriteHeader(http.StatusOK)
2022-02-17 16:16:15 +00:00
return
}
if !tkn.Scope.Has(domain.ScopeProfile) {
2022-12-26 14:09:34 +00:00
//nolint:errchkjson
2022-02-17 16:16:15 +00:00
_ = encoder.Encode(domain.NewError(
domain.ErrorCodeInsufficientScope,
"token with 'profile' scope is required to view profile data",
2022-02-17 16:16:15 +00:00
"https://indieauth.net/source/#user-information",
))
w.WriteHeader(http.StatusForbidden)
return
}
//nolint:errchkjson
_ = encoder.Encode(NewUserInformationResponse(userInfo,
userInfo.HasEmail() && tkn.Scope.Has(domain.ScopeEmail)))
w.WriteHeader(http.StatusOK)
2022-02-17 16:16:15 +00:00
}