@@ -40,6 +40,8 @@ type GoogleProvider struct {
4040 // Refresh. `Authorize` uses the results of this saved in `session.Groups`
4141 // Since it is called on every request.
4242 groupValidator func(*sessions.SessionState) bool
43+
44+ setPreferredUsername func(s *sessions.SessionState) error
4345}
4446
4547var _ Provider = (*GoogleProvider)(nil)
@@ -100,17 +102,59 @@ func NewGoogleProvider(p *ProviderData, opts options.GoogleOptions) (*GoogleProv
100102 groupValidator: func(*sessions.SessionState) bool {
101103 return true
102104 },
103− }
104105
105− if opts.ServiceAccountJSON != "" || opts.UseApplicationDefaultCredentials {
106− provider.configureGroups(opts)
106+ setPreferredUsername: func(_ *sessions.SessionState) error {
107+ return nil
108+ },
107109 }
108110
111+ if opts.UseOrganizationID || opts.ServiceAccountJSON != "" || opts.UseApplicationDefaultCredentials {
112+
113+ // reuse admin service to avoid multiple calls for token
114+ var adminService *admin.Service
115+
116+ if opts.UseOrganizationID {
117+ // add user scopes to admin api
118+ userScope := getAdminAPIUserScope(opts.AdminAPIUserScope)
119+ for index, scope := range possibleScopesList {
120+ possibleScopesList[index] = scope + " " + userScope
121+ }
122+
123+ adminService = getAdminService(opts)
124+
125+ provider.setPreferredUsername = func(s *sessions.SessionState) error {
126+ userName, err := getUserInfo(adminService, s.Email)
127+ if err != nil {
128+ return err
129+ }
130+ s.PreferredUsername = userName
131+ return nil
132+ }
133+ }
134+
135+ if opts.ServiceAccountJSON != "" || opts.UseApplicationDefaultCredentials {
136+ if adminService == nil {
137+ adminService = getAdminService(opts)
138+ }
139+ provider.configureGroups(opts, adminService)
140+ }
141+
142+ }
109143 return provider, nil
110144}
111145
112−func (p *GoogleProvider) configureGroups(opts options.GoogleOptions) {
113− adminService := getAdminService(opts)
146+// by default can be readonly user scope
147+func getAdminAPIUserScope(scope string) string {
148+ switch scope {
149+ case "cloud":
150+ return admin.CloudPlatformScope
151+ case "user":
152+ return admin.AdminDirectoryUserScope
153+ }
154+ return admin.AdminDirectoryUserReadonlyScope
155+}
156+
157+func (p *GoogleProvider) configureGroups(opts options.GoogleOptions, adminService *admin.Service) {
114158 // Backwards compatibility with `--google-group` option
115159 if len(opts.Groups) > 0 {
116160 p.setAllowedGroups(opts.Groups)
@@ -204,6 +248,7 @@ func (p *GoogleProvider) Redeem(ctx context.Context, redirectURL, code, codeVeri
204248
205249// EnrichSession checks the listed Google Groups configured and adds any
206250// that the user is a member of to session.Groups.
251+// if preferred username is configured to be organization ID, it sets that as well.
207252func (p *GoogleProvider) EnrichSession(_ context.Context, s *sessions.SessionState) error {
208253 // TODO (@NickMeves) - Move to pure EnrichSession logic and stop
209254 // reusing legacy `groupValidator`.
@@ -212,7 +257,7 @@ func (p *GoogleProvider) EnrichSession(_ context.Context, s *sessions.SessionSta
212257 // populating logic.
213258 p.groupValidator(s)
214259
215− return nil
260+ return p.setPreferredUsername(s)
216261}
217262
218263// SetGroupRestriction configures the GoogleProvider to restrict access to the
@@ -262,7 +307,7 @@ func getOauth2TokenSource(ctx context.Context, opts options.GoogleOptions, scope
262307 if opts.UseApplicationDefaultCredentials {
263308 ts, err := impersonate.CredentialsTokenSource(ctx, impersonate.CredentialsConfig{
264309 TargetPrincipal: getTargetPrincipal(ctx, opts),
265− Scopes: []string{scope},
310+ Scopes: strings.Split(scope, " "),
266311 Subject: opts.AdminEmail,
267312 })
268313 if err != nil {
@@ -364,6 +409,30 @@ func getTargetPrincipal(ctx context.Context, opts options.GoogleOptions) (target
364409 return targetPrincipal
365410}
366411
412+func getUserInfo(service *admin.Service, email string) (string, error) {
413+ req := service.Users.Get(email)
414+ user, err := req.Do()
415+ if err != nil {
416+ return "", fmt.Errorf("failed to get user details for %s: %v", email, err)
417+ }
418+
419+ ext, _ := user.ExternalIds.([]interface{})
420+ for _, v := range ext {
421+ m, _ := v.(map[string]interface{})
422+ if m == nil {
423+ continue
424+ }
425+ if t, _ := m["type"].(string); t != "organization" {
426+ continue
427+ }
428+ if val, _ := m["value"].(string); val != "" {
429+ return val, nil
430+ }
431+ }
432+
433+ return "", fmt.Errorf("failed to get organization id for %s", email)
434+}
435+
367436// getUserGroups retrieves all groups that a user is a member of using the Google Admin Directory API
368437func getUserGroups(service *admin.Service, email string) ([]string, error) {
369438 var allGroups []string