package setup import ( "context" "crypto/rand" "fmt" "forge.cadoles.com/wpetit/clearcase/internal/config" "forge.cadoles.com/wpetit/clearcase/internal/http/handler/webui/auth" "github.com/gorilla/sessions" "github.com/markbates/goth" "github.com/markbates/goth/gothic" "github.com/markbates/goth/providers/github" "github.com/markbates/goth/providers/google" "github.com/markbates/goth/providers/openidConnect" "github.com/pkg/errors" ) func NewAuthHandlerFromConfig(ctx context.Context, conf *config.Config) (*auth.Handler, error) { // Configure sessions store keyPairs := make([][]byte, 0) if len(conf.HTTP.Session.Keys) == 0 { key, err := getRandomBytes(32) if err != nil { return nil, errors.Wrap(err, "could not generate cookie signing key") } keyPairs = append(keyPairs, key) } else { for _, k := range conf.HTTP.Session.Keys { keyPairs = append(keyPairs, []byte(k)) } } sessionStore := sessions.NewCookieStore(keyPairs...) sessionStore.MaxAge(int(conf.HTTP.Session.Cookie.MaxAge)) sessionStore.Options.Path = conf.HTTP.Session.Cookie.Path sessionStore.Options.HttpOnly = conf.HTTP.Session.Cookie.HTTPOnly sessionStore.Options.Secure = conf.HTTP.Session.Cookie.Secure // Configure providers gothProviders := make([]goth.Provider, 0) providers := make([]auth.Provider, 0) if conf.Auth.Providers.Google.Key != "" && conf.Auth.Providers.Google.Secret != "" { googleProvider := google.New( conf.Auth.Providers.Google.Key, conf.Auth.Providers.Google.Secret, fmt.Sprintf("%s/auth/providers/google/callback", conf.HTTP.BaseURL), conf.Auth.Providers.Google.Scopes..., ) gothProviders = append(gothProviders, googleProvider) providers = append(providers, auth.Provider{ ID: googleProvider.Name(), Label: "Google", Icon: "fa-google", }) } if conf.Auth.Providers.Github.Key != "" && conf.Auth.Providers.Github.Secret != "" { githubProvider := github.New( conf.Auth.Providers.Github.Key, conf.Auth.Providers.Github.Secret, fmt.Sprintf("%s/auth/providers/github/callback", conf.HTTP.BaseURL), conf.Auth.Providers.Github.Scopes..., ) gothProviders = append(gothProviders, githubProvider) providers = append(providers, auth.Provider{ ID: githubProvider.Name(), Label: "Github", Icon: "fa-github", }) } if conf.Auth.Providers.OIDC.Key != "" && conf.Auth.Providers.OIDC.Secret != "" { oidcProvider, err := openidConnect.New( conf.Auth.Providers.OIDC.Key, conf.Auth.Providers.OIDC.Secret, fmt.Sprintf("%s/auth/providers/openid-connect/callback", conf.HTTP.BaseURL), conf.Auth.Providers.OIDC.DiscoveryURL, conf.Auth.Providers.OIDC.Scopes..., ) if err != nil { return nil, errors.Wrap(err, "could not configure oidc provider") } gothProviders = append(gothProviders, oidcProvider) providers = append(providers, auth.Provider{ ID: oidcProvider.Name(), Label: conf.Auth.Providers.OIDC.Label, Icon: conf.Auth.Providers.OIDC.Icon, }) } goth.UseProviders(gothProviders...) gothic.Store = sessionStore opts := []auth.OptionFunc{ auth.WithProviders(providers...), } if conf.Auth.DefaultAdmin.Email != "" && conf.Auth.DefaultAdmin.Provider != "" { opts = append(opts, auth.WithDefaultAdmin(auth.DefaultAdmin{ Provider: conf.Auth.DefaultAdmin.Provider, Email: conf.Auth.DefaultAdmin.Email, })) } auth := auth.NewHandler( sessionStore, opts..., ) return auth, nil } func getRandomBytes(n int) ([]byte, error) { data := make([]byte, n) read, err := rand.Read(data) if err != nil { return nil, errors.WithStack(err) } if read != n { return nil, errors.Errorf("could not read %d bytes", n) } return data, nil }