diff options
Diffstat (limited to 'models')
-rw-r--r-- | models/fixtures/oauth2_grant.yml | 1 | ||||
-rw-r--r-- | models/migrations/migrations.go | 2 | ||||
-rw-r--r-- | models/migrations/v164.go | 38 | ||||
-rw-r--r-- | models/oauth2_application.go | 47 | ||||
-rw-r--r-- | models/oauth2_application_test.go | 12 |
5 files changed, 96 insertions, 4 deletions
diff --git a/models/fixtures/oauth2_grant.yml b/models/fixtures/oauth2_grant.yml index 113eec7e5c..105e3f22db 100644 --- a/models/fixtures/oauth2_grant.yml +++ b/models/fixtures/oauth2_grant.yml @@ -2,5 +2,6 @@ user_id: 1 application_id: 1 counter: 1 + scope: "openid profile" created_unix: 1546869730 updated_unix: 1546869730 diff --git a/models/migrations/migrations.go b/models/migrations/migrations.go index 6570460425..bb3adccc25 100644 --- a/models/migrations/migrations.go +++ b/models/migrations/migrations.go @@ -271,6 +271,8 @@ var migrations = []Migration{ NewMigration("Convert webhook task type from int to string", convertWebhookTaskTypeToString), // v163 -> v164 NewMigration("Convert topic name from 25 to 50", convertTopicNameFrom25To50), + // v164 -> v165 + NewMigration("Add scope and nonce columns to oauth2_grant table", addScopeAndNonceColumnsToOAuth2Grant), } // GetCurrentDBVersion returns the current db version diff --git a/models/migrations/v164.go b/models/migrations/v164.go new file mode 100644 index 0000000000..01ba796563 --- /dev/null +++ b/models/migrations/v164.go @@ -0,0 +1,38 @@ +// Copyright 2020 The Gitea Authors. All rights reserved. +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file. + +package migrations + +import ( + "fmt" + + "xorm.io/xorm" +) + +// OAuth2Grant here is a snapshot of models.OAuth2Grant for this version +// of the database, as it does not appear to have been added as a part +// of a previous migration. +type OAuth2Grant struct { + ID int64 `xorm:"pk autoincr"` + UserID int64 `xorm:"INDEX unique(user_application)"` + ApplicationID int64 `xorm:"INDEX unique(user_application)"` + Counter int64 `xorm:"NOT NULL DEFAULT 1"` + Scope string `xorm:"TEXT"` + Nonce string `xorm:"TEXT"` + CreatedUnix int64 `xorm:"created"` + UpdatedUnix int64 `xorm:"updated"` +} + +// TableName sets the database table name to be the correct one, as the +// autogenerated table name for this struct is "o_auth2_grant". +func (grant *OAuth2Grant) TableName() string { + return "oauth2_grant" +} + +func addScopeAndNonceColumnsToOAuth2Grant(x *xorm.Engine) error { + if err := x.Sync2(new(OAuth2Grant)); err != nil { + return fmt.Errorf("Sync2: %v", err) + } + return nil +} diff --git a/models/oauth2_application.go b/models/oauth2_application.go index af4d280d0c..1b544e4e9e 100644 --- a/models/oauth2_application.go +++ b/models/oauth2_application.go @@ -9,6 +9,7 @@ import ( "encoding/base64" "fmt" "net/url" + "strings" "time" "code.gitea.io/gitea/modules/secret" @@ -103,14 +104,15 @@ func (app *OAuth2Application) getGrantByUserID(e Engine, userID int64) (grant *O } // CreateGrant generates a grant for an user -func (app *OAuth2Application) CreateGrant(userID int64) (*OAuth2Grant, error) { - return app.createGrant(x, userID) +func (app *OAuth2Application) CreateGrant(userID int64, scope string) (*OAuth2Grant, error) { + return app.createGrant(x, userID, scope) } -func (app *OAuth2Application) createGrant(e Engine, userID int64) (*OAuth2Grant, error) { +func (app *OAuth2Application) createGrant(e Engine, userID int64, scope string) (*OAuth2Grant, error) { grant := &OAuth2Grant{ ApplicationID: app.ID, UserID: userID, + Scope: scope, } _, err := e.Insert(grant) if err != nil { @@ -380,6 +382,8 @@ type OAuth2Grant struct { Application *OAuth2Application `xorm:"-"` ApplicationID int64 `xorm:"INDEX unique(user_application)"` Counter int64 `xorm:"NOT NULL DEFAULT 1"` + Scope string `xorm:"TEXT"` + Nonce string `xorm:"TEXT"` CreatedUnix timeutil.TimeStamp `xorm:"created"` UpdatedUnix timeutil.TimeStamp `xorm:"updated"` } @@ -431,6 +435,30 @@ func (grant *OAuth2Grant) increaseCount(e Engine) error { return nil } +// ScopeContains returns true if the grant scope contains the specified scope +func (grant *OAuth2Grant) ScopeContains(scope string) bool { + for _, currentScope := range strings.Split(grant.Scope, " ") { + if scope == currentScope { + return true + } + } + return false +} + +// SetNonce updates the current nonce value of a grant +func (grant *OAuth2Grant) SetNonce(nonce string) error { + return grant.setNonce(x, nonce) +} + +func (grant *OAuth2Grant) setNonce(e Engine, nonce string) error { + grant.Nonce = nonce + _, err := e.ID(grant.ID).Cols("nonce").Update(grant) + if err != nil { + return err + } + return nil +} + // GetOAuth2GrantByID returns the grant with the given ID func GetOAuth2GrantByID(id int64) (*OAuth2Grant, error) { return getOAuth2GrantByID(x, id) @@ -533,3 +561,16 @@ func (token *OAuth2Token) SignToken() (string, error) { jwtToken := jwt.NewWithClaims(jwt.SigningMethodHS512, token) return jwtToken.SignedString(setting.OAuth2.JWTSecretBytes) } + +// OIDCToken represents an OpenID Connect id_token +type OIDCToken struct { + jwt.StandardClaims + Nonce string `json:"nonce,omitempty"` +} + +// SignToken signs an id_token with the (symmetric) client secret key +func (token *OIDCToken) SignToken(clientSecret string) (string, error) { + token.IssuedAt = time.Now().Unix() + jwtToken := jwt.NewWithClaims(jwt.SigningMethodHS256, token) + return jwtToken.SignedString([]byte(clientSecret)) +} diff --git a/models/oauth2_application_test.go b/models/oauth2_application_test.go index 3afdf50f53..511d019465 100644 --- a/models/oauth2_application_test.go +++ b/models/oauth2_application_test.go @@ -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) |