package dbhandler import ( "context" "crypto/rand" "encoding/base64" "fmt" "log" "git.acooldomain.co/server-manager/backend-kubernetes-go/models" "github.com/coreos/go-oidc" "golang.org/x/oauth2" ) type LoginRequest struct { Username string `json:"username"` Password string `json:"password"` } type InviteUserRequest struct { Email string `json:"email"` InvitingUser string `json:"inviting_user"` Permissions models.Permission `json:"permissions"` } type InviteToken struct { Email string `json:"email"` Permissions models.Permission `json:"permissions"` Token string `json:"token"` } type UserSignupRequest struct { Token InviteToken `json:"token"` Username string `json:"username"` Password string `json:"password"` } type UserPassAuthanticationDbHandler interface { AuthenticateUser(LoginRequest) (models.Permission, error) InviteUser(InviteUserRequest) (InviteToken, error) UserSignup(UserSignupRequest) error RemoveUser(string) error SetPermissions(string, models.Permission) error } type CallbackRequest struct { Code string `json:"code"` } type OidcClaims struct { Email string Profile string Permissions models.Permission } type OidcAuthenticationDbHandler struct { provider *oidc.Provider oauth2Config *oauth2.Config } func GenerateOidcState() string { b := make([]byte, 16) _, err := rand.Read(b) if err != nil { log.Fatal(err) } return base64.URLEncoding.EncodeToString(b) } func (self *OidcAuthenticationDbHandler) AuthenticateUser(ctx context.Context, request CallbackRequest) (models.Permission, error) { token, err := self.oauth2Config.Exchange(ctx, request.Code) if err != nil { return 0, err } verifier := self.provider.Verifier(&oidc.Config{ClientID: self.oauth2Config.ClientID}) idToken, ok := token.Extra("id_token").(string) if !ok { return 0, fmt.Errorf("Failed to convert id_token to string") } tokenObj, err := verifier.Verify(ctx, idToken) var claims OidcClaims if err := tokenObj.Claims(&claims); err != nil { return 0, err } return claims.Permissions, nil } func NewOidcAuthenticationDbHamdler(config models.OidcAuthConfig) (*OidcAuthenticationDbHandler, error) { provider, err := oidc.NewProvider(context.Background(), config.IssuerUrl) if err != nil { return nil, err } return &OidcAuthenticationDbHandler{ provider: provider, oauth2Config: &oauth2.Config{ ClientID: config.ClientId, ClientSecret: config.ClientSecret, Endpoint: provider.Endpoint(), Scopes: []string{oidc.ScopeOpenID, "email", "name", "profile"}, }, }, nil }