jsr375-experts@javaee-security-spec.java.net

[jsr375-experts] Re: Identity store - handling a custom principal and interface only

From: Rudy De Busscher <rdebusscher_at_gmail.com>
Date: Wed, 13 Jan 2016 15:51:40 +0100

Hi Arjan,

I did look up a few things and though about how you can use multiple
identity stores. (hope I did understand the Required, Requisite etc
correctly )

And basically, everything comes down to 2 scenarios when you have multiples
stores.

*scenario1*
You have for example an LDAP with your internal users and DB for some users
outside of your company and they all need to have access to your
application.

So if the user is found correctly within the LDAP or DB Table, it is OK.
This corresponds with the 'Sufficient' option on both If I'm correct.

And an Order/Properity here can be nice if you know that for example 99%
of your users will be found in the LDAP so that you can check that first.
But it is not needed.

*scenario2*
Since you have multiple stores you could check if the user is available in
both and pass the authentication check. And it passes only if both stores
says they are OK with it. But why should you do that?


*Other scenarios*
There are of course many combinations possible of 'Required', 'Requisite',
... but don't see many use cases for them.

For example, you could have the scenario where the first store is used to
'Identify' the user and the second store to see if (s)he has has access to
the application. But that can be solved differently.

*Conclusion*
So I think option 2 (Ordered in some way (@Priority?), only consider
success/fail) is sufficient.

Of course you could make it far more complex by implementing option 3. (but
you make it overly complex for those 1 or 2 cases it would be nice to have
PAM/JAAS rules but you are capable of solving it also with an option 2 code
base and some additional code in your app [as you will be able to create
your own custom implementation an Identity store and do whatever you like,
as calling for instance a default store])

Hope the above makes my ideas clear enough.

Regards
Rudy






On 13 January 2016 at 13:25, arjan tijms <arjan.tijms_at_gmail.com> wrote:

