Skip to content

feat(rest): support OAuth2 token exchange sessions - #867

Merged
wgtmac merged 3 commits into
apache:mainfrom
lishuxu:feature/oauth-1
Aug 24, 2026
Merged

feat(rest): support OAuth2 token exchange sessions#867
wgtmac merged 3 commits into
apache:mainfrom
lishuxu:feature/oauth-1

Conversation

@lishuxu

@lishuxu lishuxu commented Aug 2, 2026

Copy link
Copy Markdown
Contributor

Add RFC 8693 token exchange support, including OAuth2 endpoint handling and response parsing. Create contextual and table child sessions from direct tokens, credentials, or typed tokens.

Keep OAuth2 metadata in one synchronized session snapshot. Use shared HttpClient ownership so refresh tasks can safely keep the client alive. Align token expiry with Java by preferring JWT exp and otherwise using the request start time plus expires_in.

Move OAuth2 helpers into OAuth2Util and update unit and integration tests. Leave catalog token refresh, token exchange during refresh, and child session caching as follow-up work.

Comment thread src/iceberg/catalog/rest/auth/auth_manager.cc
Comment thread src/iceberg/catalog/rest/auth/auth_manager.cc
HttpClient& client,
const std::unordered_map<std::string, std::string>& properties) override {
ICEBERG_ASSIGN_OR_RAISE(auto config, AuthProperties::FromProperties(properties));
shared_client_ = &client;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shared_client_ is a borrowed HttpClient*, but child sessions use it after this call. Please pass a std::shared_ptr<HttpClient> through the manager/session API so the client lifetime is explicit.

// Determine expiration time
expires_at_ = std::chrono::steady_clock::time_point{};
if (token_response.expires_in_secs.has_value()) {
expires_at_ = std::chrono::steady_clock::now() +

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

expires_in is measured from the token request, but the session starts the clock later. A slow config request can consume part of the token lifetime; please carry the init fetch start time into the session.

if (endpoint.starts_with('/')) {
return base_uri + endpoint;
}
return base_uri + "/" + std::string(TrimTrailingSlash(endpoint));

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Java preserves the relative endpoint suffix. Trimming oauth/token/ here changes the resolved URI; please keep the trailing slash and update the test.

Result<std::string> ResolveOAuth2ServerUri(
const std::unordered_map<std::string, std::string>& properties) {
auto endpoint_it = properties.find(AuthProperties::kOAuth2ServerUri.key());
std::string endpoint = endpoint_it == properties.end() || endpoint_it->second.empty()

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Java defaults only when oauth2-server-uri is absent. This also defaults an explicitly empty value; please preserve that distinction or reject empty explicitly.

std::unordered_map<std::string, std::string> properties = {
{AuthProperties::kAuthType, "oauth2"},
{AuthProperties::kToken.key(), "my-static-token"},
{AuthProperties::kCredential.key(), "client-id:client-secret"},

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add a test with a short expires_in and delayed config fetch to verify elapsed init time is deducted from the session lifetime.

EXPECT_THAT(root->WithContext(SessionContext{}), IsError(ErrorKind::kInvalidArgument));
}

TEST_F(RestCatalogIntegrationTest, OAuthContextCredentialEndToEnd) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These tests call AuthManager directly, so they do not cover RestCatalog context/table wiring. Please add one real catalog path or move them to the unit suite.

shuxu.li added 2 commits August 23, 2026 11:48
Add RFC 8693 token exchange support, including token type helpers,
request form construction, OAuth endpoint normalization, and response
handling.

Preserve OAuth metadata in auth sessions and create contextual and
table-scoped child sessions from direct tokens, credentials, or typed
tokens. Disable child refresh until session lifecycle management is
available.
    Add RFC 8693 token exchange support, including token type helpers,
    request form construction, OAuth endpoint normalization, and response
    handling.

    Preserve OAuth metadata in auth sessions and create contextual and
    table-scoped child sessions from direct tokens, credentials, or typed
    tokens. Disable child refresh until session lifecycle management is
    available.
@wgtmac

wgtmac commented Aug 23, 2026

Copy link
Copy Markdown
Member

As discussed offline, I'll directly address these minor issues to move forward.

@wgtmac

wgtmac commented Aug 24, 2026

Copy link
Copy Markdown
Member

I've made some changes to this PR. The intention is to be more Java-like so future feature catch-up and review will be much easier.

  • HttpClient now uses std::shared_ptr through the auth flow. The session can refresh in the background, so it must keep the client alive.
  • OAuth2Session is now a separate internal class.
  • Token expiry now follows Java. JWT exp takes precedence. Otherwise, expiry is based on the token request start time plus expires_in.
  • OAuth2Util is now a class so we are able to have internal functions.
  • I updated the related unit and integration tests by removing meaningless cases.

- propagate shared HttpClient ownership through REST auth managers
- preserve OAuth2 session state and request-start expiry semantics
- expose OAuth2 metadata through a synchronized OAuth2Info snapshot
- encapsulate OAuth2 utilities and normalize token endpoints
- update REST auth and integration tests

@wgtmac wgtmac left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let me merge this to proceed. Thanks @lishuxu!

@wgtmac wgtmac changed the title feat(rest): support OAuth token exchange sessions feat(rest): support OAuth2 token exchange sessions Aug 24, 2026
@wgtmac
wgtmac merged commit 2377328 into apache:main Aug 24, 2026
18 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants