Added UserInfo endpoint

This commit is contained in:
Maxim Lebedev 2022-02-17 21:16:15 +05:00
parent 6594a532fc
commit 9b94472bb5
Signed by: toby3d
GPG Key ID: 1F14E25B7C119FC5
1 changed files with 95 additions and 0 deletions

View File

@ -0,0 +1,95 @@
package http
import (
"encoding/json"
"strings"
"github.com/fasthttp/router"
"github.com/lestrrat-go/jwx/jwa"
http "github.com/valyala/fasthttp"
"source.toby3d.me/toby3d/middleware"
"source.toby3d.me/website/indieauth/internal/common"
"source.toby3d.me/website/indieauth/internal/domain"
"source.toby3d.me/website/indieauth/internal/token"
)
type (
UserInformationResponse struct {
Name string `json:"name,omitempty"`
URL *domain.URL `json:"url,omitempty"`
Photo *domain.URL `json:"photo,omitempty"`
Email *domain.Email `json:"email,omitempty"`
}
RequestHandler struct {
config *domain.Config
tokens token.UseCase
}
)
func NewRequestHandler(tokens token.UseCase, config *domain.Config) *RequestHandler {
return &RequestHandler{
tokens: tokens,
config: config,
}
}
func (h *RequestHandler) Register(r *router.Router) {
chain := middleware.Chain{
middleware.JWTWithConfig(middleware.JWTConfig{
AuthScheme: "Bearer",
BeforeFunc: nil,
Claims: nil,
ContextKey: "token",
ErrorHandler: nil,
ErrorHandlerWithContext: nil,
ParseTokenFunc: nil,
SigningKey: []byte(h.config.JWT.Secret),
SigningKeys: nil,
SigningMethod: jwa.SignatureAlgorithm(h.config.JWT.Algorithm),
Skipper: middleware.DefaultSkipper,
SuccessHandler: nil,
TokenLookup: middleware.SourceHeader + ":" + http.HeaderAuthorization +
"," + middleware.SourceCookie + ":" + "__Secure-auth-token",
}),
middleware.LogFmt(),
}
r.GET("/userinfo", chain.RequestHandler(h.handleUserInformation))
}
func (h *RequestHandler) handleUserInformation(ctx *http.RequestCtx) {
ctx.SetContentType(common.MIMEApplicationJSONCharsetUTF8)
ctx.SetStatusCode(http.StatusOK)
encoder := json.NewEncoder(ctx)
tkn, err := h.tokens.Verify(ctx, strings.TrimPrefix(string(ctx.Request.Header.Peek(http.HeaderAuthorization)),
"Bearer "))
if err != nil || tkn == nil {
// WARN(toby3d): If the token is not valid, the endpoint still
// MUST return a 200 Response.
_ = encoder.Encode(err)
return
}
if !tkn.Scope.Has(domain.ScopeProfile) && !tkn.Scope.Has(domain.ScopeEmail) {
ctx.SetStatusCode(http.StatusForbidden)
_ = encoder.Encode(domain.NewError(
domain.ErrorCodeInsufficientScope,
"token with 'profile' and/or 'email' scopes is required to view profile data",
"https://indieauth.net/source/#user-information",
))
return
}
_ = encoder.Encode(&UserInformationResponse{
Name: "",
URL: &domain.URL{},
Photo: &domain.URL{},
Email: &domain.Email{},
})
}