package oidc import ( "context" "log/slog" "net/http" "os" "slices" "git.ctdo.de/ctdo/machinelock-manager/config" "git.ctdo.de/ctdo/machinelock-manager/cookies" "github.com/coreos/go-oidc/v3/oidc" "github.com/gin-gonic/gin" "golang.org/x/oauth2" ) var provider *oidc.Provider var oauth2Config oauth2.Config func init() { ctx := context.Background() var err error provider, err = oidc.NewProvider(ctx, config.OauthEndpoint) if err != nil { slog.Error(err.Error()) os.Exit(1) } oauth2Config = oauth2.Config{ ClientID: config.OauthClientID, ClientSecret: config.OauthClientSecret, RedirectURL: config.BaseUrl + "/auth/success", Endpoint: provider.Endpoint(), Scopes: []string{oidc.ScopeOpenID, "profile", "email"}, } } func HandleRedirect(ctx *gin.Context) { ctx.Redirect(http.StatusFound, oauth2Config.AuthCodeURL("machinelock")) } func HandleOauthCallback(ctx *gin.Context) { verifier := provider.Verifier(&oidc.Config{ClientID: oauth2Config.ClientID}) oauth2Token, err := oauth2Config.Exchange(ctx, ctx.Query("code")) if err != nil { slog.Error(err.Error()) ctx.String(http.StatusInternalServerError, "internal error check logs") return } rawIDToken, ok := oauth2Token.Extra("id_token").(string) if !ok { ctx.String(http.StatusInternalServerError, "internal error check logs") return } // Parse and verify ID Token payload. idToken, err := verifier.Verify(ctx, rawIDToken) if err != nil { slog.Error(err.Error()) ctx.String(http.StatusInternalServerError, "internal error check logs") return } // Extract custom claims var claims struct { Groups []string `json:"groups"` } if err := idToken.Claims(&claims); err != nil { slog.Error(err.Error()) ctx.String(http.StatusInternalServerError, "internal error check logs") return } if slices.Contains(claims.Groups, "admin") { cookies.SetAuth(ctx, true) slog.Info("auth success") ctx.Redirect(http.StatusFound, "/") } else { cookies.SetAuth(ctx, false) slog.Info("auth failure") ctx.Redirect(http.StatusFound, "/forbidden") } }