-
-
Notifications
You must be signed in to change notification settings - Fork 5.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Enhancing Gitea OAuth2 Provider with Granular Scopes for Resource Acc…
…ess (#32573) Resolve #31609 This PR was initiated following my personal research to find the lightest possible Single Sign-On solution for self-hosted setups. The existing solutions often seemed too enterprise-oriented, involving many moving parts and services, demanding significant resources while promising planetary-scale capabilities. Others were adequate in supporting basic OAuth2 flows but lacked proper user management features, such as a change password UI. Gitea hits the sweet spot for me, provided it supports more granular access permissions for resources under users who accept the OAuth2 application. This PR aims to introduce granularity in handling user resources as nonintrusively and simply as possible. It allows third parties to inform users about their intent to not ask for the full access and instead request a specific, reduced scope. If the provided scopes are **only** the typical ones for OIDC/OAuth2—`openid`, `profile`, `email`, and `groups`—everything remains unchanged (currently full access to user's resources). Additionally, this PR supports processing scopes already introduced with [personal tokens](https://docs.gitea.com/development/oauth2-provider#scopes) (e.g. `read:user`, `write:issue`, `read:group`, `write:repository`...) Personal tokens define scopes around specific resources: user info, repositories, issues, packages, organizations, notifications, miscellaneous, admin, and activitypub, with access delineated by read and/or write permissions. The initial case I wanted to address was to have Gitea act as an OAuth2 Identity Provider. To achieve that, with this PR, I would only add `openid public-only` to provide access token to the third party to authenticate the Gitea's user but no further access to the API and users resources. Another example: if a third party wanted to interact solely with Issues, it would need to add `read:user` (for authorization) and `read:issue`/`write:issue` to manage Issues. My approach is based on my understanding of how scopes can be utilized, supported by examples like [Sample Use Cases: Scopes and Claims](https://auth0.com/docs/get-started/apis/scopes/sample-use-cases-scopes-and-claims) on auth0.com. I renamed `CheckOAuthAccessToken` to `GetOAuthAccessTokenScopeAndUserID` so now it returns AccessTokenScope and user's ID. In the case of additional scopes in `userIDFromToken` the default `all` would be reduced to whatever was asked via those scopes. The main difference is the opportunity to reduce the permissions from `all`, as is currently the case, to what is provided by the additional scopes described above. Screenshots: ![Screenshot_20241121_121405](https://github.com/user-attachments/assets/29deaed7-4333-4b02-8898-b822e6f2463e) ![Screenshot_20241121_120211](https://github.com/user-attachments/assets/7a4a4ef7-409c-4116-9d5f-2fe00eb37167) ![Screenshot_20241121_120119](https://github.com/user-attachments/assets/aa52c1a2-212d-4e64-bcdf-7122cee49eb6) ![Screenshot_20241121_120018](https://github.com/user-attachments/assets/9eac318c-e381-4ea9-9e2c-3a3f60319e47) --------- Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
- Loading branch information
1 parent
a175f98
commit a3881ff
Showing
8 changed files
with
537 additions
and
18 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
// Copyright 2024 The Gitea Authors. All rights reserved. | ||
// SPDX-License-Identifier: MIT | ||
|
||
package oauth2_provider //nolint | ||
|
||
import ( | ||
"testing" | ||
|
||
"github.com/stretchr/testify/assert" | ||
) | ||
|
||
func TestGrantAdditionalScopes(t *testing.T) { | ||
tests := []struct { | ||
grantScopes string | ||
expectedScopes string | ||
}{ | ||
{"openid profile email", "all"}, | ||
{"openid profile email groups", "all"}, | ||
{"openid profile email all", "all"}, | ||
{"openid profile email read:user all", "all"}, | ||
{"openid profile email groups read:user", "read:user"}, | ||
{"read:user read:repository", "read:repository,read:user"}, | ||
{"read:user write:issue public-only", "public-only,write:issue,read:user"}, | ||
{"openid profile email read:user", "read:user"}, | ||
{"read:invalid_scope", "all"}, | ||
{"read:invalid_scope,write:scope_invalid,just-plain-wrong", "all"}, | ||
} | ||
|
||
for _, test := range tests { | ||
t.Run(test.grantScopes, func(t *testing.T) { | ||
result := GrantAdditionalScopes(test.grantScopes) | ||
assert.Equal(t, test.expectedScopes, string(result)) | ||
}) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.