diff options
author | Nico Schieder <Nico.schieder@gmail.com> | 2021-10-22 11:19:24 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-10-22 17:19:24 +0800 |
commit | 870f5fbc4146110be37c28e670e57568d3db3288 (patch) | |
tree | 69d2f6989030c459094d51bfc2798af6ae092ee0 | |
parent | af96286f2254c1e073394aae0f18b132f07b38ad (diff) | |
download | gitea-870f5fbc4146110be37c28e670e57568d3db3288.tar.gz gitea-870f5fbc4146110be37c28e670e57568d3db3288.zip |
Add groups scope/claim to OIDC/OAuth2 Provider (#17367)
* Add groups scope/claim to OICD/OAuth2
Add support for groups claim as part of the OIDC/OAuth2 flow.
Groups is a list of "org" and "org:team" strings to allow clients to
authorize based on the groups a user is part of.
Signed-off-by: Nico Schieder <code@nico-schieder.de>
Co-authored-by: zeripath <art27@cantab.net>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
-rw-r--r-- | routers/web/user/oauth.go | 55 | ||||
-rw-r--r-- | services/auth/source/oauth2/token.go | 3 | ||||
-rw-r--r-- | templates/user/auth/oidc_wellknown.tmpl | 6 |
3 files changed, 57 insertions, 7 deletions
diff --git a/routers/web/user/oauth.go b/routers/web/user/oauth.go index d9fc5eeaf9..642a7f33b0 100644 --- a/routers/web/user/oauth.go +++ b/routers/web/user/oauth.go @@ -207,6 +207,17 @@ func newAccessTokenResponse(grant *login.OAuth2Grant, serverKey, clientKey oauth idToken.Email = user.Email idToken.EmailVerified = user.IsActive } + if grant.ScopeContains("groups") { + groups, err := getOAuthGroupsForUser(user) + if err != nil { + log.Error("Error getting groups: %v", err) + return nil, &AccessTokenError{ + ErrorCode: AccessTokenErrorCodeInvalidRequest, + ErrorDescription: "server error", + } + } + idToken.Groups = groups + } signedIDToken, err = idToken.SignToken(clientKey) if err != nil { @@ -227,11 +238,12 @@ func newAccessTokenResponse(grant *login.OAuth2Grant, serverKey, clientKey oauth } type userInfoResponse struct { - Sub string `json:"sub"` - Name string `json:"name"` - Username string `json:"preferred_username"` - Email string `json:"email"` - Picture string `json:"picture"` + Sub string `json:"sub"` + Name string `json:"name"` + Username string `json:"preferred_username"` + Email string `json:"email"` + Picture string `json:"picture"` + Groups []string `json:"groups"` } // InfoOAuth manages request for userinfo endpoint @@ -241,6 +253,7 @@ func InfoOAuth(ctx *context.Context) { ctx.HandleText(http.StatusUnauthorized, "no valid authorization") return } + response := &userInfoResponse{ Sub: fmt.Sprint(ctx.User.ID), Name: ctx.User.FullName, @@ -248,9 +261,41 @@ func InfoOAuth(ctx *context.Context) { Email: ctx.User.Email, Picture: ctx.User.AvatarLink(), } + + groups, err := getOAuthGroupsForUser(ctx.User) + if err != nil { + ctx.ServerError("Oauth groups for user", err) + return + } + response.Groups = groups + ctx.JSON(http.StatusOK, response) } +// returns a list of "org" and "org:team" strings, +// that the given user is a part of. +func getOAuthGroupsForUser(user *models.User) ([]string, error) { + orgs, err := models.GetUserOrgsList(user) + if err != nil { + return nil, fmt.Errorf("GetUserOrgList: %v", err) + } + + var groups []string + for _, org := range orgs { + groups = append(groups, org.Name) + + if err := org.LoadTeams(); err != nil { + return nil, fmt.Errorf("LoadTeams: %v", err) + } + for _, team := range org.Teams { + if team.IsMember(user.ID) { + groups = append(groups, org.Name+":"+team.LowerName) + } + } + } + return groups, nil +} + // IntrospectOAuth introspects an oauth token func IntrospectOAuth(ctx *context.Context) { if ctx.User == nil { diff --git a/services/auth/source/oauth2/token.go b/services/auth/source/oauth2/token.go index 16d1220842..0c7c5d8caa 100644 --- a/services/auth/source/oauth2/token.go +++ b/services/auth/source/oauth2/token.go @@ -83,6 +83,9 @@ type OIDCToken struct { // Scope email Email string `json:"email,omitempty"` EmailVerified bool `json:"email_verified,omitempty"` + + // Groups are generated by organization and team names + Groups []string `json:"groups,omitempty"` } // SignToken signs an id_token with the (symmetric) client secret key diff --git a/templates/user/auth/oidc_wellknown.tmpl b/templates/user/auth/oidc_wellknown.tmpl index d4cbf7dfec..38e6900c38 100644 --- a/templates/user/auth/oidc_wellknown.tmpl +++ b/templates/user/auth/oidc_wellknown.tmpl @@ -18,7 +18,8 @@ "scopes_supported": [ "openid", "profile", - "email" + "email", + "groups" ], "claims_supported": [ "aud", @@ -34,7 +35,8 @@ "locale", "updated_at", "email", - "email_verified" + "email_verified", + "groups" ], "code_challenge_methods_supported": [ "plain", |