294 lines
8.2 KiB
Go
294 lines
8.2 KiB
Go
package auth
|
|
|
|
import (
|
|
"fmt"
|
|
"log/slog"
|
|
"os"
|
|
"reflect"
|
|
"strings"
|
|
|
|
"github.com/caarlos0/env/v11"
|
|
)
|
|
|
|
// CognitoConfig holds the configuration for AWS Cognito
|
|
// Contains all necessary parameters to interact with Cognito endpoints
|
|
type CognitoConfig struct {
|
|
// annotated vars
|
|
AuthRegion string `env:"COGNITO_REGION" envDefault:"us-east-2"`
|
|
AuthUserPoolID string `env:"COGNITO_USER_POOL_ID,required,notEmpty"`
|
|
AuthClientSecret string `env:"COGNITO_CLIENT_SECRET,required,notEmpty"`
|
|
AuthDomain string `env:"COGNITO_DOMAIN,required,notEmpty"`
|
|
AuthClientID string `env:"COGNITO_CLIENT_ID,required,notEmpty"`
|
|
DisableAuth string `env:"DISABLE_AUTH" envDefault:"false"`
|
|
|
|
AuthRedirectURI string // URL where Cognito redirects after authentication
|
|
AuthTokenURL string // Cognito endpoint for token operations
|
|
AuthJwksURL string // URL for JSON Web Key Set (for token verification)
|
|
AuthURL string // Cognito authorization endpoint for initiating login
|
|
AuthLoginPath string `env:"COGNITO_LOGIN_PATH" envDefault:"/login"`
|
|
AuthCallbackPath string `env:"COGNITO_CALLBACK_PATH" envDefault:"/login-callback"`
|
|
AuthHomePath string `env:"COGNITO_HOME_PATH" envDefault:"/home"`
|
|
AuthLogoutPath string `env:"COGNITO_LOGOUT_PATH" envDefault:"/logout"`
|
|
AuthLogger *slog.Logger // Logger instance ( normally just the same logger as main)
|
|
AuthRoutePermissions map[string][]string // Map of routes to required permissions
|
|
}
|
|
|
|
type ConfigProvider interface {
|
|
// Env annotated fields
|
|
GetAuthRegion() string
|
|
SetAuthRegion(string)
|
|
GetAuthUserPoolID() string
|
|
SetAuthUserPoolID(string)
|
|
GetAuthClientSecret() string
|
|
SetAuthClientSecret(string)
|
|
GetAuthDomain() string
|
|
SetAuthDomain(string)
|
|
GetAuthClientID() string
|
|
SetAuthClientID(string)
|
|
|
|
// Non-env fields
|
|
GetAuthRedirectURI() string
|
|
SetAuthRedirectURI(string)
|
|
GetAuthTokenURL() string
|
|
SetAuthTokenURL(string)
|
|
GetAuthJwksURL() string
|
|
SetAuthJwksURL(string)
|
|
GetAuthURL() string
|
|
SetAuthURL(string)
|
|
GetAuthLoginPath() string
|
|
SetAuthLoginPath(string)
|
|
GetAuthCallbackPath() string
|
|
SetAuthCallbackPath(string)
|
|
GetAuthHomePath() string
|
|
SetAuthHomePath(string)
|
|
GetAuthLogoutPath() string
|
|
SetAuthLogoutPath(string)
|
|
GetAuthLogger() *slog.Logger
|
|
SetAuthLogger(*slog.Logger)
|
|
GetAuthRoutePermissions() map[string][]string
|
|
SetAuthRoutePermissions(map[string][]string)
|
|
|
|
// Initialize method
|
|
InitializeAuthConfig(baseURL string, logger *slog.Logger) error
|
|
}
|
|
|
|
// InitializeAuthConfig initializes the receiver CognitoConfig instance with values from a newly created config.
|
|
// It takes a baseURL string used for redirect URI construction and a logger instance for logging operations.
|
|
// The function creates a temporary config using InitializeConfig() and copies all fields to the receiver using reflection.
|
|
// Returns an error if initialization fails, nil otherwise.
|
|
func (c *CognitoConfig) InitializeAuthConfig(baseURL string, logger *slog.Logger) error {
|
|
tempConfig := InitializeConfig(baseURL, logger)
|
|
//fmt.Printf("base url after InitializeAuthConfig: %s\n", tempConfig.)
|
|
if tempConfig == nil {
|
|
return fmt.Errorf("could not initialize auth config")
|
|
}
|
|
|
|
// Use reflection to copy all fields
|
|
dst := reflect.ValueOf(c).Elem()
|
|
src := reflect.ValueOf(tempConfig).Elem()
|
|
|
|
for i := 0; i < src.NumField(); i++ {
|
|
dstField := dst.Field(i)
|
|
srcField := src.Field(i)
|
|
|
|
if dstField.CanSet() {
|
|
dstField.Set(srcField)
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// InitializeConfig creates a new CognitoConfig from environment variables
|
|
// and sets the values that are computed from other values and
|
|
// sets all default values for fields that will infrequently change.
|
|
func InitializeConfig(baseURL string, logger *slog.Logger) *CognitoConfig {
|
|
|
|
// Set default logger to text slog if not provided
|
|
if logger == nil {
|
|
var logLevel slog.Level
|
|
if os.Getenv("DEBUG") == "true" {
|
|
logLevel = slog.LevelDebug
|
|
} else {
|
|
logLevel = slog.LevelInfo
|
|
}
|
|
|
|
logHandler := slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{
|
|
Level: logLevel,
|
|
})
|
|
logger = slog.New(logHandler)
|
|
}
|
|
|
|
// Sanitize base URL (remove trailing slash)
|
|
baseURL = strings.TrimSuffix(baseURL, "/")
|
|
|
|
tempConfig := &CognitoConfig{}
|
|
errorParsingCognitoConfig := env.Parse(tempConfig)
|
|
if errorParsingCognitoConfig != nil {
|
|
logger.Error("Error parsing Cognito config", "error", errorParsingCognitoConfig)
|
|
return nil
|
|
}
|
|
|
|
tempConfig.AuthRedirectURI = baseURL + tempConfig.AuthCallbackPath
|
|
tempConfig.AuthRedirectURI = baseURL + tempConfig.AuthCallbackPath
|
|
tempConfig.AuthTokenURL = fmt.Sprintf("%s/oauth2/token", tempConfig.AuthDomain)
|
|
tempConfig.AuthURL = fmt.Sprintf("%s/oauth2/authorize", tempConfig.AuthDomain)
|
|
tempConfig.AuthJwksURL = fmt.Sprintf("https://cognito-idp.%s.amazonaws.com/%s/.well-known/jwks.json",
|
|
tempConfig.AuthRegion,
|
|
tempConfig.AuthUserPoolID)
|
|
tempConfig.AuthLogger = logger
|
|
tempConfig.AuthRoutePermissions = make(map[string][]string)
|
|
|
|
tempConfig.PrettyPrintDebugOnly()
|
|
return tempConfig
|
|
}
|
|
|
|
func (c *CognitoConfig) PrettyPrintDebugOnly() {
|
|
logger := c.AuthLogger
|
|
if logger != nil {
|
|
logger.Debug("CognitoConfig details",
|
|
"AuthClientID", c.AuthClientID,
|
|
"AuthClientSecret", c.AuthClientSecret,
|
|
"AuthRedirectURI", c.AuthRedirectURI,
|
|
"AuthTokenURL", c.AuthTokenURL,
|
|
"AuthURL", c.AuthURL,
|
|
"AuthJwksURL", c.AuthJwksURL,
|
|
"AuthUserPoolID", c.AuthUserPoolID,
|
|
"AuthRegion", c.AuthRegion,
|
|
"AuthLoginPath", c.AuthLoginPath,
|
|
"AuthCallbackPath", c.AuthCallbackPath,
|
|
"AuthHomePath", c.AuthHomePath,
|
|
"AuthLogoutPath", c.AuthLogoutPath,
|
|
"DisableAuth", c.DisableAuth,
|
|
"AuthDomain", c.AuthDomain)
|
|
|
|
// pretty print the route permissions map
|
|
for route, permissions := range c.AuthRoutePermissions {
|
|
logger.Debug("Route permission",
|
|
"route", route,
|
|
"permissions", permissions)
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
func (c *CognitoConfig) GetAuthRegion() string {
|
|
return c.AuthRegion
|
|
}
|
|
|
|
func (c *CognitoConfig) SetAuthRegion(val string) {
|
|
c.AuthRegion = val
|
|
}
|
|
|
|
func (c *CognitoConfig) GetAuthUserPoolID() string {
|
|
return c.AuthUserPoolID
|
|
}
|
|
|
|
func (c *CognitoConfig) SetAuthUserPoolID(val string) {
|
|
c.AuthUserPoolID = val
|
|
}
|
|
|
|
func (c *CognitoConfig) GetAuthClientSecret() string {
|
|
return c.AuthClientSecret
|
|
}
|
|
|
|
func (c *CognitoConfig) SetAuthClientSecret(val string) {
|
|
c.AuthClientSecret = val
|
|
}
|
|
|
|
func (c *CognitoConfig) GetAuthDomain() string {
|
|
return c.AuthDomain
|
|
}
|
|
|
|
func (c *CognitoConfig) SetAuthDomain(val string) {
|
|
c.AuthDomain = val
|
|
}
|
|
|
|
func (c *CognitoConfig) GetAuthClientID() string {
|
|
return c.AuthClientID
|
|
}
|
|
|
|
func (c *CognitoConfig) SetAuthClientID(val string) {
|
|
c.AuthClientID = val
|
|
}
|
|
|
|
func (c *CognitoConfig) GetAuthRedirectURI() string {
|
|
return c.AuthRedirectURI
|
|
}
|
|
|
|
func (c *CognitoConfig) SetAuthRedirectURI(val string) {
|
|
c.AuthRedirectURI = val
|
|
}
|
|
|
|
func (c *CognitoConfig) GetAuthTokenURL() string {
|
|
return c.AuthTokenURL
|
|
}
|
|
|
|
func (c *CognitoConfig) SetAuthTokenURL(val string) {
|
|
c.AuthTokenURL = val
|
|
}
|
|
|
|
func (c *CognitoConfig) GetAuthJwksURL() string {
|
|
return c.AuthJwksURL
|
|
}
|
|
|
|
func (c *CognitoConfig) SetAuthJwksURL(val string) {
|
|
c.AuthJwksURL = val
|
|
}
|
|
|
|
func (c *CognitoConfig) GetAuthURL() string {
|
|
return c.AuthURL
|
|
}
|
|
|
|
func (c *CognitoConfig) SetAuthURL(val string) {
|
|
c.AuthURL = val
|
|
}
|
|
|
|
func (c *CognitoConfig) GetAuthLoginPath() string {
|
|
return c.AuthLoginPath
|
|
}
|
|
|
|
func (c *CognitoConfig) SetAuthLoginPath(val string) {
|
|
c.AuthLoginPath = val
|
|
}
|
|
|
|
func (c *CognitoConfig) GetAuthCallbackPath() string {
|
|
return c.AuthCallbackPath
|
|
}
|
|
|
|
func (c *CognitoConfig) SetAuthCallbackPath(val string) {
|
|
c.AuthCallbackPath = val
|
|
}
|
|
|
|
func (c *CognitoConfig) GetAuthHomePath() string {
|
|
return c.AuthHomePath
|
|
}
|
|
|
|
func (c *CognitoConfig) SetAuthHomePath(val string) {
|
|
c.AuthHomePath = val
|
|
}
|
|
|
|
func (c *CognitoConfig) GetAuthLogoutPath() string {
|
|
return c.AuthLogoutPath
|
|
}
|
|
|
|
func (c *CognitoConfig) SetAuthLogoutPath(val string) {
|
|
c.AuthLogoutPath = val
|
|
}
|
|
|
|
func (c *CognitoConfig) GetAuthLogger() *slog.Logger {
|
|
return c.AuthLogger
|
|
}
|
|
|
|
func (c *CognitoConfig) SetAuthLogger(val *slog.Logger) {
|
|
c.AuthLogger = val
|
|
}
|
|
|
|
func (c *CognitoConfig) GetAuthRoutePermissions() map[string][]string {
|
|
return c.AuthRoutePermissions
|
|
}
|
|
|
|
func (c *CognitoConfig) SetAuthRoutePermissions(val map[string][]string) {
|
|
c.AuthRoutePermissions = val
|
|
}
|