Hi Alex

Thanks for this. Admittedly, the ActiveRolesProvider was *intended* to
support the future OIDC/Quarkus support, but that was long before the
current HttpAuthenticationMechanism.

I'm going to check out this branch and validate, but I think it's a good
change. It helps with some changes I had planned to make, but hadn't had a
chance to work on yet.

Mike

On Tue, Aug 19, 2025 at 6:49 AM Alexandre Dutra <adu...@apache.org> wrote:

> Hi all,
>
> I went ahead and created a PR implementing the proposed changes:
>
> https://github.com/apache/polaris/pull/2390
>
> Please take a look and let me know what you think.
>
> Thanks,
> Alex
>
> On Wed, Aug 13, 2025 at 9:58 AM Robert Stupp <sn...@snazy.de> wrote:
> >
> > Merging those two things SGTM.
> > It's what Quarkus/Vert.X
> > 'HttpAuthenticationMechanism'/'SecurityIdentity' do (right).
> >
> > On Wed, Aug 13, 2025 at 1:55 AM Dmitri Bourlatchkov <di...@apache.org>
> wrote:
> > >
> > > Thanks for starting this thread, Alex!
> > >
> > > I fully support merging Authenticator and ActiveRolesProvider.
> > >
> > > Aside from the issues you mentioned, from my perspective, it also makes
> > > sense conceptually. Authenticating a request implies establishing the
> > > principal's
> > > identity and consequently its roles. It is a single integration point.
> > > Mixing one
> > > Authenticator implementation with another Role Resolver looks really
> > > awkward.
> > >
> > > If some Authenticator implementations need to break this process down
> into
> > > two
> > > stages, it is ok, but Polaris core still receives one (immutable)
> Principal
> > > per request
> > > with relevant roles in it.
> > >
> > > Cheers,
> > > Dmitri.
> > >
> > > On Mon, Aug 4, 2025 at 6:45 AM Alexandre Dutra <adu...@apache.org>
> wrote:
> > >
> > > > Hi all,
> > > >
> > > > ActiveRolesProvider was introduced back in January, in order to
> enrich
> > > > SecurityContext with valid roles for a given principal.
> > > >
> > > > But that was before the introduction of Quarkus, and the introduction
> > > > of external authentication with Quarkus Security and OIDC.
> > > >
> > > > TLDR: ActiveRolesProvider became problematic since (see details
> > > > below), and I propose to merge ActiveRolesProvider into
> Authenticator.
> > > > This would make Authenticator the central component for resolving
> > > > principals and principal roles, significantly simplifying both code
> > > > and configuration.
> > > >
> > > > That's it :-) I'm eager to know what the community thinks.
> > > >
> > > > Thanks,
> > > > Alex
> > > >
> > > > ---------
> > > >
> > > > Now, for the interested readers, some low-level details.
> > > > ActiveRolesProvider is problematic because of its signature, and the
> > > > reliance on conventions:
> > > >
> > > > - Its signature expects an AuthenticatedPolarisPrincipal, thus
> forcing
> > > > the Authenticator to create a "temporary" instance of
> > > > AuthenticatedPolarisPrincipal, *potentially containing invalid
> roles*.
> > > > This makes the code error-prone. For example, let's assume a
> principal
> > > > has been granted "catalog_admin", but presents a JWT containing also
> > > > "service_admin":
> > > >
> > > > 1) JWT roles = [PRINCIPAL:ROLE:catalog_admin,
> PRINCIPAL:ROLE:service_admin]
> > > > 2) Authenticator: creates a temporary
> > > > AuthenticatedPolarisPrincipal{roles:[PRINCIPAL:ROLE:catalog_admin,
> > > > PRINCIPAL:ROLE:service_admin]}
> > > > 3) This temporary instance contains HIGHER privileges than the user
> was
> > > > granted!
> > > > 4) ActiveRolesProvider: removes the wrong role
> > > > 5) Final SecurityContext:
> > > > AuthenticatedPolarisPrincipal{roles:[PRINCIPAL_ROLE:catalog_admin]}
> > > >
> > > > While the final security context is correct and does not contain
> > > > "service_admin", the *temporary one does contain "service_admin" and
> > > > is thus dangerous*. It must not be leaked (injected or used).
> > > >
> > > > - Even worse, if this temporary instance contains invalid roles, by
> > > > convention the default Authenticator would filter out those roles,
> > > > while the default ActiveRolesProvider would (again, by convention)
> > > > assume that, since no roles were presented, then all roles should be
> > > > activated. This could allow a user to obtain more roles than the JWT
> > > > allows them to. Let's suppose a user has "service_admin", but
> presents
> > > > a token with wrong roles:
> > > >
> > > > 1) JWT roles = [foo, bar]
> > > > 2) Authenticator: was expecting "PRINCIPAL_ROLE:XYZ" => removes the
> roles
> > > > 3) Authenticator: creates a temporary
> > > > AuthenticatedPolarisPrincipal{roles:[]}
> > > > 4) ActiveRolesProvider: roles is empty => assumes PRINCIPAL_ROLE:ALL
> > > > => activates all roles
> > > > 5) Final SecurityContext:
> > > > AuthenticatedPolarisPrincipal{roles:[PRINCIPAL_ROLE:service_admin]}
> > > >
> > > > In the above scenario, the reliance on conventions results in the
> > > > principal getting higher activated roles than the JWT allowed (the
> JWT
> > > > above should have resulted in no roles activated). It's not a serious
> > > > security issue because only roles previously granted can be
> activated,
> > > > but it is concerning, because the original JWT did not contain such
> > > > roles.
> > > >
> > > > Merging ActiveRolesProvider into Authenticator fixes both of the
> issues.
> > > >
>

Reply via email to