mirror of https://github.com/h44z/wg-portal.git
				
				
				
			Enable allowed_domains in oauth and oidc providers (#416)
* Enable allowed_domains in oauth and oidc providers Signed-off-by: Vladimir DOMBROVSKI <vladimir.dombrovski@bso.co> * Domain check code cleanup * Run gofmt on domain validation code --------- Signed-off-by: Vladimir DOMBROVSKI <vladimir.dombrovski@bso.co>
This commit is contained in:
		
							parent
							
								
									d8a57edef9
								
							
						
					
					
						commit
						3eb84f0ee9
					
				|  | @ -63,6 +63,8 @@ type AuthenticatorOauth interface { | ||||||
| 	ParseUserInfo(raw map[string]any) (*domain.AuthenticatorUserInfo, error) | 	ParseUserInfo(raw map[string]any) (*domain.AuthenticatorUserInfo, error) | ||||||
| 	// RegistrationEnabled returns whether registration is enabled for the OAuth authenticator.
 | 	// RegistrationEnabled returns whether registration is enabled for the OAuth authenticator.
 | ||||||
| 	RegistrationEnabled() bool | 	RegistrationEnabled() bool | ||||||
|  | 	// GetAllowedDomains returns the list of whitelisted domains
 | ||||||
|  | 	GetAllowedDomains() []string | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // AuthenticatorLdap is the interface for all LDAP authenticators.
 | // AuthenticatorLdap is the interface for all LDAP authenticators.
 | ||||||
|  | @ -392,6 +394,23 @@ func (a *Authenticator) randString(nByte int) (string, error) { | ||||||
| 	return base64.RawURLEncoding.EncodeToString(b), nil | 	return base64.RawURLEncoding.EncodeToString(b), nil | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | func isDomainAllowed(email string, allowedDomains []string) bool { | ||||||
|  | 	if len(allowedDomains) == 0 { | ||||||
|  | 		return true | ||||||
|  | 	} | ||||||
|  | 	parts := strings.Split(email, "@") | ||||||
|  | 	if len(parts) != 2 { | ||||||
|  | 		return false | ||||||
|  | 	} | ||||||
|  | 	domain := strings.ToLower(parts[1]) | ||||||
|  | 	for _, allowed := range allowedDomains { | ||||||
|  | 		if domain == strings.ToLower(allowed) { | ||||||
|  | 			return true | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	return false | ||||||
|  | } | ||||||
|  | 
 | ||||||
| // OauthLoginStep2 finishes the oauth authentication flow by exchanging the code for an access token and
 | // OauthLoginStep2 finishes the oauth authentication flow by exchanging the code for an access token and
 | ||||||
| // fetching the user information.
 | // fetching the user information.
 | ||||||
| func (a *Authenticator) OauthLoginStep2(ctx context.Context, providerId, nonce, code string) (*domain.User, error) { | func (a *Authenticator) OauthLoginStep2(ctx context.Context, providerId, nonce, code string) (*domain.User, error) { | ||||||
|  | @ -431,6 +450,10 @@ func (a *Authenticator) OauthLoginStep2(ctx context.Context, providerId, nonce, | ||||||
| 		return nil, fmt.Errorf("unable to process user information: %w", err) | 		return nil, fmt.Errorf("unable to process user information: %w", err) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	if !isDomainAllowed(userInfo.Email, oauthProvider.GetAllowedDomains()) { | ||||||
|  | 		return nil, fmt.Errorf("user is not in allowed domains: %w", err) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	if user.IsLocked() || user.IsDisabled() { | 	if user.IsLocked() || user.IsDisabled() { | ||||||
| 		a.bus.Publish(app.TopicAuditLoginFailed, domain.AuditEventWrapper[audit.AuthEvent]{ | 		a.bus.Publish(app.TopicAuditLoginFailed, domain.AuditEventWrapper[audit.AuthEvent]{ | ||||||
| 			Ctx:    ctx, | 			Ctx:    ctx, | ||||||
|  |  | ||||||
|  | @ -27,6 +27,7 @@ type PlainOauthAuthenticator struct { | ||||||
| 	userAdminMapping    *config.OauthAdminMapping | 	userAdminMapping    *config.OauthAdminMapping | ||||||
| 	registrationEnabled bool | 	registrationEnabled bool | ||||||
| 	userInfoLogging     bool | 	userInfoLogging     bool | ||||||
|  | 	allowedDomains      []string | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func newPlainOauthAuthenticator( | func newPlainOauthAuthenticator( | ||||||
|  | @ -56,6 +57,7 @@ func newPlainOauthAuthenticator( | ||||||
| 	provider.userAdminMapping = &cfg.AdminMapping | 	provider.userAdminMapping = &cfg.AdminMapping | ||||||
| 	provider.registrationEnabled = cfg.RegistrationEnabled | 	provider.registrationEnabled = cfg.RegistrationEnabled | ||||||
| 	provider.userInfoLogging = cfg.LogUserInfo | 	provider.userInfoLogging = cfg.LogUserInfo | ||||||
|  | 	provider.allowedDomains = cfg.AllowedDomains | ||||||
| 
 | 
 | ||||||
| 	return provider, nil | 	return provider, nil | ||||||
| } | } | ||||||
|  | @ -65,6 +67,10 @@ func (p PlainOauthAuthenticator) GetName() string { | ||||||
| 	return p.name | 	return p.name | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | func (p PlainOauthAuthenticator) GetAllowedDomains() []string { | ||||||
|  | 	return p.allowedDomains | ||||||
|  | } | ||||||
|  | 
 | ||||||
| // RegistrationEnabled returns whether registration is enabled for the OAuth authenticator.
 | // RegistrationEnabled returns whether registration is enabled for the OAuth authenticator.
 | ||||||
| func (p PlainOauthAuthenticator) RegistrationEnabled() bool { | func (p PlainOauthAuthenticator) RegistrationEnabled() bool { | ||||||
| 	return p.registrationEnabled | 	return p.registrationEnabled | ||||||
|  |  | ||||||
|  | @ -24,6 +24,7 @@ type OidcAuthenticator struct { | ||||||
| 	userAdminMapping    *config.OauthAdminMapping | 	userAdminMapping    *config.OauthAdminMapping | ||||||
| 	registrationEnabled bool | 	registrationEnabled bool | ||||||
| 	userInfoLogging     bool | 	userInfoLogging     bool | ||||||
|  | 	allowedDomains      []string | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func newOidcAuthenticator( | func newOidcAuthenticator( | ||||||
|  | @ -57,6 +58,7 @@ func newOidcAuthenticator( | ||||||
| 	provider.userAdminMapping = &cfg.AdminMapping | 	provider.userAdminMapping = &cfg.AdminMapping | ||||||
| 	provider.registrationEnabled = cfg.RegistrationEnabled | 	provider.registrationEnabled = cfg.RegistrationEnabled | ||||||
| 	provider.userInfoLogging = cfg.LogUserInfo | 	provider.userInfoLogging = cfg.LogUserInfo | ||||||
|  | 	provider.allowedDomains = cfg.AllowedDomains | ||||||
| 
 | 
 | ||||||
| 	return provider, nil | 	return provider, nil | ||||||
| } | } | ||||||
|  | @ -66,6 +68,10 @@ func (o OidcAuthenticator) GetName() string { | ||||||
| 	return o.name | 	return o.name | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | func (o OidcAuthenticator) GetAllowedDomains() []string { | ||||||
|  | 	return o.allowedDomains | ||||||
|  | } | ||||||
|  | 
 | ||||||
| // RegistrationEnabled returns whether registration is enabled for this authenticator.
 | // RegistrationEnabled returns whether registration is enabled for this authenticator.
 | ||||||
| func (o OidcAuthenticator) RegistrationEnabled() bool { | func (o OidcAuthenticator) RegistrationEnabled() bool { | ||||||
| 	return o.registrationEnabled | 	return o.registrationEnabled | ||||||
|  |  | ||||||
|  | @ -188,6 +188,9 @@ type OpenIDConnectProvider struct { | ||||||
| 	// ExtraScopes specifies optional requested permissions.
 | 	// ExtraScopes specifies optional requested permissions.
 | ||||||
| 	ExtraScopes []string `yaml:"extra_scopes"` | 	ExtraScopes []string `yaml:"extra_scopes"` | ||||||
| 
 | 
 | ||||||
|  | 	// AllowedDomains defines the list of allowed domains
 | ||||||
|  | 	AllowedDomains []string `yaml:"allowed_domains"` | ||||||
|  | 
 | ||||||
| 	// FieldMap is used to map the names of the user-info endpoint fields to wg-portal fields
 | 	// FieldMap is used to map the names of the user-info endpoint fields to wg-portal fields
 | ||||||
| 	FieldMap OauthFields `yaml:"field_map"` | 	FieldMap OauthFields `yaml:"field_map"` | ||||||
| 
 | 
 | ||||||
|  | @ -226,6 +229,9 @@ type OAuthProvider struct { | ||||||
| 	// Scope specifies optional requested permissions.
 | 	// Scope specifies optional requested permissions.
 | ||||||
| 	Scopes []string `yaml:"scopes"` | 	Scopes []string `yaml:"scopes"` | ||||||
| 
 | 
 | ||||||
|  | 	// AllowedDomains defines the list of allowed domains
 | ||||||
|  | 	AllowedDomains []string `yaml:"allowed_domains"` | ||||||
|  | 
 | ||||||
| 	// FieldMap is used to map the names of the user-info endpoint fields to wg-portal fields
 | 	// FieldMap is used to map the names of the user-info endpoint fields to wg-portal fields
 | ||||||
| 	FieldMap OauthFields `yaml:"field_map"` | 	FieldMap OauthFields `yaml:"field_map"` | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue