mirror of
https://github.com/oauth2-proxy/oauth2-proxy.git
synced 2026-10-21 10:17:22 +02:00
feat: added organizationId/employee id as preferred username (#3237)
Signed-off-by: Drew Foehn <drew@pixelburn.net> Signed-off-by: Jan Larwig <jan@larwig.com>
This commit is contained in:
+76
-7
@@ -40,6 +40,8 @@ type GoogleProvider struct {
|
||||
// Refresh. `Authorize` uses the results of this saved in `session.Groups`
|
||||
// Since it is called on every request.
|
||||
groupValidator func(*sessions.SessionState) bool
|
||||
|
||||
setPreferredUsername func(s *sessions.SessionState) error
|
||||
}
|
||||
|
||||
var _ Provider = (*GoogleProvider)(nil)
|
||||
@@ -100,17 +102,59 @@ func NewGoogleProvider(p *ProviderData, opts options.GoogleOptions) (*GoogleProv
|
||||
groupValidator: func(*sessions.SessionState) bool {
|
||||
return true
|
||||
},
|
||||
|
||||
setPreferredUsername: func(_ *sessions.SessionState) error {
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
if opts.ServiceAccountJSON != "" || opts.UseApplicationDefaultCredentials {
|
||||
provider.configureGroups(opts)
|
||||
}
|
||||
if opts.UseOrganizationID || opts.ServiceAccountJSON != "" || opts.UseApplicationDefaultCredentials {
|
||||
|
||||
// reuse admin service to avoid multiple calls for token
|
||||
var adminService *admin.Service
|
||||
|
||||
if opts.UseOrganizationID {
|
||||
// add user scopes to admin api
|
||||
userScope := getAdminAPIUserScope(opts.AdminAPIUserScope)
|
||||
for index, scope := range possibleScopesList {
|
||||
possibleScopesList[index] = scope + " " + userScope
|
||||
}
|
||||
|
||||
adminService = getAdminService(opts)
|
||||
|
||||
provider.setPreferredUsername = func(s *sessions.SessionState) error {
|
||||
userName, err := getUserInfo(adminService, s.Email)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
s.PreferredUsername = userName
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
if opts.ServiceAccountJSON != "" || opts.UseApplicationDefaultCredentials {
|
||||
if adminService == nil {
|
||||
adminService = getAdminService(opts)
|
||||
}
|
||||
provider.configureGroups(opts, adminService)
|
||||
}
|
||||
|
||||
}
|
||||
return provider, nil
|
||||
}
|
||||
|
||||
func (p *GoogleProvider) configureGroups(opts options.GoogleOptions) {
|
||||
adminService := getAdminService(opts)
|
||||
// by default can be readonly user scope
|
||||
func getAdminAPIUserScope(scope string) string {
|
||||
switch scope {
|
||||
case "cloud":
|
||||
return admin.CloudPlatformScope
|
||||
case "user":
|
||||
return admin.AdminDirectoryUserScope
|
||||
}
|
||||
return admin.AdminDirectoryUserReadonlyScope
|
||||
}
|
||||
|
||||
func (p *GoogleProvider) configureGroups(opts options.GoogleOptions, adminService *admin.Service) {
|
||||
// Backwards compatibility with `--google-group` option
|
||||
if len(opts.Groups) > 0 {
|
||||
p.setAllowedGroups(opts.Groups)
|
||||
@@ -204,6 +248,7 @@ func (p *GoogleProvider) Redeem(ctx context.Context, redirectURL, code, codeVeri
|
||||
|
||||
// EnrichSession checks the listed Google Groups configured and adds any
|
||||
// that the user is a member of to session.Groups.
|
||||
// if preferred username is configured to be organization ID, it sets that as well.
|
||||
func (p *GoogleProvider) EnrichSession(_ context.Context, s *sessions.SessionState) error {
|
||||
// TODO (@NickMeves) - Move to pure EnrichSession logic and stop
|
||||
// reusing legacy `groupValidator`.
|
||||
@@ -212,7 +257,7 @@ func (p *GoogleProvider) EnrichSession(_ context.Context, s *sessions.SessionSta
|
||||
// populating logic.
|
||||
p.groupValidator(s)
|
||||
|
||||
return nil
|
||||
return p.setPreferredUsername(s)
|
||||
}
|
||||
|
||||
// SetGroupRestriction configures the GoogleProvider to restrict access to the
|
||||
@@ -262,7 +307,7 @@ func getOauth2TokenSource(ctx context.Context, opts options.GoogleOptions, scope
|
||||
if opts.UseApplicationDefaultCredentials {
|
||||
ts, err := impersonate.CredentialsTokenSource(ctx, impersonate.CredentialsConfig{
|
||||
TargetPrincipal: getTargetPrincipal(ctx, opts),
|
||||
Scopes: []string{scope},
|
||||
Scopes: strings.Split(scope, " "),
|
||||
Subject: opts.AdminEmail,
|
||||
})
|
||||
if err != nil {
|
||||
@@ -364,6 +409,30 @@ func getTargetPrincipal(ctx context.Context, opts options.GoogleOptions) (target
|
||||
return targetPrincipal
|
||||
}
|
||||
|
||||
func getUserInfo(service *admin.Service, email string) (string, error) {
|
||||
req := service.Users.Get(email)
|
||||
user, err := req.Do()
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to get user details for %s: %v", email, err)
|
||||
}
|
||||
|
||||
ext, _ := user.ExternalIds.([]interface{})
|
||||
for _, v := range ext {
|
||||
m, _ := v.(map[string]interface{})
|
||||
if m == nil {
|
||||
continue
|
||||
}
|
||||
if t, _ := m["type"].(string); t != "organization" {
|
||||
continue
|
||||
}
|
||||
if val, _ := m["value"].(string); val != "" {
|
||||
return val, nil
|
||||
}
|
||||
}
|
||||
|
||||
return "", fmt.Errorf("failed to get organization id for %s", email)
|
||||
}
|
||||
|
||||
// getUserGroups retrieves all groups that a user is a member of using the Google Admin Directory API
|
||||
func getUserGroups(service *admin.Service, email string) ([]string, error) {
|
||||
var allGroups []string
|
||||
|
||||
Reference in New Issue
Block a user