diff --git a/pkg/authn/authproxy_basic_auth.go b/pkg/authn/authproxy_basic_auth.go index 9a5f7cc..35eb743 100644 --- a/pkg/authn/authproxy_basic_auth.go +++ b/pkg/authn/authproxy_basic_auth.go @@ -17,14 +17,15 @@ package authn import ( "context" "encoding/base64" + "strings" + "time" + "github.com/greenpau/go-authcrunch/pkg/authn/enums/operator" "github.com/greenpau/go-authcrunch/pkg/authproxy" "github.com/greenpau/go-authcrunch/pkg/errors" "github.com/greenpau/go-authcrunch/pkg/requests" "github.com/greenpau/go-authcrunch/pkg/user" "go.uber.org/zap" - "strings" - "time" ) // BasicAuth performs API key authentication. @@ -148,7 +149,7 @@ func (p *Portal) BasicAuth(r *authproxy.Request) error { } // Inject portal specific roles - injectPortalRoles(m) + injectPortalRoles(m, p.config) // Create a new user and sign the token. usr, err := user.NewUser(m) diff --git a/pkg/authn/config.go b/pkg/authn/config.go index 959664e..60e5851 100644 --- a/pkg/authn/config.go +++ b/pkg/authn/config.go @@ -16,6 +16,7 @@ package authn import ( "regexp" + "slices" "strings" "github.com/greenpau/go-authcrunch/pkg/acl" @@ -29,6 +30,12 @@ import ( cfgutil "github.com/greenpau/go-authcrunch/pkg/util/cfg" ) +const ( + defaultGuestRoleName = "authp/guest" + defaultUserRoleName = "authp/user" + defaultAdminRoleName = "authp/admin" +) + // PortalConfig represents Portal configuration. type PortalConfig struct { Name string `json:"name,omitempty" xml:"name,omitempty" yaml:"name,omitempty"` @@ -75,7 +82,8 @@ type PortalConfig struct { // PortalGuestRolePatterns holds the list of regular expressions for the role names without admin or user privileges in the portal. PortalGuestRolePatterns []string `json:"portal_guest_role_patterns,omitempty" xml:"portal_guest_role_patterns,omitempty" yaml:"portal_guest_role_patterns,omitempty"` guestRolePatterns []*regexp.Regexp - + reservedPortalRoles map[string]interface{} + guestPortalRoles []string // API holds the configuration for API endpoints. API *APIConfig `json:"api,omitempty" xml:"api,omitempty" yaml:"api,omitempty"` @@ -134,27 +142,51 @@ func (cfg *PortalConfig) parseRawCryptoConfigs() error { return nil } +// GetReservedPortalRoles returns the names of reserved portal roles. +func (cfg *PortalConfig) GetReservedPortalRoles() map[string]interface{} { + if cfg.reservedPortalRoles == nil { + cfg.parsePortalRoles() + } + return cfg.reservedPortalRoles +} + +// GetGuestPortalRoles returns the names of guest portal roles. +func (cfg *PortalConfig) GetGuestPortalRoles() []string { + return cfg.guestPortalRoles +} + // parsePortalRoles validates the configuration of portal roles. func (cfg *PortalConfig) parsePortalRoles() error { + if cfg.reservedPortalRoles == nil { + cfg.reservedPortalRoles = make(map[string]interface{}) + } + if cfg.PortalAdminRoles == nil { cfg.PortalAdminRoles = make(map[string]interface{}) } if len(cfg.PortalAdminRoles) < 1 { - cfg.PortalAdminRoles["authp/admin"] = true + cfg.PortalAdminRoles[defaultAdminRoleName] = true + cfg.reservedPortalRoles[defaultAdminRoleName] = true } if cfg.PortalUserRoles == nil { cfg.PortalUserRoles = make(map[string]interface{}) } if len(cfg.PortalUserRoles) < 1 { - cfg.PortalUserRoles["authp/user"] = true + cfg.PortalUserRoles[defaultUserRoleName] = true + cfg.reservedPortalRoles[defaultUserRoleName] = true } if cfg.PortalGuestRoles == nil { cfg.PortalGuestRoles = make(map[string]interface{}) + cfg.reservedPortalRoles[defaultGuestRoleName] = true } if len(cfg.PortalGuestRoles) < 1 { - cfg.PortalGuestRoles["authp/guest"] = true + cfg.PortalGuestRoles[defaultGuestRoleName] = true + } + + if slices.Contains(cfg.guestPortalRoles, defaultGuestRoleName) { + cfg.guestPortalRoles = append(cfg.guestPortalRoles, defaultGuestRoleName) } for _, ptrn := range cfg.PortalAdminRolePatterns { diff --git a/pkg/authn/handle_api_profile.go b/pkg/authn/handle_api_profile.go index 46c7864..a96dfc6 100644 --- a/pkg/authn/handle_api_profile.go +++ b/pkg/authn/handle_api_profile.go @@ -22,6 +22,7 @@ import ( "net/http" "time" + "github.com/greenpau/go-authcrunch/pkg/authn/enums/role" "github.com/greenpau/go-authcrunch/pkg/requests" "regexp" @@ -68,7 +69,7 @@ func (p *Portal) handleAPIProfile(ctx context.Context, w http.ResponseWriter, r return handleAPIProfileResponse(w, rr, http.StatusUnauthorized, resp) } - if permitted := usr.HasRole("authp/admin", "authp/user"); !permitted { + if err := p.authorizedRole(usr, []role.Kind{role.Admin, role.User}, rr.Response.Authenticated); err != nil { resp["message"] = "Profile API did not find valid role for the user" return handleAPIProfileResponse(w, rr, http.StatusForbidden, resp) } diff --git a/pkg/authn/handle_http_login.go b/pkg/authn/handle_http_login.go index 9739df0..55265ae 100644 --- a/pkg/authn/handle_http_login.go +++ b/pkg/authn/handle_http_login.go @@ -17,6 +17,12 @@ package authn import ( "context" "fmt" + "net/http" + "net/url" + "path" + "strings" + "time" + "github.com/greenpau/go-authcrunch/pkg/authn/enums/operator" "github.com/greenpau/go-authcrunch/pkg/idp" "github.com/greenpau/go-authcrunch/pkg/ids" @@ -25,11 +31,6 @@ import ( "github.com/greenpau/go-authcrunch/pkg/util" addrutil "github.com/greenpau/go-authcrunch/pkg/util/addr" "go.uber.org/zap" - "net/http" - "net/url" - "path" - "strings" - "time" ) func (p *Portal) handleHTTPLogin(ctx context.Context, w http.ResponseWriter, r *http.Request, rr *requests.Request, usr *user.User) error { @@ -148,7 +149,7 @@ func (p *Portal) handleHTTPLoginRequest(ctx context.Context, w http.ResponseWrit } // Inject portal-specific roles. - injectPortalRoles(m) + injectPortalRoles(m, p.config) usr, err := user.NewUser(m) if err != nil { rr.Response.Code = http.StatusBadRequest @@ -329,7 +330,7 @@ func (p *Portal) authorizeLoginRequest(ctx context.Context, w http.ResponseWrite if err := p.transformUser(ctx, rr, m); err != nil { return err } - injectPortalRoles(m) + injectPortalRoles(m, p.config) usr, err := user.NewUser(m) if err != nil { rr.Response.Code = http.StatusUnauthorized @@ -480,19 +481,19 @@ func combineGroupRoles(m map[string]interface{}) { } } -func injectPortalRoles(m map[string]interface{}) { +func injectPortalRoles(m map[string]interface{}, cfg *PortalConfig) { var roles, updatedRoles []string var reservedRoleFound bool roleMap := make(map[string]bool) - reservedRoles := map[string]bool{ - "authp/admin": false, - "authp/user": false, - "authp/guest": false, - } + reservedRoles := cfg.GetReservedPortalRoles() v, exists := m["roles"] if !exists { - m["roles"] = []string{"authp/guest"} + guestRoles := []string{} + for _, roleName := range cfg.GetGuestPortalRoles() { + guestRoles = append(guestRoles, roleName) + } + m["roles"] = guestRoles return } switch val := v.(type) { @@ -524,7 +525,7 @@ func injectPortalRoles(m map[string]interface{}) { updatedRoles = append(updatedRoles, roleName) } if !reservedRoleFound { - updatedRoles = append(updatedRoles, "authp/guest") + updatedRoles = append(updatedRoles, defaultGuestRoleName) } m["roles"] = updatedRoles return diff --git a/pkg/authn/handle_register.go b/pkg/authn/handle_register.go index c65a97b..87f7352 100644 --- a/pkg/authn/handle_register.go +++ b/pkg/authn/handle_register.go @@ -16,15 +16,16 @@ package authn import ( "context" + "net/http" + "path" + "strings" + "time" + "github.com/greenpau/go-authcrunch/pkg/authn/validators" "github.com/greenpau/go-authcrunch/pkg/requests" "github.com/greenpau/go-authcrunch/pkg/util" addrutil "github.com/greenpau/go-authcrunch/pkg/util/addr" "go.uber.org/zap" - "net/http" - "path" - "strings" - "time" ) type registerRequest struct { @@ -393,7 +394,7 @@ func (p *Portal) handleHTTPRegisterAckRequest(ctx context.Context, w http.Respon Username: usr["username"], Password: usr["password"], Email: usr["email"], - Roles: []string{"authp/user"}, + Roles: []string{defaultUserRoleName}, }, Query: requests.Query{ ID: registrationID, diff --git a/pkg/authn/idp_apikey_auth.go b/pkg/authn/idp_apikey_auth.go index 6eff75a..30f9a19 100644 --- a/pkg/authn/idp_apikey_auth.go +++ b/pkg/authn/idp_apikey_auth.go @@ -16,13 +16,14 @@ package authn import ( "context" + "time" + "github.com/greenpau/go-authcrunch/pkg/authn/enums/operator" "github.com/greenpau/go-authcrunch/pkg/authproxy" "github.com/greenpau/go-authcrunch/pkg/errors" "github.com/greenpau/go-authcrunch/pkg/requests" "github.com/greenpau/go-authcrunch/pkg/user" "go.uber.org/zap" - "time" ) // APIKeyAuth performs API key authentication. @@ -96,7 +97,7 @@ func (p *Portal) APIKeyAuth(r *authproxy.Request) error { } // Inject portal specific roles - injectPortalRoles(m) + injectPortalRoles(m, p.config) // Create a new user and sign the token. usr, err := user.NewUser(m) diff --git a/pkg/ids/local/authenticator.go b/pkg/ids/local/authenticator.go index b920521..a7d8905 100644 --- a/pkg/ids/local/authenticator.go +++ b/pkg/ids/local/authenticator.go @@ -24,6 +24,10 @@ import ( "go.uber.org/zap" ) +const ( + defaultAdminRoleName = "authp/admin" +) + // Authenticator represents database connector. type Authenticator struct { db *identity.Database @@ -109,7 +113,7 @@ func (sa *Authenticator) Configure(fp string, users []*User) error { Username: os.Getenv("AUTHP_ADMIN_USER"), Password: os.Getenv("AUTHP_ADMIN_SECRET"), Email: os.Getenv("AUTHP_ADMIN_EMAIL"), - Roles: []string{"authp/admin"}, + Roles: []string{defaultAdminRoleName}, }, }