@@ -103,17 +103,24 @@ func NewGoogleProvider(p *ProviderData, opts options.GoogleOptions) (*GoogleProv
103103 }
104104
105105 if opts.ServiceAccountJSON != "" || opts.UseApplicationDefaultCredentials {
106− // Backwards compatibility with `--google-group` option
107− if len(opts.Groups) > 0 {
108− provider.setAllowedGroups(opts.Groups)
109− }
110−
111− provider.setGroupRestriction(opts)
106+ provider.configureGroups(opts)
112107 }
113108
114109 return provider, nil
115110}
116111
112+func (p *GoogleProvider) configureGroups(opts options.GoogleOptions) {
113+ adminService := getAdminService(opts)
114+ // Backwards compatibility with `--google-group` option
115+ if len(opts.Groups) > 0 {
116+ p.setAllowedGroups(opts.Groups)
117+ p.groupValidator = p.setGroupRestriction(opts.Groups, adminService)
118+ return
119+ }
120+
121+ p.groupValidator = p.populateAllGroups(adminService)
122+}
123+
117124func claimsFromIDToken(idToken string) (*claims, error) {
118125
119126 // id_token is a base64 encode ID token payload
@@ -209,18 +216,13 @@ func (p *GoogleProvider) EnrichSession(_ context.Context, s *sessions.SessionSta
209216}
210217
211218// SetGroupRestriction configures the GoogleProvider to restrict access to the
212−// specified group(s). AdminEmail has to be an administrative email on the domain that is
213−// checked. CredentialsFile is the path to a json file containing a Google service
214−// account credentials.
215−//
216−// TODO (@NickMeves) - Unit Test this OR refactor away from groupValidator func
217−func (p *GoogleProvider) setGroupRestriction(opts options.GoogleOptions) {
218− adminService := getAdminService(opts)
219− p.groupValidator = func(s *sessions.SessionState) bool {
219+// specified group(s).
220+func (p *GoogleProvider) setGroupRestriction(groups []string, adminService *admin.Service) func(*sessions.SessionState) bool {
221+ return func(s *sessions.SessionState) bool {
220222 // Reset our saved Groups in case membership changed
221223 // This is used by `Authorize` on every request
222− s.Groups = make([]string, 0, len(opts.Groups))
223− for _, group := range opts.Groups {
224+ s.Groups = make([]string, 0, len(groups))
225+ for _, group := range groups {
224226 if userInGroup(adminService, group, s.Email) {
225227 s.Groups = append(s.Groups, group)
226228 }
@@ -229,6 +231,25 @@ func (p *GoogleProvider) setGroupRestriction(opts options.GoogleOptions) {
229231 }
230232}
231233
234+// populateAllGroups configures the GoogleProvider to allow access with all
235+// groups and populate session with all groups of the user when no specific
236+// groups are configured.
237+func (p *GoogleProvider) populateAllGroups(adminService *admin.Service) func(s *sessions.SessionState) bool {
238+ return func(s *sessions.SessionState) bool {
239+ // Get all groups of the user
240+ groups, err := getUserGroups(adminService, s.Email)
241+ if err != nil {
242+ logger.Errorf("Failed to get user groups for %s: %v", s.Email, err)
243+ s.Groups = []string{}
244+ return true // Allow access even if we can't get groups
245+ }
246+
247+ // Populate session with all user groups
248+ s.Groups = groups
249+ return true // Always allow access when no specific groups are configured
250+ }
251+}
252+
232253// https://developers.google.com/admin-sdk/directory/reference/rest/v1/members/hasMember#authorization-scopes
233254var possibleScopesList = [...]string{
234255 admin.AdminDirectoryGroupMemberReadonlyScope,
@@ -269,6 +290,10 @@ func getOauth2TokenSource(ctx context.Context, opts options.GoogleOptions, scope
269290 return conf.TokenSource(ctx)
270291}
271292
293+// getAdminService retrieves an oauth token for the admin api of Google
294+// AdminEmail has to be an administrative email on the domain that is
295+// checked. CredentialsFile is the path to a json file containing a Google service
296+// account credentials.
272297func getAdminService(opts options.GoogleOptions) *admin.Service {
273298 ctx := context.Background()
274299 var client *http.Client
@@ -339,6 +364,38 @@ func getTargetPrincipal(ctx context.Context, opts options.GoogleOptions) (target
339364 return targetPrincipal
340365}
341366
367+// getUserGroups retrieves all groups that a user is a member of using the Google Admin Directory API
368+func getUserGroups(service *admin.Service, email string) ([]string, error) {
369+ var allGroups []string
370+ var pageToken string
371+
372+ for {
373+ req := service.Groups.List().UserKey(email).MaxResults(200)
374+ if pageToken != "" {
375+ req = req.PageToken(pageToken)
376+ }
377+
378+ groupsResp, err := req.Do()
379+ if err != nil {
380+ return nil, fmt.Errorf("failed to list groups for user %s: %v", email, err)
381+ }
382+
383+ for _, group := range groupsResp.Groups {
384+ if group.Email != "" {
385+ allGroups = append(allGroups, group.Email)
386+ }
387+ }
388+
389+ // Check if there are more pages
390+ if groupsResp.NextPageToken == "" {
391+ break
392+ }
393+ pageToken = groupsResp.NextPageToken
394+ }
395+
396+ return allGroups, nil
397+}
398+
342399func userInGroup(service *admin.Service, group string, email string) bool {
343400 // Use the HasMember API to checking for the user's presence in each group or nested subgroups
344401 req := service.Members.HasMember(group, email)