Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
ceaf11c
Add setting to OAuth handlers to override local 2FA settings
zeripath Aug 21, 2021
ddc1966
Fix regression from #16544
zeripath Aug 20, 2021
ca74f82
Add scopes settings
zeripath Aug 20, 2021
c282f85
fix trace logging in auth_openid
zeripath Aug 20, 2021
0d4874f
add required claim options
zeripath Aug 20, 2021
bd86307
Move UpdateExternalUser to externalaccount
zeripath Aug 20, 2021
0e27070
Allow OAuth2/OIDC to set Admin/Restricted status
zeripath Aug 20, 2021
b51c09c
Allow use of the same group claim name for the prohibit login value
zeripath Aug 21, 2021
11791e5
fixup! Move UpdateExternalUser to externalaccount
zeripath Aug 21, 2021
de07c25
Merge branch 'main' into oidc-claims
zeripath Aug 29, 2021
ea37fd0
Merge branch 'main' into oidc-claims
zeripath Aug 29, 2021
a730e6b
Merge remote-tracking branch 'origin/main' into oidc-claims
zeripath Sep 25, 2021
4818a72
Merge remote-tracking branch 'origin/main' into oidc-claims
zeripath Sep 27, 2021
8b8abaa
as per wxiaoguang
zeripath Sep 27, 2021
7a88d06
add label back in
zeripath Oct 14, 2021
1f0d1a0
Merge remote-tracking branch 'origin/main' into oidc-claims
zeripath Oct 14, 2021
7cd84d7
adjust localisation
zeripath Oct 14, 2021
d119bc8
Merge branch 'main' into oidc-claims
6543 Oct 15, 2021
125747a
Merge remote-tracking branch 'origin/main' into oidc-claims
zeripath Nov 20, 2021
a5d3887
Merge remote-tracking branch 'origin/main' into oidc-claims
zeripath Nov 27, 2021
7545100
Merge remote-tracking branch 'origin/main' into oidc-claims
zeripath Nov 28, 2021
47ae8f5
placate lint
zeripath Nov 28, 2021
3f4df7c
Merge branch 'main' into oidc-claims
lunny Dec 10, 2021
bc558ed
Merge branch 'main' into oidc-claims
lunny Dec 10, 2021
36da1a6
Merge branch 'main' into oidc-claims
lunny Dec 13, 2021
6041ea8
Merge branch 'main' into oidc-claims
lunny Dec 13, 2021
706532a
Merge remote-tracking branch 'origin/main' into oidc-claims
zeripath Dec 13, 2021
33e3af2
Merge branch 'main' into oidc-claims
lunny Dec 14, 2021
323782f
Merge branch 'main' into oidc-claims
techknowlogick Dec 14, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Allow OAuth2/OIDC to set Admin/Restricted status
Signed-off-by: Andrew Thornton <[email protected]>
  • Loading branch information
zeripath committed Aug 21, 2021
commit 0e27070c6d17ad902f3b47100e89f872d85fe351
28 changes: 28 additions & 0 deletions cmd/admin.go
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,21 @@ var (
Value: "",
Usage: "Claim value that has to be set to allow users to login with this source",
},
cli.StringFlag{
Name: "group-claim-name",
Value: "",
Usage: "Claim name providing group names for this source",
},
cli.StringFlag{
Name: "admin-group",
Value: "",
Usage: "Group Claim value for administrator users",
},
cli.StringFlag{
Name: "restricted-group",
Value: "",
Usage: "Group Claim value for restricted users",
},
}

microcmdAuthUpdateOauth = cli.Command{
Expand Down Expand Up @@ -639,6 +654,9 @@ func parseOAuth2Config(c *cli.Context) *oauth2.Source {
Scopes: c.StringSlice("scopes"),
RequiredClaimName: c.String("required-claim-name"),
RequiredClaimValue: c.String("required-claim-value"),
GroupClaimName: c.String("group-claim-name"),
AdminGroup: c.String("admin-group"),
RestrictedGroup: c.String("restricted-group"),
}
}

Expand Down Expand Up @@ -707,6 +725,16 @@ func runUpdateOauth(c *cli.Context) error {
oAuth2Config.RequiredClaimValue = c.String("required-claim-value")
}

if c.IsSet("group-claim-name") {
oAuth2Config.GroupClaimName = c.String("group-claim-name")
}
if c.IsSet("admin-group") {
oAuth2Config.AdminGroup = c.String("admin-group")
}
if c.IsSet("restricted-group") {
oAuth2Config.RestrictedGroup = c.String("restricted-group")
}

