Skip to content

Commit 3623f69

Browse files
committed
Add secret prefix column and query to get token
This will be used as an ID that we can prefix into the secrets themselves. This is so we can salt the hashed secrets. The token query is for implementing the refresh flow.
1 parent d1a2111 commit 3623f69

15 files changed

+320
-196
lines changed

coderd/database/dbauthz/dbauthz.go

+22-6
Original file line numberDiff line numberDiff line change
@@ -1202,16 +1202,12 @@ func (q *querier) GetOAuth2ProviderAppByID(ctx context.Context, id uuid.UUID) (d
12021202
return q.db.GetOAuth2ProviderAppByID(ctx, id)
12031203
}
12041204

1205-
func (q *querier) GetOAuth2ProviderAppCodeByAppIDAndSecret(ctx context.Context, arg database.GetOAuth2ProviderAppCodeByAppIDAndSecretParams) (database.OAuth2ProviderAppCode, error) {
1206-
return fetch(q.log, q.auth, q.db.GetOAuth2ProviderAppCodeByAppIDAndSecret)(ctx, arg)
1207-
}
1208-
12091205
func (q *querier) GetOAuth2ProviderAppCodeByID(ctx context.Context, id uuid.UUID) (database.OAuth2ProviderAppCode, error) {
12101206
return fetch(q.log, q.auth, q.db.GetOAuth2ProviderAppCodeByID)(ctx, id)
12111207
}
12121208

