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
