Backport #37704 This PR hardens OAuth token exchange validation by binding exchanged credentials to the client and redirect URI that originally obtained them. What it changes: - reject refresh token exchanges when the refresh token belongs to a different OAuth application - reject authorization code exchanges when the `redirect_uri` in the token request differs from the `redirect_uri` stored with the authorization code - add integration coverage for: - authorization code exchange with a mismatched redirect URI - refresh token reuse across two different dynamically created OAuth applications Why: OAuth authorization codes and refresh tokens must remain bound to the client context that originally received them. Without those checks: - a valid authorization code can be redeemed against a different registered redirect URI of the same client - a refresh token can be replayed by a different OAuth client --------- Co-authored-by: Nicolas <bircni@icloud.com>
This commit is contained in:
@@ -561,6 +561,13 @@ func handleRefreshToken(ctx *context.Context, form forms.AccessTokenForm, server
|
||||
})
|
||||
return
|
||||
}
|
||||
if grant.ApplicationID != app.ID {
|
||||
handleAccessTokenError(ctx, oauth2_provider.AccessTokenError{
|
||||
ErrorCode: oauth2_provider.AccessTokenErrorCodeInvalidGrant,
|
||||
ErrorDescription: "refresh token belongs to a different client",
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
// check if token got already used
|
||||
if setting.OAuth2.InvalidateRefreshTokens && (grant.Counter != token.Counter || token.Counter == 0) {
|
||||
@@ -630,6 +637,13 @@ func handleAuthorizationCode(ctx *context.Context, form forms.AccessTokenForm, s
|
||||
})
|
||||
return
|
||||
}
|
||||
if authorizationCode.RedirectURI != "" && form.RedirectURI != authorizationCode.RedirectURI {
|
||||
handleAccessTokenError(ctx, oauth2_provider.AccessTokenError{
|
||||
ErrorCode: oauth2_provider.AccessTokenErrorCodeInvalidGrant,
|
||||
ErrorDescription: "redirect_uri differs from the original authorization request",
|
||||
})
|
||||
return
|
||||
}
|
||||
// check if granted for this application
|
||||
if authorizationCode.Grant.ApplicationID != app.ID {
|
||||
handleAccessTokenError(ctx, oauth2_provider.AccessTokenError{
|
||||
|
||||
Reference in New Issue
Block a user