Fix: Remove Authorization Header for Public OAuth Clients (RFC 7636) #88
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Fix: Remove Authorization Header for Public OAuth Clients (RFC 7636)
Summary
based on:
#61
Thanks to @rcdailey for his contributions
This pull request addresses a critical OAuth2 compliance issue where the application was incorrectly sending an Authorization header during token exchange for public clients using PKCE (Proof Key for Code Exchange). According to RFC 7636 and the OAuth 2.0 specification for public clients, native applications that cannot securely store client secrets must not include an Authorization header when exchanging authorization codes for tokens.
Problem Description
The previous implementation always attempted to generate a
clientAuthvalue and include it in the Authorization header during the token exchange request, regardless of whether the client was configured as a public or confidential client. This behavior caused authentication failures with OAuth providers that strictly enforce RFC 7636 compliance, as they reject token requests from public clients that include an Authorization header.Public clients are characterized by an empty
clientSecretvalue. When theclientSecretis empty or not provided, the application should authenticate solely through the PKCE code verifier mechanism rather than through HTTP Basic Authentication headers.Technical Changes
TokenRequestRemoteOperation.kt
The core fix resides in the
TokenRequestRemoteOperationclass, which handles the HTTP request to the token endpoint. The critical change is the conditional logic that now checks whetherclientAuthis non-empty before adding the Authorization header:Previously, this header was always added regardless of the
clientAuthvalue. With this change, whenclientAuthis an empty string, no Authorization header is sent, which is the correct behavior for public PKCE clients.LoginActivity.kt
The
exchangeAuthorizationCodeForTokensmethod was updated to properly determine theclientAuthvalue based on whether aclientSecretexists. The implementation now uses a clear conditional check:This ensures that when the application is configured as a public client with no client secret, an empty string is passed as
clientAuth, which subsequently prevents the Authorization header from being added to the token request.A variable shadowing bug was also fixed in this method. Previously, destructuring assignment created local variables that shadowed the intended values, which could lead to incorrect data being used when constructing the token request.
AccountAuthenticator.java
The AccountAuthenticator class was refactored to improve code organization and readability. The changes enhance the token refresh logic to properly handle public client scenarios where no Authorization header should be sent during token refresh operations.
Unit Tests
Comprehensive unit tests were added to ensure RFC 7636 compliance is maintained:
TokenRequest.kt (Test Fixtures)
Two new test fixtures were added for public PKCE clients:
OCRemoteOAuthDataSourceTest.kt
Three new test methods were added:
performTokenRequest with public PKCE client returns a TokenResponse- Verifies that access token requests work correctly with emptyclientAuth.performTokenRequest with public PKCE client refresh token returns a TokenResponse- Verifies that refresh token requests work correctly with emptyclientAuth.public PKCE client fixtures have empty clientAuth preventing Authorization header- A compliance verification test that asserts public client fixtures have emptyclientAuthwhile confidential client fixtures have non-emptyclientAuth.RemoteOAuthUtils.kt
Test utility classes were extended with corresponding remote parameter fixtures for both public and confidential client scenarios, ensuring complete test coverage across the OAuth data layer.
Verification
All changes have been verified through:
Related Standards
Files Changed