95 lines
2.7 KiB
Go
95 lines
2.7 KiB
Go
package middleware
|
|
|
|
import (
|
|
"net/http"
|
|
"time"
|
|
|
|
"forge.cadoles.com/arcad/edge/pkg/jwtutil"
|
|
"forge.cadoles.com/arcad/edge/pkg/module/auth"
|
|
"github.com/lestrrat-go/jwx/v2/jwa"
|
|
"github.com/lestrrat-go/jwx/v2/jwk"
|
|
"github.com/pkg/errors"
|
|
"gitlab.com/wpetit/goweb/logger"
|
|
)
|
|
|
|
func DefaultUser(key jwk.Key, signingAlgorithm jwa.SignatureAlgorithm, funcs ...DefaultUserOptionFunc) func(next http.Handler) http.Handler {
|
|
opts := defaultUserOptions()
|
|
for _, fn := range funcs {
|
|
fn(opts)
|
|
}
|
|
|
|
return func(next http.Handler) http.Handler {
|
|
handler := func(w http.ResponseWriter, r *http.Request) {
|
|
rawToken, err := jwtutil.FindRawToken(r, jwtutil.WithFinders(
|
|
jwtutil.FindTokenFromAuthorizationHeader,
|
|
jwtutil.FindTokenFromQueryString(auth.CookieName),
|
|
jwtutil.FindTokenFromCookie(auth.CookieName),
|
|
))
|
|
|
|
// If request already has a raw token, we do nothing
|
|
if rawToken != "" && err == nil {
|
|
next.ServeHTTP(w, r)
|
|
return
|
|
}
|
|
|
|
ctx := r.Context()
|
|
|
|
subject, err := opts.GetSubject(r)
|
|
if err != nil {
|
|
logger.Error(ctx, "could not retrieve user subject", logger.CapturedE(errors.WithStack(err)))
|
|
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
|
|
|
|
return
|
|
}
|
|
|
|
preferredUsername, err := opts.GetPreferredUsername(r)
|
|
if err != nil {
|
|
logger.Error(ctx, "could not retrieve user preferred username", logger.CapturedE(errors.WithStack(err)))
|
|
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
|
|
|
|
return
|
|
}
|
|
|
|
claims := map[string]any{
|
|
auth.ClaimSubject: subject,
|
|
auth.ClaimIssuer: opts.Issuer,
|
|
auth.ClaimPreferredUsername: preferredUsername,
|
|
auth.ClaimEdgeRole: opts.Role,
|
|
auth.ClaimEdgeEntrypoint: opts.Entrypoint,
|
|
auth.ClaimEdgeTenant: opts.Tenant,
|
|
}
|
|
|
|
token, err := jwtutil.SignedToken(key, signingAlgorithm, claims)
|
|
if err != nil {
|
|
logger.Error(ctx, "could not generate signed token", logger.CapturedE(errors.WithStack(err)))
|
|
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
|
|
|
|
return
|
|
}
|
|
|
|
cookieDomain, err := opts.GetCookieDomain(r)
|
|
if err != nil {
|
|
logger.Error(ctx, "could not retrieve cookie domain", logger.CapturedE(errors.WithStack(err)))
|
|
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
|
|
|
|
return
|
|
}
|
|
|
|
cookie := http.Cookie{
|
|
Name: auth.CookieName,
|
|
Value: string(token),
|
|
Domain: cookieDomain,
|
|
HttpOnly: false,
|
|
Expires: time.Now().Add(opts.CookieDuration),
|
|
Path: "/",
|
|
}
|
|
|
|
http.SetCookie(w, &cookie)
|
|
|
|
next.ServeHTTP(w, r)
|
|
}
|
|
|
|
return http.HandlerFunc(handler)
|
|
}
|
|
}
|