Hi Alex, Selva,

Thanks Alex, that context is helpful. I agree my earlier read was too
narrow: simply switching PolarisPrincipal to expose the full
PrincipalEntity property map would blur the boundary between the
authenticated principal and the persisted entity, and it may conflict with
the detached-principal direction.

For PR #4292, I would not merge the direct property-copy approach as-is. If
a component needs the user-defined attributes of the persisted principal
entity, it should either fetch that entity explicitly or use a clearly
modeled security identity attribute, as Alex suggested, rather than making
PolarisPrincipal a carrier for all entity properties. This thread [1]
discussed a way by introducing a container named either
authenticatedMetadata or AuthorizationContext. I think that's the right
direction.

So I think the next step should be to clarify the intended contract first:

   - PolarisPrincipal should expose only authentication/principal identity
   data needed by authn/authz paths, potentially via an object like
   AuthorizationContext.
   - Arbitrary user-defined PrincipalEntity attributes should remain entity
   data, not implicit principal identity data.

Selva, thanks for opening the issue and PR. The test case and Ranger
integration are still useful because they capture the behavior gap and use
cases, but I think the fix should probably move in the direction Alex
outlined rather than expanding PolarisPrincipal directly.

1. https://lists.apache.org/thread/fmy8c43dmr8hmtrhphtcwp8yogqhkwqw

Yufei

On Sun, 26 Apr 2026 16:35:18 +0200, Alexandre Dutra [email protected] wrote:

Hi Selva,

I can provide some context on why only internal properties are
currently exposed in PolarisPrincipal.

Previously, PolarisPrincipal directly surfaced the underlying
PrincipalEntity. However, this direct dependency was removed to enable
alternative authentication mechanisms 1
<https://github.com/apache/polaris/pull/2307>.

A specific challenge during this transition was that several
components relied on inspecting the principal’s internal properties.
For example, the legacy code looked like this:

principal
.getPrincipalEntity()
.getInternalPropertiesAsMap()
.containsKey(PolarisEntityConstants.PRINCIPAL_CREDENTIAL_ROTATION_REQUIRED_STATE)

Because the code only required access to internal properties at that
time, we moved the internal properties map directly into
PolarisPrincipal. This simplified the access pattern to:

principal
.getProperties()
.containsKey(PolarisEntityConstants.PRINCIPAL_CREDENTIAL_ROTATION_REQUIRED_STATE)

With that, I have a few concerns regarding your proposal:

1) I am not sure that PolarisPrincipal should expose all attributes of
a PrincipalEntity. These are different concepts. If you are writing a
component that needs to access the properties of the entity
corresponding to the authenticated principal, I’d recommend fetching
the entity from the metastore explicitly.

2) We should not assume that all PolarisPrincipal instances are backed
by a PrincipalEntity. This may be true today, but the goal is to
achieve “detached” principals one day (principals not persisted in the
metastore).

3) I am uncertain if merging the entity’s internal and non-internal
property maps is a safe operation.

4) There is an ongoing conversation 2
<https://lists.apache.org/thread/fmy8c43dmr8hmtrhphtcwp8yogqhkwqw> about
redesigning the
PolarisPrincipal interface. Some contributors feel it already exposes
too much - such as the getToken() method. The preferred direction may
be to further isolate the principal from credentials and other
attributes. Adding more attributes now might conflict with that goal.

For example, a cleaner approach in my opinion could be for
authenticators to produce a Quarkus security identity with the
following shape:

SecurityIdentity:
- principal: PolarisPrincipal
- credentials:
- PolarisCredential (principal ID, name and roles)
- TokenCredential (the OAuth2 access token if available)
- etc.
- attributes:
- POLARIS_ENTITY => PolarisEntity (optional)

Then you would be able to inject the security identity and get the
entire principal entity from its attributes.

Thanks,
Alex

On Sat, Apr 25, 2026 at 6:55 AM Selvamohan Neethiraj
[email protected] wrote:

Hi Yufei,

Thank you for confirming that this is likely a bug and for pointing to the
relevant logic and PR reference.

I have created Issue #4291 to track this:
https://github.com/apache/polaris/issues/4291

I have also submitted a proposed fix along with test coverage in PR #4292:
https://github.com/apache/polaris/pull/4292

Could you please review the PR and share your feedback?

Thanks again for your guidance.

Regards,
Selva-

On Apr 24, 2026, at 7:44 PM, Yufei Gu [email protected] wrote:

Hi Selva,

It is likely a bug. The logic 1
<https://github.com/apache/polaris/pull/2307> was introduced in PR 23072
<https://lists.apache.org/thread/fmy8c43dmr8hmtrhphtcwp8yogqhkwqw>, before
that, getProperties() did not exist. I think using
principalEntity.getPropertiesAsMap() makes more sense in 1
<https://github.com/apache/polaris/pull/2307>.

1.
https://github-personal/flyrain/polaris/blob/4d90f53f2d360e622f0d6e3006dedcec497b1d38/polaris-core/src/main/java/org/apache/polaris/core/auth/PolarisPrincipal.java#L46
2. https://github.com/apache/polaris/pull/2307

Yufei

On Thu, Apr 23, 2026 at 6:10 PM Selvamohan Neethiraj [email protected]
wrote:

Following up on my earlier email, I was able to trace the issue and am now
trying to understand the reasoning behind the current implementation.

When a PolarisPrincipal (org.apache.polaris.core.auth.PolarisPrincipal) is
created from a PrincipalEntity
(org.apache.polaris.core.entity.PrincipalEntity), it appears to copy only
the internal properties using getInternalPropertiesAsMap(). This preserves
attributes such as clientId, but drops user-defined attributes.

Based on this behavior, it seems that using
principalEntity.getPropertiesAsMap() instead of
principalEntity.getInternalPropertiesAsMap() would retain both internal and
user-defined attributes.

Is there a specific reason why user-defined attributes are intentionally
excluded when creating a PolarisPrincipal object?

Regards,
Selva-

On Apr 23, 2026, at 1:34 PM, Selvamohan Neethiraj [email protected]
wrote:

Hi,

I am using the REST API /api/management/v1/principals to create a new
principal with user attributes (for example: region=northamerica). The API
call completes successfully, and the response correctly includes the
specified user attributes.

However, when I use the returned client-id and client-secret to obtain
an OAuth token from /api/catalog/v1/oauth/tokens, and then use that token
to perform other API operations (such as listing catalogs via
/api/management/v1/catalogs), the server-side Polaris principal does not
appear to include the user attributes.

Specifically, the user attributes defined during principal creation do
not seem to be available during subsequent API calls authenticated using
the generated OAuth token.

Could you please confirm:

   1. Whether this is the expected behavior, or
   2. If there is an additional step required to propagate or include
   principal attributes when generating or using OAuth tokens, or
   3. If this might be a bug.

Thanks in advance for your guidance.

Best regards,
Selva

Reply via email to