Added validation of configured acr values
(cherry picked from commit 0a5d74a7bb13554a41eaba3b7505d508fb53970a)
This commit is contained in:
		
							parent
							
								
									4c823a66c7
								
							
						
					
					
						commit
						012c155d2a
					
				|  | @ -25,6 +25,7 @@ func CreateTokenToSessionFunc(verify VerifyFunc) TokenToSessionFunc { | ||||||
| 			Verified          *bool    `json:"email_verified"` | 			Verified          *bool    `json:"email_verified"` | ||||||
| 			PreferredUsername string   `json:"preferred_username"` | 			PreferredUsername string   `json:"preferred_username"` | ||||||
| 			Groups            []string `json:"groups"` | 			Groups            []string `json:"groups"` | ||||||
|  | 			Acr               string   `json:"acr"` | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		idToken, err := verify(ctx, token) | 		idToken, err := verify(ctx, token) | ||||||
|  | @ -49,6 +50,7 @@ func CreateTokenToSessionFunc(verify VerifyFunc) TokenToSessionFunc { | ||||||
| 			User:              claims.Subject, | 			User:              claims.Subject, | ||||||
| 			Groups:            claims.Groups, | 			Groups:            claims.Groups, | ||||||
| 			PreferredUsername: claims.PreferredUsername, | 			PreferredUsername: claims.PreferredUsername, | ||||||
|  | 			Acr:               claims.Acr, | ||||||
| 			AccessToken:       token, | 			AccessToken:       token, | ||||||
| 			IDToken:           token, | 			IDToken:           token, | ||||||
| 			RefreshToken:      "", | 			RefreshToken:      "", | ||||||
|  |  | ||||||
|  | @ -727,6 +727,7 @@ func (l *LegacyProvider) convert() (Providers, error) { | ||||||
| 		provider.KeycloakConfig = KeycloakOptions{ | 		provider.KeycloakConfig = KeycloakOptions{ | ||||||
| 			Groups: l.KeycloakGroups, | 			Groups: l.KeycloakGroups, | ||||||
| 			Roles:  l.AllowedRoles, | 			Roles:  l.AllowedRoles, | ||||||
|  | 			ACRs:   l.AcrValues, | ||||||
| 		} | 		} | ||||||
| 	case "keycloak": | 	case "keycloak": | ||||||
| 		provider.KeycloakConfig = KeycloakOptions{ | 		provider.KeycloakConfig = KeycloakOptions{ | ||||||
|  |  | ||||||
|  | @ -149,6 +149,7 @@ type KeycloakOptions struct { | ||||||
| 
 | 
 | ||||||
| 	// Role enables to restrict login to users with role (only available when using the keycloak-oidc provider)
 | 	// Role enables to restrict login to users with role (only available when using the keycloak-oidc provider)
 | ||||||
| 	Roles []string `json:"roles,omitempty"` | 	Roles []string `json:"roles,omitempty"` | ||||||
|  | 	ACRs  string   `json:"acr,omitempty"` | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| type AzureOptions struct { | type AzureOptions struct { | ||||||
|  |  | ||||||
|  | @ -28,6 +28,7 @@ type SessionState struct { | ||||||
| 	User              string   `msgpack:"u,omitempty"` | 	User              string   `msgpack:"u,omitempty"` | ||||||
| 	Groups            []string `msgpack:"g,omitempty"` | 	Groups            []string `msgpack:"g,omitempty"` | ||||||
| 	PreferredUsername string   `msgpack:"pu,omitempty"` | 	PreferredUsername string   `msgpack:"pu,omitempty"` | ||||||
|  | 	Acr               string   `msgpack:"acr,omitempty"` | ||||||
| 
 | 
 | ||||||
| 	// Internal helpers, not serialized
 | 	// Internal helpers, not serialized
 | ||||||
| 	Clock clock.Clock `msgpack:"-"` | 	Clock clock.Clock `msgpack:"-"` | ||||||
|  | @ -148,6 +149,8 @@ func (s *SessionState) GetClaim(claim string) []string { | ||||||
| 		return groups | 		return groups | ||||||
| 	case "preferred_username": | 	case "preferred_username": | ||||||
| 		return []string{s.PreferredUsername} | 		return []string{s.PreferredUsername} | ||||||
|  | 	case "acr": | ||||||
|  | 		return []string{s.Acr} | ||||||
| 	default: | 	default: | ||||||
| 		return []string{} | 		return []string{} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | @ -61,6 +61,7 @@ func NewKeycloakProvider(p *ProviderData, opts options.KeycloakOptions) *Keycloa | ||||||
| 
 | 
 | ||||||
| 	provider := &KeycloakProvider{ProviderData: p} | 	provider := &KeycloakProvider{ProviderData: p} | ||||||
| 	provider.setAllowedGroups(opts.Groups) | 	provider.setAllowedGroups(opts.Groups) | ||||||
|  | 	provider.setAllowedACR(opts.ACRs) | ||||||
| 	return provider | 	return provider | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -26,6 +26,7 @@ func NewKeycloakOIDCProvider(p *ProviderData, opts options.Provider) *KeycloakOI | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	provider.addAllowedRoles(opts.KeycloakConfig.Roles) | 	provider.addAllowedRoles(opts.KeycloakConfig.Roles) | ||||||
|  | 	provider.setAllowedACR(opts.KeycloakConfig.ACRs) | ||||||
| 	return provider | 	return provider | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -53,6 +53,7 @@ type ProviderData struct { | ||||||
| 	// Universal Group authorization data structure
 | 	// Universal Group authorization data structure
 | ||||||
| 	// any provider can set to consume
 | 	// any provider can set to consume
 | ||||||
| 	AllowedGroups map[string]struct{} | 	AllowedGroups map[string]struct{} | ||||||
|  | 	AllowedACRs   map[string]struct{} | ||||||
| 
 | 
 | ||||||
| 	getAuthorizationHeaderFunc func(string) http.Header | 	getAuthorizationHeaderFunc func(string) http.Header | ||||||
| 	loginURLParameterDefaults  url.Values | 	loginURLParameterDefaults  url.Values | ||||||
|  | @ -181,6 +182,14 @@ func (p *ProviderData) setAllowedGroups(groups []string) { | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | func (p *ProviderData) setAllowedACR(acrs string) { | ||||||
|  | 	p.AllowedACRs = make(map[string]struct{}) | ||||||
|  | 	var resultingACRs = strings.Split(acrs, ",") | ||||||
|  | 	for _, acr := range resultingACRs { | ||||||
|  | 		p.AllowedACRs[acr] = struct{}{} | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
| type providerDefaults struct { | type providerDefaults struct { | ||||||
| 	name        string | 	name        string | ||||||
| 	loginURL    *url.URL | 	loginURL    *url.URL | ||||||
|  | @ -258,6 +267,7 @@ func (p *ProviderData) buildSessionFromClaims(rawIDToken, accessToken string) (* | ||||||
| 		{p.UserClaim, &ss.User}, | 		{p.UserClaim, &ss.User}, | ||||||
| 		{p.EmailClaim, &ss.Email}, | 		{p.EmailClaim, &ss.Email}, | ||||||
| 		{p.GroupsClaim, &ss.Groups}, | 		{p.GroupsClaim, &ss.Groups}, | ||||||
|  | 		{"acr", &ss.Acr}, | ||||||
| 		// TODO (@NickMeves) Deprecate for dynamic claim to session mapping
 | 		// TODO (@NickMeves) Deprecate for dynamic claim to session mapping
 | ||||||
| 		{"preferred_username", &ss.PreferredUsername}, | 		{"preferred_username", &ss.PreferredUsername}, | ||||||
| 	} { | 	} { | ||||||
|  |  | ||||||
|  | @ -3,6 +3,7 @@ package providers | ||||||
| import ( | import ( | ||||||
| 	"bytes" | 	"bytes" | ||||||
| 	"context" | 	"context" | ||||||
|  | 	"encoding/json" | ||||||
| 	"errors" | 	"errors" | ||||||
| 	"fmt" | 	"fmt" | ||||||
| 	"net/url" | 	"net/url" | ||||||
|  | @ -116,6 +117,16 @@ func (p *ProviderData) EnrichSession(_ context.Context, _ *sessions.SessionState | ||||||
| // Authorize performs global authorization on an authenticated session.
 | // Authorize performs global authorization on an authenticated session.
 | ||||||
| // This is not used for fine-grained per route authorization rules.
 | // This is not used for fine-grained per route authorization rules.
 | ||||||
| func (p *ProviderData) Authorize(_ context.Context, s *sessions.SessionState) (bool, error) { | func (p *ProviderData) Authorize(_ context.Context, s *sessions.SessionState) (bool, error) { | ||||||
|  | 	println("ACR level is", s.Acr) | ||||||
|  | 	bs, _ := json.Marshal(p.AllowedACRs) | ||||||
|  | 	fmt.Println("Current configured acr is", string(bs)) | ||||||
|  | 	if len(p.AllowedACRs) > 0 { | ||||||
|  | 		var _, ok = p.AllowedACRs[s.Acr] | ||||||
|  | 		if !ok { | ||||||
|  | 			return false, nil | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	if len(p.AllowedGroups) == 0 { | 	if len(p.AllowedGroups) == 0 { | ||||||
| 		return true, nil | 		return true, nil | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue