Skip to content

Commit fc45f77

Browse files
committed
test: add unit test for deleting oauth created api keys
1 parent 2bd0408 commit fc45f77

File tree

1 file changed

+71
-37
lines changed

1 file changed

+71
-37
lines changed

coderd/oauth2_test.go

Lines changed: 71 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import (
2323
"github.com/coder/coder/v2/coderd/database/dbauthz"
2424
"github.com/coder/coder/v2/coderd/database/dbtestutil"
2525
"github.com/coder/coder/v2/coderd/database/dbtime"
26+
"github.com/coder/coder/v2/coderd/httpmw"
2627
"github.com/coder/coder/v2/coderd/oauth2provider"
2728
"github.com/coder/coder/v2/coderd/userpassword"
2829
"github.com/coder/coder/v2/coderd/util/ptr"
@@ -1607,18 +1608,22 @@ func TestOAuth2RegistrationAccessToken(t *testing.T) {
16071608
func TestOAuth2CoderClient(t *testing.T) {
16081609
t.Parallel()
16091610

1610-
owner := coderdtest.New(t, nil)
1611+
db, pubsub := dbtestutil.NewDB(t)
1612+
owner := coderdtest.New(t, &coderdtest.Options{
1613+
Database: db,
1614+
Pubsub: pubsub,
1615+
})
16111616
first := coderdtest.CreateFirstUser(t, owner)
16121617

16131618
// Setup an oauth app
1614-
ctx := testutil.Context(t, testutil.WaitLong)
1615-
app, err := owner.PostOAuth2ProviderApp(ctx, codersdk.PostOAuth2ProviderAppRequest{
1619+
setupCtx := testutil.Context(t, testutil.WaitLong)
1620+
app, err := owner.PostOAuth2ProviderApp(setupCtx, codersdk.PostOAuth2ProviderAppRequest{
16161621
Name: "new-app",
16171622
CallbackURL: "http://localhost",
16181623
})
16191624
require.NoError(t, err)
16201625

1621-
appsecret, err := owner.PostOAuth2ProviderAppSecret(ctx, app.ID)
1626+
appsecret, err := owner.PostOAuth2ProviderAppSecret(setupCtx, app.ID)
16221627
require.NoError(t, err)
16231628

16241629
cfg := &oauth2.Config{
@@ -1635,47 +1640,76 @@ func TestOAuth2CoderClient(t *testing.T) {
16351640
}
16361641

16371642
// Make a new user
1638-
client, user := coderdtest.CreateAnotherUser(t, owner, first.OrganizationID)
1643+
userClient, user := coderdtest.CreateAnotherUser(t, owner, first.OrganizationID)
1644+
1645+
// userOAuthFlow is a helper function that runs the oauth flow and returns
1646+
// the codersdk userClient using oauth as the means of authentication.
1647+
userOAuthFlow := func(t *testing.T) (*codersdk.Client, *oauth2.Token) {
1648+
// Do an OAuth2 token exchange and get a new userClient with an oauth token
1649+
state := uuid.NewString()
1650+
1651+
// Get an OAuth2 code for a token exchange
1652+
code, err := oidctest.OAuth2GetCode(
1653+
cfg.AuthCodeURL(state),
1654+
func(req *http.Request) (*http.Response, error) {
1655+
// Change to POST to simulate the form submission
1656+
req.Method = http.MethodPost
1657+
1658+
// Prevent automatic redirect following
1659+
userClient.HTTPClient.CheckRedirect = func(req *http.Request, via []*http.Request) error {
1660+
return http.ErrUseLastResponse
1661+
}
1662+
return userClient.Request(setupCtx, req.Method, req.URL.String(), nil)
1663+
},
1664+
)
1665+
require.NoError(t, err)
16391666

1640-
// Do an OAuth2 token exchange and get a new client with an oauth token
1641-
state := uuid.NewString()
1667+
token, err := cfg.Exchange(setupCtx, code)
1668+
require.NoError(t, err)
16421669

1643-
// Get an OAuth2 code for a token exchange
1644-
code, err := oidctest.OAuth2GetCode(
1645-
cfg.AuthCodeURL(state),
1646-
func(req *http.Request) (*http.Response, error) {
1647-
// Change to POST to simulate the form submission
1648-
req.Method = http.MethodPost
1670+
// Use the oauth userClient's authentication
1671+
// TODO: The SDK could probably support this with a better syntax/api.
1672+
oauthClient := oauth2.NewClient(setupCtx, oauth2.StaticTokenSource(token))
1673+
usingOauth := codersdk.New(owner.URL)
1674+
usingOauth.HTTPClient = oauthClient
16491675

1650-
// Prevent automatic redirect following
1651-
client.HTTPClient.CheckRedirect = func(req *http.Request, via []*http.Request) error {
1652-
return http.ErrUseLastResponse
1653-
}
1654-
return client.Request(ctx, req.Method, req.URL.String(), nil)
1655-
},
1656-
)
1657-
require.NoError(t, err)
1676+
me, err := usingOauth.User(setupCtx, codersdk.Me)
1677+
require.NoError(t, err)
1678+
require.Equal(t, user.ID, me.ID)
1679+
return usingOauth, token
1680+
}
16581681

1659-
token, err := cfg.Exchange(ctx, code)
1660-
require.NoError(t, err)
1682+
//nolint:tparallel,paralleltest
1683+
t.Run("OauthRevoke", func(t *testing.T) {
1684+
// OauthRevoke uses the proper oauth revocation endpoint to revoke the token.
1685+
ctx := testutil.Context(t, testutil.WaitShort)
1686+
client, token := userOAuthFlow(t)
1687+
// Revoking the refresh token should prevent further access
1688+
// Revoking the refresh also invalidates the associated access token.
1689+
err = client.RevokeOAuth2Token(ctx, app.ID, token.RefreshToken)
1690+
require.NoError(t, err)
16611691

1662-
// Use the oauth client's authentication
1663-
// TODO: The SDK could probably support this with a better syntax/api.
1664-
oauthClient := oauth2.NewClient(ctx, oauth2.StaticTokenSource(token))
1665-
usingOauth := codersdk.New(owner.URL)
1666-
usingOauth.HTTPClient = oauthClient
1692+
_, err = client.User(ctx, codersdk.Me)
1693+
require.Error(t, err)
1694+
})
16671695

1668-
me, err := usingOauth.User(ctx, codersdk.Me)
1669-
require.NoError(t, err)
1670-
require.Equal(t, user.ID, me.ID)
1696+
//nolint:tparallel,paralleltest
1697+
t.Run("DeleteAPIKey", func(t *testing.T) {
1698+
// DeleteAPIKey uses the coder api to delete the underlying api key used by the
1699+
// oauth token. This is not the recommended way to revoke oauth tokens, but is
1700+
// supported and should work.
1701+
ctx := testutil.Context(t, testutil.WaitShort)
1702+
client, token := userOAuthFlow(t)
16711703

1672-
// Revoking the refresh token should prevent further access
1673-
// Revoking the refresh also invalidates the associated access token.
1674-
err = usingOauth.RevokeOAuth2Token(ctx, app.ID, token.RefreshToken)
1675-
require.NoError(t, err)
1704+
id, _, err := httpmw.SplitAPIToken(token.AccessToken)
1705+
require.NoError(t, err)
16761706

1677-
_, err = usingOauth.User(ctx, codersdk.Me)
1678-
require.Error(t, err)
1707+
err = db.DeleteAPIKeyByID(ctx, id)
1708+
require.NoError(t, err)
1709+
1710+
_, err = client.User(ctx, codersdk.Me)
1711+
require.Error(t, err)
1712+
})
16791713
}
16801714

16811715
// NOTE: OAuth2 client registration validation tests have been migrated to

0 commit comments

Comments
 (0)