// update custom URL mapping
var customURLMapping = &oauth2.CustomURLMapping{}

Expand Down
6 changes: 6 additions & 0 deletions docs/content/doc/usage/command-line.en-us.md
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,9 @@ Admin operations:
- `--scopes`: Addtional scopes to request for this OAuth2 source. (Optional)
- `--required-claim-name`: Claim name that has to be set to allow users to login with this source. (Optional)
- `--required-claim-value`: Claim value that has to be set to allow users to login with this source. (Optional)
- `--group-claim-name`: Claim name providing group names for this source. (Optional)
- `--admin-group`: Group Claim value for administrator users. (Optional)
- `--restricted-group`: Group Claim value for restricted users. (Optional)
- Examples:
- `gitea admin auth add-oauth --name external-github --provider github --key OBTAIN_FROM_SOURCE --secret OBTAIN_FROM_SOURCE`
- `update-oauth`:
Expand All @@ -141,6 +144,9 @@ Admin operations:
- `--scopes`: Addtional scopes to request for this OAuth2 source.
- `--required-claim-name`: Claim name that has to be set to allow users to login with this source. (Optional)
- `--required-claim-value`: Claim value that has to be set to allow users to login with this source. (Optional)
- `--group-claim-name`: Claim name providing group names for this source. (Optional)
- `--admin-group`: Group Claim value for administrator users. (Optional)
- `--restricted-group`: Group Claim value for restricted users. (Optional)
- Examples:
- `gitea admin auth update-oauth --id 1 --name external-github-updated`
- `add-ldap`: Add new LDAP (via Bind DN) authentication source
Expand Down
72 changes: 71 additions & 1 deletion routers/web/user/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -597,6 +597,13 @@ func SignInOAuthCallback(ctx *context.Context) {
u, gothUser, err := oAuth2UserLoginCallback(loginSource, ctx.Req, ctx.Resp)

if err != nil {
if models.IsErrUserProhibitLogin(err) {
uplerr := err.(*models.ErrUserProhibitLogin)
log.Info("Failed authentication attempt for %s from %s: %v", uplerr.Name, ctx.RemoteAddr(), err)
ctx.Data["Title"] = ctx.Tr("auth.prohibit_login")
ctx.HTML(http.StatusOK, "user/auth/prohibit_login")
return
}
ctx.ServerError("UserSignIn", err)
return
}
Expand Down Expand Up @@ -633,6 +640,8 @@ func SignInOAuthCallback(ctx *context.Context) {
LoginName: gothUser.UserID,
}

setUserGroupClaims(loginSource, u, &gothUser)

if !createAndHandleCreatedUser(ctx, base.TplName(""), nil, u, &gothUser, setting.OAuth2Client.AccountLinking != setting.OAuth2AccountLinkingDisabled) {
// error already handled
return
Expand All @@ -647,6 +656,51 @@ func SignInOAuthCallback(ctx *context.Context) {
handleOAuth2SignIn(ctx, loginSource, u, gothUser)
}

func setUserGroupClaims(loginSource *models.LoginSource, u *models.User, gothUser *goth.User) bool {

source := loginSource.Cfg.(*oauth2.Source)
if source.GroupClaimName == "" || (source.AdminGroup == "" && source.RestrictedGroup == "") {
return false
}

groupClaims, has := gothUser.RawData[source.GroupClaimName]
if !has {
return false
}

var groups []string

switch rawGroup := groupClaims.(type) {
case []string:
groups = rawGroup
case string:
if strings.Contains(rawGroup, ",") {
groups = strings.Split(rawGroup, ",")
} else {
groups = []string{rawGroup}
}
}

wasAdmin, wasRestricted := u.IsAdmin, u.IsRestricted

if source.AdminGroup != "" {
u.IsAdmin = false
}
if source.RestrictedGroup != "" {
u.IsRestricted = false
}

for _, g := range groups {
if source.AdminGroup != "" && g == source.AdminGroup {
u.IsAdmin = true
} else if source.RestrictedGroup != "" && g == source.RestrictedGroup {
u.IsRestricted = true
}
}

return wasAdmin == u.IsAdmin && wasRestricted == u.IsRestricted
}

func getUserName(gothUser *goth.User) string {
switch setting.OAuth2Client.Username {
case setting.OAuth2UsernameEmail:
Expand Down Expand Up @@ -717,7 +771,15 @@ func handleOAuth2SignIn(ctx *context.Context, source *models.LoginSource, u *mod

// Register last login
u.SetLastLogin()
if err := models.UpdateUserCols(u, "last_login_unix"); err != nil {

// Update GroupClaims
changed := setUserGroupClaims(source, u, &gothUser)
cols := []string{"last_login_unix"}
if changed {
cols = append(cols, "is_admin", "is_restricted")
}

if err := models.UpdateUserCols(u, cols...); err != nil {
ctx.ServerError("UpdateUserCols", err)
return
}
Expand All @@ -737,6 +799,14 @@ func handleOAuth2SignIn(ctx *context.Context, source *models.LoginSource, u *mod
return
}

changed := setUserGroupClaims(source, u, &gothUser)
if changed {
if err := models.UpdateUserCols(u, "is_admin", "is_restricted"); err != nil {
ctx.ServerError("UpdateUserCols", err)
return
}
}

// User needs to use 2FA, save data and redirect to 2FA page.
if err := ctx.Session.Set("twofaUid", u.ID); err != nil {
log.Error("Error setting twofaUid in session: %v", err)
Expand Down
3 changes: 3 additions & 0 deletions services/auth/source/oauth2/source.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ type Source struct {
Scopes []string
RequiredClaimName string
RequiredClaimValue string
GroupClaimName string
AdminGroup string
RestrictedGroup string

// reference to the loginSource
loginSource *models.LoginSource
Expand Down
3 changes: 3 additions & 0 deletions services/forms/auth_form.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,9 @@ type AuthenticationForm struct {
Oauth2Scopes string
Oauth2RequiredClaimName string
Oauth2RequiredClaimValue string
Oauth2GroupClaimName string
Oauth2AdminGroup string
Oauth2RestrictedGroup string
SSPIAutoCreateUsers bool
SSPIAutoActivateUsers bool
SSPIStripDomainNames bool
Expand Down
12 changes: 12 additions & 0 deletions templates/admin/auth/edit.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,18 @@
<input id="oauth2_required_claim_value" name="oauth2_required_claim_value" values="{{$cfg.RequiredClaimValue}}">
<p class="help">{{.i18n.Tr "admin.auths.oauth2_required_claim_value_helper"}}</p>
</div>
<div class="field">
<label for="oauth2_group_claim_name">{{.i18n.Tr "admin.auths.oauth2_group_claim_name"}}</label>
<input id="oauth2_group_claim_name" name="oauth2_group_claim_name" value="{{$cfg.GroupClaimName}}">
</div>
<div class="field">
<label for="oauth2_admin_group">{{.i18n.Tr "admin.auths.oauth2_admin_group"}}</label>
<input id="oauth2_admin_group" name="oauth2_admin_group" value="{{$cfg.AdminGroup}}">
</div>
<div class="field">
<label for="oauth2_restricted_group">{{.i18n.Tr "admin.auths.oauth2_restricted_group"}}</label>
<input id="oauth2_restricted_group" name="oauth2_restricted_group" value="{{$cfg.RestrictedGroup}}">
</div>
{{end}}

<!-- SSPI -->
Expand Down
12 changes: 12 additions & 0 deletions templates/admin/auth/source/oauth.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -86,4 +86,16 @@
<input id="oauth2_required_claim_value" name="oauth2_required_claim_value" values="{{.oauth2_required_claim_value}}">
<p class="help">{{.i18n.Tr "admin.auths.oauth2_required_claim_value_helper"}}</p>
</div>
<div class="field">
<label for="oauth2_group_claim_name">{{.i18n.Tr "admin.auths.oauth2_group_claim_name"}}</label>
<input id="oauth2_group_claim_name" name="oauth2_group_claim_name" value="{{.oauth2_group_claim_name}}">
</div>
<div class="field">
<label for="oauth2_admin_group">{{.i18n.Tr "admin.auths.oauth2_admin_group"}}</label>
<input id="oauth2_admin_group" name="oauth2_admin_group" value="{{.oauth2_group_claim_name}}">
</div>
<div class="field">
<label for="oauth2_restricted_group">{{.i18n.Tr "admin.auths.oauth2_restricted_group"}}</label>
<input id="oauth2_restricted_group" name="oauth2_restricted_group" value="{{.oauth2_group_claim_name}}">
</div>
</div>