package dbhandler import ( "context" "crypto/rand" "encoding/base64" "fmt" "log" "git.acooldomain.co/server-manager/backend/models" "github.com/coreos/go-oidc" "golang.org/x/oauth2" ) 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 }