1213-
func (q *querier) GetOAuth2ProviderAppSecretByAppIDAndSecret(ctx context.Context, arg database.GetOAuth2ProviderAppSecretByAppIDAndSecretParams) (database.OAuth2ProviderAppSecret, error) {
1214-
return fetch(q.log, q.auth, q.db.GetOAuth2ProviderAppSecretByAppIDAndSecret)(ctx, arg)
1209+
func (q *querier) GetOAuth2ProviderAppCodeByPrefix(ctx context.Context, secretPrefix []byte) (database.OAuth2ProviderAppCode, error) {
1210+
return fetch(q.log, q.auth, q.db.GetOAuth2ProviderAppCodeByPrefix)(ctx, secretPrefix)
12151211
}
12161212

12171213
func (q *querier) GetOAuth2ProviderAppSecretByID(ctx context.Context, id uuid.UUID) (database.OAuth2ProviderAppSecret, error) {
@@ -1221,13 +1217,33 @@ func (q *querier) GetOAuth2ProviderAppSecretByID(ctx context.Context, id uuid.UU
12211217
return q.db.GetOAuth2ProviderAppSecretByID(ctx, id)
12221218
}
12231219

1220+
func (q *querier) GetOAuth2ProviderAppSecretByPrefix(ctx context.Context, secretPrefix []byte) (database.OAuth2ProviderAppSecret, error) {
1221+
return fetch(q.log, q.auth, q.db.GetOAuth2ProviderAppSecretByPrefix)(ctx, secretPrefix)
1222+
}
1223+
12241224
func (q *querier) GetOAuth2ProviderAppSecretsByAppID(ctx context.Context, appID uuid.UUID) ([]database.OAuth2ProviderAppSecret, error) {
12251225
if err := q.authorizeContext(ctx, rbac.ActionRead, rbac.ResourceOAuth2ProviderAppSecret); err != nil {
12261226
return []database.OAuth2ProviderAppSecret{}, err
12271227
}
12281228
return q.db.GetOAuth2ProviderAppSecretsByAppID(ctx, appID)
12291229
}
12301230

1231+
func (q *querier) GetOAuth2ProviderAppTokenByPrefix(ctx context.Context, hashPrefix []byte) (database.OAuth2ProviderAppToken, error) {
1232+
token, err := q.db.GetOAuth2ProviderAppTokenByPrefix(ctx, hashPrefix)
1233+
if err != nil {
1234+
return database.OAuth2ProviderAppToken{}, err
1235+
}
1236+
// The user ID is on the API key so that has to be fetched.
1237+
key, err := q.db.GetAPIKeyByID(ctx, token.APIKeyID)
1238+
if err != nil {
1239+
return database.OAuth2ProviderAppToken{}, err
1240+
}
1241+
if err := q.authorizeContext(ctx, rbac.ActionRead, rbac.ResourceOAuth2ProviderAppCodeToken.WithOwner(key.UserID.String())); err != nil {
1242+
return database.OAuth2ProviderAppToken{}, err
1243+
}
1244+
return token, nil
1245+
}
1246+
12311247
func (q *querier) GetOAuth2ProviderApps(ctx context.Context) ([]database.OAuth2ProviderApp, error) {
12321248
if err := q.authorizeContext(ctx, rbac.ActionRead, rbac.ResourceOAuth2ProviderApp); err != nil {
12331249
return []database.OAuth2ProviderApp{}, err

coderd/database/dbauthz/dbauthz_test.go

+19-10
Original file line numberDiff line numberDiff line change
@@ -2352,15 +2352,12 @@ func (s *MethodTestSuite) TestOAuth2ProviderAppSecrets() {
23522352
})
23532353
check.Args(secret.ID).Asserts(rbac.ResourceOAuth2ProviderAppSecret, rbac.ActionRead).Returns(secret)
23542354
}))
2355-
s.Run("GetOAuth2ProviderAppSecretByAppIDAndSecret", s.Subtest(func(db database.Store, check *expects) {
2355+
s.Run("GetOAuth2ProviderAppSecretByPrefix", s.Subtest(func(db database.Store, check *expects) {
23562356
app := dbgen.OAuth2ProviderApp(s.T(), db, database.OAuth2ProviderApp{})
23572357
secret := dbgen.OAuth2ProviderAppSecret(s.T(), db, database.OAuth2ProviderAppSecret{
23582358
AppID: app.ID,
23592359
})
2360-
check.Args(database.GetOAuth2ProviderAppSecretByAppIDAndSecretParams{
2361-
AppID: app.ID,
2362-
HashedSecret: secret.HashedSecret,
2363-
}).Asserts(rbac.ResourceOAuth2ProviderAppSecret, rbac.ActionRead).Returns(secret)
2360+
check.Args(secret.SecretPrefix).Asserts(rbac.ResourceOAuth2ProviderAppSecret, rbac.ActionRead).Returns(secret)
23642361
}))
23652362
s.Run("InsertOAuth2ProviderAppSecret", s.Subtest(func(db database.Store, check *expects) {
23662363
app := dbgen.OAuth2ProviderApp(s.T(), db, database.OAuth2ProviderApp{})
@@ -2398,17 +2395,14 @@ func (s *MethodTestSuite) TestOAuth2ProviderAppCodes() {
23982395
})
23992396
check.Args(code.ID).Asserts(code, rbac.ActionRead).Returns(code)
24002397
}))
2401-
s.Run("GetOAuth2ProviderAppCodeByAppIDAndSecret", s.Subtest(func(db database.Store, check *expects) {
2398+
s.Run("GetOAuth2ProviderAppCodeByPrefix", s.Subtest(func(db database.Store, check *expects) {
24022399
user := dbgen.User(s.T(), db, database.User{})
24032400
app := dbgen.OAuth2ProviderApp(s.T(), db, database.OAuth2ProviderApp{})
24042401
code := dbgen.OAuth2ProviderAppCode(s.T(), db, database.OAuth2ProviderAppCode{
24052402
AppID: app.ID,
24062403
UserID: user.ID,
24072404
})
2408-
check.Args(database.GetOAuth2ProviderAppCodeByAppIDAndSecretParams{
2409-
AppID: app.ID,
2410-
HashedSecret: code.HashedSecret,
2411-
}).Asserts(code, rbac.ActionRead).Returns(code)
2405+
check.Args(code.SecretPrefix).Asserts(code, rbac.ActionRead).Returns(code)
24122406
}))
24132407
s.Run("InsertOAuth2ProviderAppCode", s.Subtest(func(db database.Store, check *expects) {
24142408
user := dbgen.User(s.T(), db, database.User{})
@@ -2458,6 +2452,21 @@ func (s *MethodTestSuite) TestOAuth2ProviderAppTokens() {
24582452
APIKeyID: key.ID,
24592453
}).Asserts(rbac.ResourceOAuth2ProviderAppCodeToken.WithOwner(user.ID.String()), rbac.ActionCreate)
24602454
}))
2455+
s.Run("GetOAuth2ProviderAppTokenByPrefix", s.Subtest(func(db database.Store, check *expects) {
2456+
user := dbgen.User(s.T(), db, database.User{})
2457+
key, _ := dbgen.APIKey(s.T(), db, database.APIKey{
2458+
UserID: user.ID,
2459+
})
2460+
app := dbgen.OAuth2ProviderApp(s.T(), db, database.OAuth2ProviderApp{})
2461+
secret := dbgen.OAuth2ProviderAppSecret(s.T(), db, database.OAuth2ProviderAppSecret{
2462+
AppID: app.ID,
2463+
})
2464+
token := dbgen.OAuth2ProviderAppToken(s.T(), db, database.OAuth2ProviderAppToken{
2465+
AppSecretID: secret.ID,
2466+
APIKeyID: key.ID,
2467+
})
2468+
check.Args(token.HashPrefix).Asserts(rbac.ResourceOAuth2ProviderAppCodeToken.WithOwner(user.ID.String()), rbac.ActionRead)
2469+
}))
24612470
s.Run("DeleteOAuth2ProviderAppTokensByAppAndUserID", s.Subtest(func(db database.Store, check *expects) {
24622471
user := dbgen.User(s.T(), db, database.User{})
24632472
key, _ := dbgen.APIKey(s.T(), db, database.APIKey{

coderd/database/dbgen/dbgen.go

+3
Original file line numberDiff line numberDiff line change
@@ -696,6 +696,7 @@ func OAuth2ProviderAppSecret(t testing.TB, db database.Store, seed database.OAut
696696
app, err := db.InsertOAuth2ProviderAppSecret(genCtx, database.InsertOAuth2ProviderAppSecretParams{
697697
ID: takeFirst(seed.ID, uuid.New()),
698698
CreatedAt: takeFirst(seed.CreatedAt, dbtime.Now()),
699+
SecretPrefix: takeFirstSlice(seed.SecretPrefix, []byte("prefix")),
699700
HashedSecret: takeFirstSlice(seed.HashedSecret, []byte("hashed-secret")),
700701
DisplaySecret: takeFirst(seed.DisplaySecret, "secret"),
701702
AppID: takeFirst(seed.AppID, uuid.New()),
@@ -709,6 +710,7 @@ func OAuth2ProviderAppCode(t testing.TB, db database.Store, seed database.OAuth2
709710
ID: takeFirst(seed.ID, uuid.New()),
710711
CreatedAt: takeFirst(seed.CreatedAt, dbtime.Now()),
711712
ExpiresAt: takeFirst(seed.CreatedAt, dbtime.Now()),
713+
SecretPrefix: takeFirstSlice(seed.SecretPrefix, []byte("prefix")),
712714
HashedSecret: takeFirstSlice(seed.HashedSecret, []byte("hashed-secret")),
713715
AppID: takeFirst(seed.AppID, uuid.New()),
714716
UserID: takeFirst(seed.UserID, uuid.New()),
@@ -722,6 +724,7 @@ func OAuth2ProviderAppToken(t testing.TB, db database.Store, seed database.OAuth
722724
ID: takeFirst(seed.ID, uuid.New()),
723725
CreatedAt: takeFirst(seed.CreatedAt, dbtime.Now()),
724726
ExpiresAt: takeFirst(seed.CreatedAt, dbtime.Now()),
727+
HashPrefix: takeFirstSlice(seed.HashPrefix, []byte("prefix")),
725728
RefreshHash: takeFirstSlice(seed.RefreshHash, []byte("hashed-secret")),
726729
AppSecretID: takeFirst(seed.AppSecretID, uuid.New()),
727730
APIKeyID: takeFirst(seed.APIKeyID, uuid.New().String()),

coderd/database/dbmem/dbmem.go

+24-18
Original file line numberDiff line numberDiff line change
@@ -2242,58 +2242,48 @@ func (q *FakeQuerier) GetOAuth2ProviderAppByID(_ context.Context, id uuid.UUID)
22422242
return database.OAuth2ProviderApp{}, sql.ErrNoRows
22432243
}
22442244

2245-
func (q *FakeQuerier) GetOAuth2ProviderAppCodeByAppIDAndSecret(_ context.Context, arg database.GetOAuth2ProviderAppCodeByAppIDAndSecretParams) (database.OAuth2ProviderAppCode, error) {
2246-
err := validateDatabaseType(arg)
2247-
if err != nil {
2248-
return database.OAuth2ProviderAppCode{}, err
2249-
}
2250-
2245+
func (q *FakeQuerier) GetOAuth2ProviderAppCodeByID(_ context.Context, id uuid.UUID) (database.OAuth2ProviderAppCode, error) {
22512246
q.mutex.Lock()
22522247
defer q.mutex.Unlock()
22532248

22542249
for _, code := range q.oauth2ProviderAppCodes {
2255-
if bytes.Equal(code.HashedSecret, arg.HashedSecret) && code.AppID == arg.AppID {
2250+
if code.ID == id {
22562251
return code, nil
22572252
}
22582253
}
22592254
return database.OAuth2ProviderAppCode{}, sql.ErrNoRows
22602255
}
22612256

2262-
func (q *FakeQuerier) GetOAuth2ProviderAppCodeByID(_ context.Context, id uuid.UUID) (database.OAuth2ProviderAppCode, error) {
2257+
func (q *FakeQuerier) GetOAuth2ProviderAppCodeByPrefix(_ context.Context, secretPrefix []byte) (database.OAuth2ProviderAppCode, error) {
22632258
q.mutex.Lock()
22642259
defer q.mutex.Unlock()
22652260

22662261
for _, code := range q.oauth2ProviderAppCodes {
2267-
if code.ID == id {
2262+
if bytes.Equal(code.SecretPrefix, secretPrefix) {
22682263
return code, nil
22692264
}
22702265
}
22712266
return database.OAuth2ProviderAppCode{}, sql.ErrNoRows
22722267
}
22732268

2274-
func (q *FakeQuerier) GetOAuth2ProviderAppSecretByAppIDAndSecret(_ context.Context, arg database.GetOAuth2ProviderAppSecretByAppIDAndSecretParams) (database.OAuth2ProviderAppSecret, error) {
2275-
err := validateDatabaseType(arg)
2276-
if err != nil {
2277-
return database.OAuth2ProviderAppSecret{}, err
2278-
}
2279-
2269+
func (q *FakeQuerier) GetOAuth2ProviderAppSecretByID(_ context.Context, id uuid.UUID) (database.OAuth2ProviderAppSecret, error) {
22802270
q.mutex.Lock()
22812271
defer q.mutex.Unlock()
22822272

22832273
for _, secret := range q.oauth2ProviderAppSecrets {
2284-
if secret.AppID == arg.AppID && bytes.Equal(secret.HashedSecret, arg.HashedSecret) {
2274+
if secret.ID == id {
22852275
return secret, nil
22862276
}
22872277
}
22882278
return database.OAuth2ProviderAppSecret{}, sql.ErrNoRows
22892279
}
22902280

2291-
func (q *FakeQuerier) GetOAuth2ProviderAppSecretByID(_ context.Context, id uuid.UUID) (database.OAuth2ProviderAppSecret, error) {
2281+
func (q *FakeQuerier) GetOAuth2ProviderAppSecretByPrefix(_ context.Context, secretPrefix []byte) (database.OAuth2ProviderAppSecret, error) {
22922282
q.mutex.Lock()
22932283
defer q.mutex.Unlock()
22942284

22952285
for _, secret := range q.oauth2ProviderAppSecrets {
2296-
if secret.ID == id {
2286+
if bytes.Equal(secret.SecretPrefix, secretPrefix) {
22972287
return secret, nil
22982288
}
22992289
}
@@ -2328,6 +2318,18 @@ func (q *FakeQuerier) GetOAuth2ProviderAppSecretsByAppID(_ context.Context, appI
23282318
return []database.OAuth2ProviderAppSecret{}, sql.ErrNoRows
23292319
}
23302320

2321+
func (q *FakeQuerier) GetOAuth2ProviderAppTokenByPrefix(_ context.Context, hashPrefix []byte) (database.OAuth2ProviderAppToken, error) {
2322+
q.mutex.Lock()
2323+
defer q.mutex.Unlock()
2324+
2325+
for _, token := range q.oauth2ProviderAppTokens {
2326+
if bytes.Equal(token.HashPrefix, hashPrefix) {
2327+
return token, nil
2328+
}
2329+
}
2330+
return database.OAuth2ProviderAppToken{}, sql.ErrNoRows
2331+
}
2332+
23312333
func (q *FakeQuerier) GetOAuth2ProviderApps(_ context.Context) ([]database.OAuth2ProviderApp, error) {
23322334
q.mutex.Lock()
23332335
defer q.mutex.Unlock()
@@ -5419,6 +5421,7 @@ func (q *FakeQuerier) InsertOAuth2ProviderAppCode(_ context.Context, arg databas
54195421
ID: arg.ID,
54205422
CreatedAt: arg.CreatedAt,
54215423
ExpiresAt: arg.ExpiresAt,
5424+
SecretPrefix: arg.SecretPrefix,
54225425
HashedSecret: arg.HashedSecret,
54235426
UserID: arg.UserID,
54245427
AppID: arg.AppID,
@@ -5445,6 +5448,7 @@ func (q *FakeQuerier) InsertOAuth2ProviderAppSecret(_ context.Context, arg datab
54455448
secret := database.OAuth2ProviderAppSecret{
54465449
ID: arg.ID,
54475450
CreatedAt: arg.CreatedAt,
5451+
SecretPrefix: arg.SecretPrefix,
54485452
HashedSecret: arg.HashedSecret,
54495453
DisplaySecret: arg.DisplaySecret,
54505454
AppID: arg.AppID,
@@ -5473,6 +5477,7 @@ func (q *FakeQuerier) InsertOAuth2ProviderAppToken(_ context.Context, arg databa
54735477
ID: arg.ID,
54745478
CreatedAt: arg.CreatedAt,
54755479
ExpiresAt: arg.ExpiresAt,
5480+
HashPrefix: arg.HashPrefix,
54765481
RefreshHash: arg.RefreshHash,
54775482
APIKeyID: arg.APIKeyID,
54785483
AppSecretID: arg.AppSecretID,
@@ -6553,6 +6558,7 @@ func (q *FakeQuerier) UpdateOAuth2ProviderAppSecretByID(_ context.Context, arg d
65536558
newSecret := database.OAuth2ProviderAppSecret{
65546559
ID: arg.ID,
65556560
CreatedAt: secret.CreatedAt,
6561+
SecretPrefix: secret.SecretPrefix,
65566562
HashedSecret: secret.HashedSecret,
65576563
DisplaySecret: secret.DisplaySecret,
65586564
AppID: secret.AppID,

coderd/database/dbmetrics/dbmetrics.go

+17-10
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)