Skip to content

Conversation

@adutra
Copy link
Contributor

@adutra adutra commented Aug 19, 2025

Summary of changes:

  • Instead of including the principal id twice in the token, the principal name is now used as the subject claim. While the default authenticator doesn't need the principal name and works with just the principal id, not having the "real" principal name available could be a problem for other authenticator implementations.

  • DecodedToken has been refactored and renamed to InternalPolarisCredential. It is also now a package-private component as it is an implementation detail of Polaris internal auth mechanism.

  • TokenBroker.verify() now returns PolarisCredential.

* @see JWTBroker
*/
@PolarisImmutable
abstract class InternalPolarisCredential implements PolarisCredential {
Copy link
Contributor

Choose a reason for hiding this comment

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

[optional : may be another name ?] isn't it still a decoded bearer token ? maybe its just me but i find it a little bit hard to disassociate with the client crendentials flow semantics, which typically requires client secret

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'm not opposed to other names.

My rationale is: this component represents credentials extracted from an internal polaris token, hence the name I picked.

Let's wait for more feedback from other reviewers and I'll change the name accordingly.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Would PolarisToken work for you?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

(or InternalPolarisToken)

Copy link
Contributor

@singhpk234 singhpk234 Aug 19, 2025

Choose a reason for hiding this comment

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

InternalPolarisToken

works for me ! This comment is totally optional to address, agree for waiting for more peoplr to weigh in :) !

Summary of changes:

- Instead of including the principal id twice in the token, the principal name is now used as the subject claim. While the default authenticator doesn't need the principal name and works with just the principal id, not having the "real" principal name available could be a problem for other authenticator implementations.

- `DecodedToken` has been refactored and renamed to `InternalPolarisCredential`. It is also now a package-private component.

