summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNico Schieder <Nico.schieder@gmail.com>2021-10-22 11:19:24 +0200
committerGitHub <noreply@github.com>2021-10-22 17:19:24 +0800
commit870f5fbc4146110be37c28e670e57568d3db3288 (patch)
tree69d2f6989030c459094d51bfc2798af6ae092ee0
parentaf96286f2254c1e073394aae0f18b132f07b38ad (diff)
downloadgitea-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.go55
-rw-r--r--services/auth/source/oauth2/token.go3
-rw-r--r--templates/user/auth/oidc_wellknown.tmpl6
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",