Minimal OpenID Connect implementation (#14139)

This is "minimal" in the sense that only the Authorization Code Flow
from OpenID Connect Core is implemented.  No discovery, no configuration
endpoint, and no user scope management.

OpenID Connect is an extension to the (already implemented) OAuth 2.0
protocol, and essentially an `id_token` JWT is added to the access token
endpoint response when using the Authorization Code Flow.  I also added
support for the "nonce" field since it is required to be used in the
id_token if the client decides to include it in its initial request.

In order to enable this extension an OAuth 2.0 scope containing
"openid" is needed. Other OAuth 2.0 requests should not be impacted by
this change.

This minimal implementation is enough to enable single sign-on (SSO)
for other sites, e.g. by using something like `mod_auth_openidc` to
only allow access to a CI server if a user has logged into Gitea.

Fixes: #1310

Co-authored-by: 6543 <6543@obermui.de>
Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
Co-authored-by: zeripath <art27@cantab.net>
This commit is contained in:
Johnny Oskarsson 2021-01-01 17:33:27 +01:00 committed by GitHub
parent 4f2f08bd80
commit a07e67d9cc
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 154 additions and 9 deletions

View file

@ -94,11 +94,12 @@ func TestOAuth2Application_GetGrantByUserID(t *testing.T) {
func TestOAuth2Application_CreateGrant(t *testing.T) {
assert.NoError(t, PrepareTestDatabase())
app := AssertExistsAndLoadBean(t, &OAuth2Application{ID: 1}).(*OAuth2Application)
grant, err := app.CreateGrant(2)
grant, err := app.CreateGrant(2, "")
assert.NoError(t, err)
assert.NotNil(t, grant)
assert.Equal(t, int64(2), grant.UserID)
assert.Equal(t, int64(1), grant.ApplicationID)
assert.Equal(t, "", grant.Scope)
}
//////////////////// Grant
@ -122,6 +123,15 @@ func TestOAuth2Grant_IncreaseCounter(t *testing.T) {
AssertExistsAndLoadBean(t, &OAuth2Grant{ID: 1, Counter: 2})
}
func TestOAuth2Grant_ScopeContains(t *testing.T) {
assert.NoError(t, PrepareTestDatabase())
grant := AssertExistsAndLoadBean(t, &OAuth2Grant{ID: 1, Scope: "openid profile"}).(*OAuth2Grant)
assert.True(t, grant.ScopeContains("openid"))
assert.True(t, grant.ScopeContains("profile"))
assert.False(t, grant.ScopeContains("profil"))
assert.False(t, grant.ScopeContains("profile2"))
}
func TestOAuth2Grant_GenerateNewAuthorizationCode(t *testing.T) {
assert.NoError(t, PrepareTestDatabase())
grant := AssertExistsAndLoadBean(t, &OAuth2Grant{ID: 1}).(*OAuth2Grant)