- `TokenBroker.verify()` now returns PolarisCredential.
@adutra adutra force-pushed the decoded-token-enhancements branch from d3a0eee to a74ac4a Compare September 16, 2025 15:48
@adutra adutra requested a review from singhpk234 September 16, 2025 15:48
@adutra adutra force-pushed the decoded-token-enhancements branch from a74ac4a to 88c9a03 Compare September 16, 2025 16:20
String principalName, long principalId, String clientId, String scope) {
Instant now = Instant.now();
return JWT.create()
.withIssuer(ISSUER_KEY)
Copy link
Contributor

Choose a reason for hiding this comment

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

side note: it might be worth setting aud to the realm ID and later validating it (for follow up). WDYT?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

We could definitely include the realm in the token, but I'm not sure about using the aud claim. In all compliance with the specs, this claim should contain the URI of the Polaris service:

https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.3

But, it could also contain a simple string as well, and the interpretation of that value is application-specific.

Maybe a separate claim e.g. polaris_realm would be better?


} catch (JWTVerificationException e) {
return InternalPolarisToken.of(
decodedJWT.getSubject(),
Copy link
Contributor

Choose a reason for hiding this comment

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

I guess this might have issues during rolling upgrades as old tokens might still have sub == principal ID.

I do not think it is a critical issue, but might be worth mentioning in CHANGELOG.md. WDYT?

Copy link
Contributor Author

@adutra adutra Sep 16, 2025

Choose a reason for hiding this comment

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

I think we are fine: the DefaultAuthenticator inspects PolarisCredential.getPrincipalId() and PolarisCredential.getPrincipalName(), and these fields are mapped as follows:

Source claim before this PRSource claim after this PR
getPrincipalId()principal_idprincipal_id
getPrincipalName()(none)sub

Copy link
Contributor Author

Choose a reason for hiding this comment

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

So, if a token generated by an old JWTBroker is processed by a new JWTBroker, getPrincipalName() would return the string representation of the principal ID which would result in a failed lookup, but getPrincipalId() would still return the principal ID in numeric form, and that lookup would succeed.

Copy link
Contributor

Choose a reason for hiding this comment

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

Good point! Thanks for the clarification 👍

@adutra adutra added this to the 1.2.0 milestone Sep 16, 2025
@github-project-automation github-project-automation bot moved this from PRs In Progress to Ready to merge in Basic Kanban Board Sep 16, 2025
@adutra adutra merged commit d91dbd0 into apache:main Sep 19, 2025
14 checks passed
@adutra adutra deleted the decoded-token-enhancements branch September 19, 2025 16:11
@github-project-automation github-project-automation bot moved this from Ready to merge to Done in Basic Kanban Board Sep 19, 2025
snazy added a commit to snazy/polaris that referenced this pull request Nov 20, 2025
* Avoid calling deprecated `TableMetadataParser.read(FileIO, InputFile)` method. (apache#2609)

Call `read(InputFile)` instead, as instructed by Iceberg javadoc.

* Add doc notes about EclipseLink removal (apache#2605)

* chore(docs): add polaris-api-specs section (apache#2598)

* docs(README): Updating the READMEs to Reflect the Project Structure (apache#2599)

* docs(README): Updating the READMEs to Reflect the Project Structure

* fix(deps): update dependency io.opentelemetry:opentelemetry-bom to v1.54.1 (apache#2613)

* Add Code of Conduct entry to the ASF menu (apache#2537)

* Use the ASF Code Of Conduct

* Update site/hugo.yaml

Co-authored-by: Robert Stupp <snazy@snazy.de>

---------

Co-authored-by: Robert Stupp <snazy@snazy.de>

* fix(deps): update dependency org.postgresql:postgresql to v42.7.8 (apache#2619)

* chore(deps): update dependency mypy to >=1.18, <=1.18.2 (apache#2617)

* Update registry.access.redhat.com/ubi9/openjdk-21-runtime Docker tag to v1.23-6.1758133907 (apache#2612)

* Introduce alternate in-memory buffering event listener (apache#2574)

* fix(deps): update dependency org.assertj:assertj-core to v3.27.5 (apache#2618)

* chore(deps): update dependency virtualenv to >=20.34.0,<20.35.0 (apache#2614)

* Add Community Meeting 20250918 (apache#2622)

* Add 1.1.0-incubating release on the website (apache#2621)

* Add 1.1.0-incubating release content (apache#2625)

* chore(errorprone): Enabling EqualsGetClass, PatternMatchingInstanceof, and UnusedMethod in ErrorProne (apache#2600)

* fix(deps): update dependency com.adobe.testing:s3mock-testcontainers to v4.9.1 (apache#2626)

* Unify create/loadTable call paths (apache#2589)

In preparation for implementing sending non-credential config
to REST Catalog clients for apache#2207 this PR unifies calls paths
for create/load table operations.

This change does not have any differences in authorization.

This change is not expecte to have any material behaviour
differences to the affected code paths.

The main idea is to consolidate decision-making for that
to include into REST responses and use method parameters
like `EnumSet<AccessDelegationMode> delegationModes` for
driving those decisions.

* Remove numeric identifier from PolarisPrincipal (apache#2388)

This change removes the requirement for Polaris principals to have a numeric identifier, by removing the only sites where such an identifier was required:

- In the `Resolver`. Instead, the `Resolver` now performs a lookup by principal name.
- In  `PolarisAdminService`. Instead, the code now compares the principal name against the entity name.

Note: the lookup in the `Resolver` is still necessary, because the `Resolver` also needs to fetch the grant records.

* Include principal name in Polaris tokens (apache#2389)

* Include principal name in Polaris tokens

Summary of changes:

- Instead of including the principal id twice in the token, the principal name is now used as the subject claim. While the default authenticator doesn't need the principal name and works with just the principal id, not having the "real" principal name available could be a problem for other authenticator implementations.

- `DecodedToken` has been refactored and renamed to `InternalPolarisCredential`. It is also now a package-private component.

- `TokenBroker.verify()` now returns PolarisCredential.

* rename to InternalPolarisToken

* main: bump to 1.2.0-incubating-SNAPSHOT (apache#2624)

* bump version.txt to 1.2.0-incubating-SNAPSHOT

* virtualenv: wider version range (apache#2623)

see apache#2614 (comment)

* Remove ActiveRolesProvider (apache#2390)

Summary of changes:

- As proposed on the ML, `ActiveRolesProvider` is removed, and `DefaultActiveRolesProvider` is merged into `DefaultAuthenticator`. `ActiveRolesAugmentor` is also merged into `AuthenticatingAugmentor`.

- The implicit convention that no roles in credentials == all roles requested is removed as it is ambiguous. Credentials must explicitly include the `PRINCIPAL_ROLE:ALL` pseudo-role to request all roles available.

- PersistedPolarisPrincipal is removed. It existed merely as a means of passing the `PrincipalEntity` from the authenticator to the roles provider. This is not necessary anymore.

* NoSQL: adaptions

* Last merged commit d1d359a

---------

Co-authored-by: Dmitri Bourlatchkov <dmitri.bourlatchkov@gmail.com>
Co-authored-by: Artur Rakhmatulin <artur.rakhmatulin@gmail.com>
Co-authored-by: Adam Christian <105929021+adam-christian-software@users.noreply.github.com>
Co-authored-by: Mend Renovate <bot@renovateapp.com>
Co-authored-by: JB Onofré <jbonofre@apache.org>
Co-authored-by: Alexandre Dutra <adutra@apache.org>
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.

3 participants