iceberg icon indicating copy to clipboard operation
iceberg copied to clipboard

Core: Stop fetchToken from sending the Authorization header

Open okumin opened this issue 4 months ago • 1 comments

The current implementation stores the retrieved access token in AuthSession#headers, and the AuthSession and its headers are reused. This causes the OAuth2Manager sends an access token via the Authorization header as well as client ID and credential via the request-body at the next access token retrieval. I found Okta could not process such a request.

Reading RFC 6749, I guess we should have supported the basic auth. However, it is unclear all Iceberg environments can use the basic authentication anywhere. So, this pull request retains the policy by just removing the Authorization header from the token request.

  • https://datatracker.ietf.org/doc/html/rfc6749#section-4.4.2
  • https://datatracker.ietf.org/doc/html/rfc6749#section-3.2.1
  • https://datatracker.ietf.org/doc/html/rfc6749#section-2.3

Reproduction with curl

I would be able to successfully fetch an access token without the Authorization header.

% curl --request POST \
  --url "https://$OKTA_HOST/oauth2/$OKTA_APP_ID/v1/token" \
  --header 'accept: application/json' \
  --header 'cache-control: no-cache' \
  --header 'content-type: application/x-www-form-urlencoded' \
  --data "grant_type=client_credentials&scope=catalog&client_id=$CLIENT_ID&client_secret=$CLIENT_SECRET"
{"token_type":"Bearer","expires_in":3600,"access_token":"eyJraWQ...","scope":"catalog"}

However, with the Authorization header, Okta rejects a request.

% curl --request POST \
  --url "https://$OKTA_HOST/oauth2/$OKTA_APP_ID/v1/token" \
  --header 'accept: application/json' \
  --header 'authorization: Bearer yJraWQ...' \
  --header 'cache-control: no-cache' \
  --header 'content-type: application/x-www-form-urlencoded' \
  --data "grant_type=client_credentials&scope=catalog&client_id=$CLIENT_ID&client_secret=$CLIENT_SECRET"
{"errorCode":"invalid_client","errorSummary":"No client credentials found.","errorLink":"invalid_client","errorId":"oaeEin5lLeIRkeFNOSXPBrsLQ","errorCauses":[]}

This is the stacktrace I encountered.

Caused by: org.apache.iceberg.exceptions.RESTException: Unable to process: {"errorCode":"invalid_client","errorSummary":"No client credentials found.","errorLink":"invalid_client","errorId":"oaeFeryoPYSR8q6IDMlSqNVrA","errorCauses":[]}
	at org.apache.iceberg.rest.ErrorHandlers$OAuthErrorHandler.accept(ErrorHandlers.java:281)
	at org.apache.iceberg.rest.ErrorHandlers$OAuthErrorHandler.accept(ErrorHandlers.java:252)
	at org.apache.iceberg.rest.HTTPClient.throwFailure(HTTPClient.java:215)
	at org.apache.iceberg.rest.HTTPClient.execute(HTTPClient.java:299)
	at org.apache.iceberg.rest.BaseHTTPClient.postForm(BaseHTTPClient.java:111)
	at org.apache.iceberg.rest.auth.OAuth2Util.fetchToken(OAuth2Util.java:267)
	at org.apache.iceberg.rest.auth.OAuth2Util$AuthSession.fromCredential(OAuth2Util.java:709)
	at org.apache.iceberg.rest.auth.OAuth2Manager.newSessionFromCredential(OAuth2Manager.java:219)
	at org.apache.iceberg.rest.auth.OAuth2Manager.lambda$maybeCreateChildSession$2(OAuth2Manager.java:193)
	at com.github.benmanes.caffeine.cache.BoundedLocalCache.lambda$doComputeIfAbsent$14(BoundedLocalCache.java:2704)
	at java.base/java.util.concurrent.ConcurrentHashMap.compute(ConcurrentHashMap.java:1932)
	at com.github.benmanes.caffeine.cache.BoundedLocalCache.doComputeIfAbsent(BoundedLocalCache.java:2702)
	at com.github.benmanes.caffeine.cache.BoundedLocalCache.computeIfAbsent(BoundedLocalCache.java:2684)
	at com.github.benmanes.caffeine.cache.LocalCache.computeIfAbsent(LocalCache.java:112)
	at com.github.benmanes.caffeine.cache.LocalManualCache.get(LocalManualCache.java:63)
	at org.apache.iceberg.rest.auth.AuthSessionCache.cachedSession(AuthSessionCache.java:88)
	at org.apache.iceberg.rest.auth.OAuth2Manager.maybeCreateChildSession(OAuth2Manager.java:191)
	at org.apache.iceberg.rest.auth.OAuth2Manager.contextualSession(OAuth2Manager.java:140)
	at org.apache.iceberg.rest.auth.OAuth2Manager.contextualSession(OAuth2Manager.java:40)
	at org.apache.iceberg.rest.RESTSessionCatalog.loadInternal(RESTSessionCatalog.java:370)
	at org.apache.iceberg.rest.RESTSessionCatalog.loadTable(RESTSessionCatalog.java:397)
	at io.trino.plugin.iceberg.catalog.rest.TrinoRestCatalog.lambda$loadTable$0(TrinoRestCatalog.java:505)

okumin avatar Nov 10 '25 10:11 okumin

This pull request has been marked as stale due to 30 days of inactivity. It will be closed in 1 week if no further activity occurs. If you think that’s incorrect or this pull request requires a review, please simply write any comment. If closed, you can revive the PR at any time and @mention a reviewer or discuss it on the [email protected] list. Thank you for your contributions.

github-actions[bot] avatar Dec 12 '25 00:12 github-actions[bot]

This pull request has been closed due to lack of activity. This is not a judgement on the merit of the PR in any way. It is just a way of keeping the PR queue manageable. If you think that is incorrect, or the pull request requires review, you can revive the PR at any time.

github-actions[bot] avatar Dec 19 '25 00:12 github-actions[bot]