-
Notifications
You must be signed in to change notification settings - Fork 224
Description
Describe the issue
When using kubelogin with Azure IDP and PKCE authentication, there's an inconsistency in the token exchange behavior between initial authentication and subsequent attempts using cached refresh tokens. The initial authentication works as expected, but subsequent attempts fail due to missing client_id in the token exchange request body.
To reproduce
-
Create an Azure application with Mobile and desktop applications configuration:
- Enable "Allow public client flows"
-
Initial authentication (works):
kubectl oidc_login get-token \ --oidc-issuer-url=https://sts.windows.net/<tenant id>/ \ --oidc-client-id=<client id> \ --oidc-use-pkce \ --force-refresh
-
Subsequent authentication (fails):
Run the exact same command again. This time it will fail with the error:error: get-token: authentication error: authcode-browser error: authentication error: authorization code flow error: oauth2 error: could not exchange the code and token: oauth2: "invalid_request" "AADSTS900144: The request body must contain the following parameter: 'client_id'. Trace ID: [MASKED] Correlation ID: [MASKED] Timestamp: 2024-11-29 07:25:10Z" "https://login.windows.net/error?code=900144"
Debug Logs
Working Scenario (First Authentication)
First attempt (fails but triggers retry):
I1129 08:20:55.206480 1779364 oauth2cli.go:156] oauth2cli: exchanging the code and token
I1129 08:20:55.207179 1779364 transport.go:30] POST /[MASKED]/oauth2/token HTTP/1.1
Host: login.windows.net
User-Agent: Go-http-client/1.1
Content-Length: 997
Authorization: Basic [MASKED]
Content-Type: application/x-www-form-urlencoded
Accept-Encoding: gzip
code=[MASKED]&code_verifier=[MASKED]&grant_type=authorization_code&redirect_uri=http%3A%2F%2Flocalhost%3A8000
I1129 08:20:55.491795 1779364 transport.go:40] HTTP/1.1 400 Bad Request
{"error":"invalid_request","error_description":"AADSTS900144: The request body must contain the following parameter: 'client_id'. Trace ID: [MASKED] Correlation ID: [MASKED] Timestamp: 2024-11-29 07:20:55Z","error_codes":[900144],"timestamp":"2024-11-29 07:20:55Z","trace_id":"[MASKED]","correlation_id":"[MASKED]","error_uri":"https://login.windows.net/error?code=900144"}
Second attempt (succeeds with client_id):
I1129 08:20:55.492467 1779364 transport.go:30] POST /[MASKED]/oauth2/token HTTP/1.1
Host: login.windows.net
User-Agent: Go-http-client/1.1
Content-Length: 1044
Content-Type: application/x-www-form-urlencoded
Accept-Encoding: gzip
client_id=[MASKED]&code=[MASKED]&code_verifier=[MASKED]&grant_type=authorization_code&redirect_uri=http%3A%2F%2Flocalhost%3A8000
I1129 08:20:55.735417 1779364 transport.go:40] HTTP/1.1 200 OK
Failing Scenario (Subsequent Authentication with Refresh Token)
Single attempt (fails with no retry):
I1129 08:23:17.783488 1780146 oauth2cli.go:156] oauth2cli: exchanging the code and token
I1129 08:23:17.783792 1780146 transport.go:30] POST /[MASKED]/oauth2/token HTTP/1.1
Host: login.windows.net
User-Agent: Go-http-client/1.1
Content-Length: 997
Authorization: Basic [MASKED]
Content-Type: application/x-www-form-urlencoded
Accept-Encoding: gzip
code=[MASKED]&code_verifier=[MASKED]&grant_type=authorization_code&redirect_uri=http%3A%2F%2Flocalhost%3A8000
I1129 08:23:17.969705 1780146 transport.go:40] HTTP/1.1 400 Bad Request
{"error":"invalid_request","error_description":"AADSTS900144: The request body must contain the following parameter: 'client_id'. Trace ID: [MASKED] Correlation ID: [MASKED] Timestamp: 2024-11-29 07:23:17Z","error_codes":[900144],"timestamp":"2024-11-29 07:23:17Z","trace_id":"[MASKED]","correlation_id":"[MASKED]","error_uri":"https://login.windows.net/error?code=900144"}
I1129 08:23:17.969887 1780146 get_token.go:74] releasing the lock of token cache
error: get-token: authentication error: authcode-browser error: authentication error: authorization code flow error: oauth2 error: could not exchange the code and token: oauth2: "invalid_request" "AADSTS900144: The request body must contain the following parameter: 'client_id'. Trace ID: [MASKED] Correlation ID: [MASKED] Timestamp: 2024-11-29 07:23:17Z" "https://login.windows.net/error?code=900144"
I1129 08:23:17.969946 1780146 cmd.go:76] stacktrace: get-token: authentication error: authcode-browser error: authentication error: authorization code flow error: oauth2 error: could not exchange the code and token: oauth2: "invalid_request" "AADSTS900144: The request body must contain the following parameter: 'client_id'. Trace ID: [MASKED] Correlation ID: [MASKED] Timestamp: 2024-11-29 07:23:17Z" "https://login.windows.net/error?code=900144"
Technical Details
During the first authentication:
- The initial token exchange request fails due to missing
client_id - A second attempt is made with
client_idincluded in the request body - The authentication succeeds
During subsequent authentications with cached refresh token:
- The token exchange request fails due to missing
client_id - No second attempt is made
- The authentication fails
Note: The refresh token path doesn't work with Azure because Azure doesn't reply with a new id_token during refresh. As a result, kubelogin continues with AuthCodeBrowserOption.
Your environment
- OS: Ubuntu 20.04.4 LTS
- kubelogin version: v1.31.0
- kubectl version: v1.24.17
- OpenID Connect provider: Azure