@@ -18,6 +18,7 @@ import (
1818"github.com/coder/coder/v2/coderd/database/dbauthz"
1919"github.com/coder/coder/v2/coderd/httpapi"
2020"github.com/coder/coder/v2/coderd/httpmw"
21+ "github.com/coder/coder/v2/coderd/userpassword"
2122)
2223
2324var (
2829)
2930
3031// RevokeToken implements RFC 7009 OAuth2 Token Revocation
32+ // Authentication is unique for this endpoint in that it does not use the
33+ // standard token authentication middleware. Instead, it expects the token that
34+ // is being revoked to be valid.
35+ // TODO: Currently the token validation occurs in the revocation logic itself.
36+ // This code should be refactored to share token validation logic with other parts
37+ // of the OAuth2 provider/http middleware.
3138func RevokeToken (db database.Store ,logger slog.Logger ) http.HandlerFunc {
3239return func (rw http.ResponseWriter ,r * http.Request ) {
3340ctx := r .Context ()
@@ -126,6 +133,14 @@ func revokeRefreshTokenInTx(ctx context.Context, db database.Store, token string
126133return xerrors .Errorf ("get oauth2 provider app token by prefix: %w" ,err )
127134}
128135
136+ equal ,err := userpassword .Compare (string (dbToken .RefreshHash ),parsedToken .Secret )
137+ if err != nil {
138+ return xerrors .Errorf ("invalid refresh token: %w" ,err )
139+ }
140+ if ! equal {
141+ return xerrors .Errorf ("invalid refresh token" )
142+ }
143+
129144// Verify ownership
130145//nolint:gocritic // Using AsSystemOAuth2 for OAuth2 public token revocation endpoint
131146appSecret ,err := db .GetOAuth2ProviderAppSecretByID (dbauthz .AsSystemOAuth2 (ctx ),dbToken .AppSecretID )