storj/satellite/oidc/dbx_test.go
Cameron 84b522bc06 satellite/console: create account management api keys service
We are in the process of creating an api to allow users to manage their
accounts programmatically. We would like to use api keys for
authorization. We were originally going to create an entirely new table
for these api keys, but seeing as we already have 2 other tables for
keys/tokens, api_keys and oauth_tokens, we thought it might be better to
use one of these. We're using oauth_tokens.

We create a new oidc.OAuthTokenKind for account management api keys:
KindAccountManagementTokenV0. We made the key versioned because we
likely want to improve the implementation in the future, but we want to
get something functional out the door ASAP because the account management
api feature is highly desired.

Add a new method to oidc.OAuthTokens interface for revoking v0 account
management api keys, RevokeAccountManagementTokenV0. Add update method
to dbx implementation to allow updating the expiration. We will revoke
these keys by setting the expiration to 0 so they are expired.

Change-Id: Ideb8ae04b23aa55d5825b064b5e43e32eadc1fba
2022-03-23 17:02:20 +00:00

154 lines
3.5 KiB
Go

// Copyright (C) 2022 Storj Labs, Inc.
// See LICENSE for copying information.
package oidc_test
import (
"database/sql"
"testing"
"time"
"github.com/stretchr/testify/require"
"storj.io/common/testcontext"
"storj.io/common/uuid"
"storj.io/storj/satellite"
"storj.io/storj/satellite/oidc"
"storj.io/storj/satellite/satellitedb/satellitedbtest"
)
func TestOAuthCodes(t *testing.T) {
satellitedbtest.Run(t, func(ctx *testcontext.Context, t *testing.T, db satellite.DB) {
clientID, err := uuid.New()
require.NoError(t, err)
userID, err := uuid.New()
require.NoError(t, err)
// repositories
codes := db.OIDC().OAuthCodes()
start := time.Now()
allCodes := []oidc.OAuthCode{
{
ClientID: clientID,
UserID: userID,
Code: "expired",
CreatedAt: start.Add(-2 * time.Hour),
ExpiresAt: start.Add(-1 * time.Hour),
},
{
ClientID: clientID,
UserID: userID,
Code: "valid",
CreatedAt: start,
ExpiresAt: start.Add(time.Hour),
},
{
ClientID: clientID,
UserID: userID,
Code: "claimed",
CreatedAt: start,
ExpiresAt: start.Add(time.Hour),
},
}
for _, code := range allCodes {
err = codes.Create(ctx, code)
require.NoError(t, err)
}
// claim this code ahead of time to test the token already claimed code path later on
err = codes.Claim(ctx, "claimed")
require.NoError(t, err)
testCases := []struct {
code string
err error
}{
{"expired", sql.ErrNoRows},
{"valid", nil},
{"claimed", sql.ErrNoRows}, // this should return an error since it was claimed above
}
for _, testCase := range testCases {
_, err := codes.Get(ctx, testCase.code)
require.Equal(t, testCase.err, err)
}
})
}
func TestOAuthTokens(t *testing.T) {
satellitedbtest.Run(t, func(ctx *testcontext.Context, t *testing.T, db satellite.DB) {
clientID, err := uuid.New()
require.NoError(t, err)
userID, err := uuid.New()
require.NoError(t, err)
// repositories
tokens := db.OIDC().OAuthTokens()
start := time.Now()
allTokens := []oidc.OAuthToken{
{
ClientID: clientID,
UserID: userID,
Kind: oidc.KindAccessToken,
Token: "expired",
CreatedAt: start.Add(-2 * time.Hour),
ExpiresAt: start.Add(-1 * time.Hour),
},
{
ClientID: clientID,
UserID: userID,
Kind: oidc.KindRefreshToken,
Token: "valid",
CreatedAt: start,
ExpiresAt: start.Add(time.Hour),
},
{
ClientID: clientID,
UserID: userID,
Kind: oidc.KindAccountManagementTokenV0,
Token: "testToken",
CreatedAt: start,
ExpiresAt: start.Add(time.Hour),
},
}
for _, token := range allTokens {
err = tokens.Create(ctx, token)
require.NoError(t, err)
}
// ensure that creating an existing token doesn't cause an error
err = tokens.Create(ctx, allTokens[1])
require.NoError(t, err)
testCases := []struct {
kind oidc.OAuthTokenKind
token string
err error
}{
{oidc.KindAccessToken, "expired", sql.ErrNoRows},
{oidc.KindRefreshToken, "valid", nil},
{oidc.KindAccountManagementTokenV0, "testToken", nil},
}
for _, testCase := range testCases {
_, err := tokens.Get(ctx, testCase.kind, testCase.token)
require.Equal(t, testCase.err, err)
if testCase.kind == oidc.KindAccountManagementTokenV0 {
err = tokens.RevokeAccountManagementTokenV0(ctx, testCase.token)
require.NoError(t, err)
token, err := tokens.Get(ctx, testCase.kind, testCase.token)
require.Equal(t, sql.ErrNoRows, err)
require.True(t, token.ExpiresAt.IsZero())
}
}
})
}