> Hi Rudy,
>
> Did you give the concerns below some consideration already?
>
> Would be cool to see how far we can get with the multiple stores story. I
> think the options are:
>
> 1. No order at all (like you suggested), only consider success/fail
> 2. Ordered in some way (@Priority?), only consider success/fail
> 3. Ordered in some way (@Priority?), process according to PAM/JAAS rules
>
> Kind regards,
> Arjan Tijms
>
>
>
>
>
>
> On Wed, Dec 30, 2015 at 7:49 PM, arjan tijms <arjan.tijms_at_gmail.com>
> wrote:
>
>> Hi,
>>
>> On Wed, Dec 30, 2015 at 4:57 PM, Rudy De Busscher <rdebusscher_at_gmail.com>
>> wrote:
>>
>>> It's via the highlander rule now (there can be only one).
>>>
>>>
>>> I think we can allow easily multiple ones.
>>>
>>
>> Well, yes and no.
>>
>> The problem is that with multiple stores people quickly want to have
>> something more than just iterating until one is valid. The default model to
>> take into account then is the PAM inspired one as used by JAAS and many
>> other security systems. This is the model with Required, Requisite, Sufficient
>> and Optional.
>>
>> See
>> http://docs.oracle.com/javase/6/docs/api/javax/security/auth/login/Configuration.html
>>
>> There's an existing issue for this, see
>> https://java.net/jira/browse/JASPIC_SPEC-15
>>
>> Typically in these models ordering is critical though, as there's often a
>> primary store and a fallback one. It can also be a multi-dimensional
>> problem, as you can have both multiple authentication mechanisms (e.g.
>> primary certificate, fallback form), as well as multiple identity stores
>> (like you mention, primary LDAP, fallback (local) database).
>>
>> Then to make it a little bit more complicated, there's another dimension
>> and that's letting the user choose an authentication mechanism. See
>> https://java.net/jira/browse/JASPIC_SPEC-16 This will likely be less of
>> a problem for the identity store part, as I think you'd normally not let
>> the user choose that directly.
>>
>> I experimented a little with it all here:
>> https://github.com/omnifaces/omnisecurity/blob/master/src/main/java/org/omnifaces/security/jaspic/factory/OmniServerAuthContext.java#L101
>>
>> That one shows how a stack of "modules" is retrieved, which depends on
>> which method the user choose (e.g. Facebook, Google, name/password), and
>> then each stack of modules is iterated over (in order) and the outcome
>> processed according to the PAM/JAAS rules of stacking.
>>
>> The classes themselves including a builder API for creating stacks can be
>> found here:
>> https://github.com/omnifaces/omnisecurity/tree/master/src/main/java/org/omnifaces/security/jaspic/config
>>
>> So it's quite a discussion perhaps how to best support this.
>>
>> Kind regards,
>> Arjan Tijms
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>>
>>> If the Status.NOT_VALIDATED or INVALID is returned, we can go to the
>>> next one. We stop the looping when we encounter a Status.VALID.
>>>
>>> We can add some kind of ordering, but it is generally not needed. (we
>>> could foresee a method in the IdentityStore interface which returns an
>>> ordinal number on which the sorting is performed)
>>>
>>> This way we can allow for multiple sources to be used at the same time
>>> (for example Database and LDAP)
>>>
>>> Regards
>>> Rudy
>>>
>>> On 30 December 2015 at 16:44, arjan tijms <arjan.tijms_at_gmail.com> wrote:
>>>
>>>> Hi,
>>>>
>>>> On Wed, Dec 30, 2015 at 12:08 PM, Rudy De Busscher <
>>>> rdebusscher_at_gmail.com> wrote:
>>>>
>>>>> Question:
>>>>> There are 3 annotations defined for concrete implementations of the
>>>>> IdentityStore. How is a custom definition found by the system?
>>>>>
>>>>
>>>> It's via the highlander rule now (there can be only one). The
>>>> annotations are scanned by the CDI extension and based on them they add 1
>>>> enabled implementation of IdentityStore. Likewise, if a custom definition
>>>> is used, it's simply a class implementing IdentityStore.
>>>>
>>>> The other code just asks CDI for an IdentityStore implementation, and
>>>> doesn't care how it was added; by an class on the class path implementing
>>>> that interface or by a CDI extension that programmatically added a Bean<T>.
>>>>
>>>>
>>>>> Should we consider also CDI beans which implement the IdentityStore
>>>>> interface?
>>>>>
>>>>
>>>> That's in fact the one and only method now ;) The annotations just
>>>> cause such bean to be made programmatically available.
>>>>
>>>> Kind regard,
>>>> Arjan
>>>>
>>>>
>>>>
>>>>>
>>>>> Hope to see other people their comments or approval to your nice
>>>>> proposal.
>>>>>
>>>>> regards
>>>>> Rudy
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>
>>>>> On 29 December 2015 at 16:47, arjan tijms <arjan.tijms_at_gmail.com>
>>>>> wrote:
>>>>>
>>>>>> Hi,
>>>>>>
>>>>>> I think we're quite close to a final proposal for the identity store
>>>>>> interface. The latest proposal is really quite workable. See
>>>>>> https://github.com/javaee-security-spec/javaee-security-proposals/tree/master/authentication/identity-store/identity-store-readonly-simplified
>>>>>>
>>>>>>
>>>>>> There are however a few things that I think could still be improved.
>>>>>>
>>>>>> Currently not all types are fully interface based. E.g.
>>>>>> CredentialValidationResult is now a class and not an interface. For a spec
>>>>>> with a clear API/implementation split I think CredentialValidationResult
>>>>>> could better be an interface, with the implementation being provided by the
>>>>>> RI.
>>>>>>
>>>>>> See
>>>>>> https://github.com/javaee-security-spec/javaee-security-proposals/blob/master/authentication/identity-store/identity-store-readonly-simplified/src/main/java/javax/security/identitystore/CredentialValidationResult.java
>>>>>>
>>>>>> Another thing is that there's no support for a custom Principal now.
>>>>>> This again concerns CredentialValidationResult, which now only contains a
>>>>>> "String getCallerName()".
>>>>>>
>>>>>> What we could do is add a "Principal getCallerPrincipal()" method, OR
>>>>>> an "Optional<Principal> getCallerPrincipal()" method.
>>>>>>
>>>>>> Semantics would be that if Principal is not-null/present then the
>>>>>> custom principal is to be used, otherwise the getCallerName() has to be
>>>>>> used.
>>>>>>
>>>>>> Alternatively, we only define a getPrincipal() method. This could
>>>>>> even possibly return a subtype of java.security.Principal,
>>>>>> say javax.security.CallerPrincipal (an interface too). Default identity
>>>>>> stores would then return a direct implementation of
>>>>>> javax.security.CallerPrincipal, where custom identity stores can return a
>>>>>> more elaborate implementation with fields that only the application knows
>>>>>> about.
>>>>>>
>>>>>> Thoughts?
>>>>>>
>>>>>> Kind regards,
>>>>>> Arjan Tijms
>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>
>>>>
>>>
>>
>