users@javaee-security-spec.java.net

[javaee-security-spec users] [jsr375-experts] Re: Updated Multi IdentityStore Proposal

From: arjan tijms <arjan.tijms_at_gmail.com>
Date: Mon, 19 Sep 2016 13:04:55 +0200

P.s.

By making the "get groups only" operation a special case, we could
introduce a method like:

List<String> getGroupsByCaller(CallerPrincipal caller);

This would move a bit back to Alex' original proposal, and it wouldn't be
my first choice (I much prefer the single method IdentityStore), but could
be a good compromise.

Rudy, would that work for you? Is there anyone else having an opinion about
this?

The default multi-store algorithm would then be:


    @Override
    public CredentialValidationResult validate(Credential credential) {

        CredentialValidationResult validationResult = null;

        // "Authenticate" - Check credential

        for (IdentityStore authenticationIdentityStore :
authenticationIdentityStores) {
            validationResult = authenticationIdentityStore.
validate(credential);
            if (validationResult.getStatus() == VALID) {
                break;
            }
        }

        if (validationResult.getStatus() != VALID) {
            // No store authenticated, no need to continue
            return validationResult;
        }

        CallerPrincipal caller = validationResult.getCallerPrincipal();
        List<String> groups = new ArrayList<>(validationResult.
getCallerGroups());


        // "Authorise" -> Get Groups

        for (IdentityStore authorizationIdentityStore :
authorizationIdentityStores) {
            groups.addAll(authorizationIdentityStore.
getGroupsByCaller(caller));
        }

        return new CredentialValidationResult(VALID, caller, groups);
    }


Kind regards,
Arjan Tijms

On Sun, Sep 18, 2016 at 9:30 PM, arjan tijms <arjan.tijms_at_gmail.com> wrote:

> On Sun, Sep 18, 2016 at 8:41 PM, Rudy De Busscher <rdebusscher_at_gmail.com>
> wrote:
>
>>
>> I was just looking at the actual looping algorithm again here, but wasn't
>>> it the idea that we would try all identity stores until one succeeds?
>>>
>>
>>
>> And if the first one that succeeds does only authentication, and not
>> authorization? We don't have any groups then.
>>
>
> No that's not the case, it can return the groups at that point.
>
> The first one that succeeds returns a CredentialValidationResult with a
> CallerPrincipal and optionally one or more groups.
>
> As mentioned above, the "loop over stores until valid" is probably the
>> more common and expected approach, and additionally will also prevent this
>> rather major issue.
>>
>> But then authorization and authentication can't be separated. Something
>> which we do al the time.
>>
>
> It can absolutely still be separated. An identity store is free to not
> return any groups if it's in the authentication list, while stores
> configured for the authorisation list obviously only do authorization.
>
> In the most common case with 1 identity store, the two operations are
> combined. In many cases this is the most efficient way (i.e. only one query
> to the backend needed).
>
> If there are 2 identity stores, 1 can be used for authentication and if
> that succeeds the other can be used to retrieve the groups from. Hence the
> two operations are separated. See the algorithm sketch I provided a little
> bit below. First all stores that can do authentication are consulted, after
> that, optionally, all stores that only provide the groups are consulted.
>
> (btw, taking terminology into account you could say that what we call
> "authorization" is not actually authorization here. The list of groups is
> just part of the authenticated identity. True authorization happens when
> the caller actually attempts to access a resource and the authorization
> module checks the permissions needed for that against the groups/roles that
> the user is in)
>
> Kind regards,
> Arjan Tijms
>