olivetin/service/internal/auth/authcheck.go

72 lines
1.7 KiB
Go

package auth
import (
"context"
"net/http"
"connectrpc.com/connect"
types "github.com/OliveTin/OliveTin/internal/auth/authpublic"
otjwt "github.com/OliveTin/OliveTin/internal/auth/otjwt"
"github.com/OliveTin/OliveTin/internal/config"
log "github.com/sirupsen/logrus"
)
var authChain = []func(*types.AuthCheckingContext) *types.AuthenticatedUser{
checkUserFromHeaders,
checkUserFromLocalSession,
checkUserFromLocalBearerApiKey,
otjwt.CheckUserFromJwtHeader,
otjwt.CheckUserFromJwtCookie,
}
// Handlers like the OAuth2's handler are "instance methods", so they need to be added to the auth chain after the other handlers.
func AddAuthChainFunction(check func(*types.AuthCheckingContext) *types.AuthenticatedUser) {
authChain = append(authChain, check)
}
func runAuthChain[T any](req *connect.Request[T], cfg *config.Config) *types.AuthenticatedUser {
var user *types.AuthenticatedUser
authCtx := &types.AuthCheckingContext{
Request: &http.Request{Header: req.Header()},
Config: cfg,
}
for _, check := range authChain {
user = check(authCtx)
if user != nil && user.Username != "" {
return user
}
}
return nil
}
func UserFromApiCall[T any](ctx context.Context, req *connect.Request[T], cfg *config.Config) *types.AuthenticatedUser {
user := runAuthChain(req, cfg)
log.Tracef("UserFromApiCall Context: %+v", ctx)
if user == nil || user.Username == "" {
user = UserGuest(cfg)
} else {
user.BuildUserAcls(cfg)
}
path := ""
if req != nil {
path = req.Spec().Procedure
}
log.WithFields(log.Fields{
"username": user.Username,
"usergroupLine": user.UsergroupLine,
"provider": user.Provider,
"acls": user.Acls,
"path": path,
}).Debugf("Authenticated API request")
return user
}