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

[jsr375-experts] Re: Multi IdentityStore proposal

From: Ivar Grimstad <ivar.grimstad_at_gmail.com>
Date: Tue, 23 Aug 2016 05:56:10 +0000

Hi Arjan,

Without having looked at the consequences for implementers, I would say
that option 1 sounds like the best choice.

Ivar

On Mon, Aug 22, 2016 at 9:07 PM arjan tijms <arjan.tijms_at_gmail.com> wrote:

> Hi,
>
> Does someone else from the EG or user list have any input on this?
>
> Rudy, correct me if I'm wrong, but it think it boils down to
>
> 1. More explicit (but optional) configuration of which store does
> authentication (validate credentials) and which store does authorization
> (provide groups), but with identity stores that remain as simple as can be
> and the multi-algorithm fully pluggable.
>
> vs
>
> 2. No configuration other than ordering, with the implicit semantics that
> the first stores in the order authenticate (validate credentials), and once
> authentication has happened all stores coming after that authorize (provide
> groups), but with identity stores being required to check a passed-in
> status and act accordingly and the multi-algorithm somewhat hardcoded in
> the stores.
>
>
> For 2)
>
> The checks a store has to do are:
>
> if (partialValidationResult.getStatus() !=
> CredentialValidationResult.Status.AUTHENTICATED &&
> partialValidationResult.getStatus() !=
> CredentialValidationResult.Status.VALID) {
>
> // validate credentials (only?)
>
> and
>
> if (partialValidationResult.getStatus() ==
> CredentialValidationResult.Status.VALID
> || partialValidationResult.getStatus() ==
> CredentialValidationResult.Status.AUTHENTICATED) {
>
> // provide groups only
>
>
> Ad 2)
>
> One approach to relief implementations of the identity store interface
> somewhat may be to provide default methods in the IdentityStore interface:
>
> public interface IdentityStore {
>
> default CredentialValidationResult validate(CredentialValidationResult
> partialValidationResult, Credential credential) {
> if (partialValidationResult.getStatus() !=
> CredentialValidationResult.Status.AUTHENTICATED &&
> partialValidationResult.getStatus() !=
> CredentialValidationResult.Status.VALID) {
> return validate(Credential credential);
> }
>
> if (partialValidationResult.getStatus() ==
> CredentialValidationResult.Status.VALID
> || partialValidationResult.getStatus() ==
> CredentialValidationResult.Status.AUTHENTICATED) {
> List<String> groups =
> getGroupsByPrincipal(partialValidationResult.getCallerPrincipal().getName());
> if (groups != null) {
>
> return new
> CredentialValidationResult(partialValidationResult, groups);
> }
> }
>
> return partialValidationResult;
>
> }
>
> default int priority() {
> return 0;
> }
>
> default List<String> getGroupsByPrincipal(Principal principal) {
> return null; // or Optional, or return validate(new
> CallerOnlyPrincipal(principal)), etc...
> }
>
> CredentialValidationResult validate(Credential credential);
>
> }
>
> Thoughts?
>
> Kind regards,
> Arjan Tijms
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
> On Thu, Aug 18, 2016 at 11:08 PM, arjan tijms <arjan.tijms_at_gmail.com>
> wrote:
>
>> Hi,
>>
>> On Thu, Aug 18, 2016 at 9:42 PM, Rudy De Busscher <rdebusscher_at_gmail.com>
>> wrote:
>>>
>>> The app-multiple-store in the pull request is already an example.
>>>
>>
>> Ah, sorry I somehow missed that. Thanks
>>
>>
>>>
>>> don't see how the handler knows what the IdentityStore does (unless we
>>> expose that information)
>>> The Handler can just call the individual IdentityStores (and can abort
>>> the consulting of the different stores based on some condition) but has no
>>> idea
>>> - if it does Authentication, Authorization or both
>>>
>>
>> I think I see the issue here, particularly based on the
>> AuthorizationIdentityStore and the AuthenticationIdentityStore in the test.
>>
>> There the identity stores themselves do either authentication,
>> authorization purely based on what happened in the past (which is steered
>> by their priority).
>>
>> What I was referring to was normal identity stores that can always be
>> asked or used to do authentication, authorization or both; they themselves
>> don't have to be restricted internally to be doing either of those based on
>> the order in which they are called.
>>
>> For example, let's say we an LDAPIdentityStore and a DataBaseIdentity
>> store. They are both "normal" stores. Now consider the following use cases:
>>
>> * User 1 wants to configure the application such that authentication
>> happens against the LDAPIdentityStore, and the groups are retrieved from
>> the DataBaseIdentityStore.
>>
>> * User 2 wants to configure the application such that authentication
>> happens against the DataBaseIdentityStore and the groups are retrieved
>> from the LDAPIdentityStore.
>>
>> * User 3 wants to configure the application such that authentication
>> happens against the DataBaseIdentityStore and the groups are retrieved
>> from both the LDAPIdentityStore and DataBaseIdentityStore.
>>
>> Initially the handler wouldn't necessarily know if the configured
>> identity store is capable of any of those things, but that's not really
>> different from the current situation where the authentication mechanism
>> doesn't know if the available store is capable of handling say the
>> UsernamePasswordCredential.
>>
>> If the store isn't capable, it handles this currently by returning
>> NOT_VALIDATED_RESULT.
>>
>> So for user 1, the handler would invoke the LDAPIdentityStore with the
>> normal credential from the authentication mechanism, then it would invoke
>> the DataBaseIdentityStore with the CallerOnlyCredential. If the
>> DataBaseIdentityStore doesn't support the CallerOnlyCredential the handler
>> would learn about this via its NOT_VALIDATED_RESULT return value. If it
>> does, its groups are taken, and the return from the handler is the
>> CallerPrincipal from the LDAPIdentityStore with the groups from the
>> DataBaseIdentityStore.
>>
>> Note that in this case the priority is not used, which I think is the
>> main difference with your proposal. I forgot to mention this earlier, sorry
>> for that.
>>
>> The priority would only be used for the default algorithm when multiple
>> stores happen to be present without any further configuration: loop over
>> them in the right order and first to authenticate wins.
>>
>> That does beg the question, how does the user configure any of the above
>> use cases for user 1, 2 and 3?
>>
>> Currently servers mostly use some .xml file for this to do this in a
>> proprietary way, which may be a good idea to study. For JSR 375 we could do
>> perhaps something like the following for user 1:
>>
>> @DataBaseIdentityStoreDefinition(
>> ...
>> authenticateOnly="true"
>> )
>> @LdapIdentityStoreDefinition(
>> ...
>> authorizeOnly="true"
>> )
>>
>> For user 2:
>>
>> @ LdapIdentityStoreDefinition(
>> ...
>> authenticateOnly="true"
>> )
>> @ DataBaseIdentityStoreDefinition(
>> ...
>> authorizeOnly="true"
>> )
>>
>> For user 3:
>>
>> @ LdapIdentityStoreDefinition(
>> ...
>> ) // default is authenticate + authorize
>> @ DataBaseIdentityStoreDefinition(
>> ...
>> authorizeOnly="true"
>> )
>>
>>
>>
>>> - That it can handle an already authenticated user (for the algorithm
>>> that mandates all stores to succeed)
>>>
>>
>> I don't think the handler has to know this. It would just keep feeding
>> the credentials into each store (order is not important here). In theory,
>> this could even be done in parallel then. Each store either authenticates
>> or it doesn't.
>>
>>
>>
>>> - That it should veto another store (like One store handles the OAuth2
>>> authentication, but another allows only authenticated users fro a certain
>>> domain as we have an ap now which uses Google OAuth2 but only from certain
>>> google work domains)
>>>
>>
>> This would need some further explanation, but I'd say if the caller
>> principal name is say john_at_example.com then the handler can just put
>> that caller principal into this other store. If it excepts it fine,
>> otherwise it rejects it and the handler then learns about this,
>>
>>
>>
>>> There are also issues with this solution.
>>> For example an LDAP based store used for Authorization purposes. But
>>> that LDAP stores should not care where the authentication took place, by
>>> username - password or by JWT for example. But these Authentication
>>> IdentityStores will use different types of Credentials. The LDAP identity
>>> store however, needs only to concentrate on the Status and the
>>> CallerPrincipal.
>>>
>>
>> Indeed, but that doesn't seem to clash or contradict anything I think. In
>> the above example for user 1, the handler would call the
>> DataBaseIdentityStore with the UsernamePasswordCredential, and then it
>> would call the LDAPIdentityStore with the CallerOnlyCredential, if and only
>> if the DataBaseIdentityStore authenticated the user.
>>
>> The LDAPIdentityStore would simply fetch the groups belonging to the
>> caller principal in that credential. The previous status would not matter
>> to it, as the handler already made sure to only call it when necessary.
>>
>> Hope the above makes it a bit more clear and hope it's no too length ;)
>>
>>
>>
>>> I'll try to produce some more code during my holiday break ;)
>>>
>>
>> Okay, thanks ;)
>>
>> Kind regards,
>> Arjan Tijms
>>
>>
>>
>>
>>
>>>
>>> Best regards
>>> Rudy
>>>
>>>
>>>> Kind regards,
>>>> Arjan Tijms
>>>>
>>>>
>>>>
>>>>
>>>>
>>>>> - When the store has another order in the chain, it can receive
>>>>> another type for the Credential parameter (AuthorizeOnlyCredential instead
>>>>> of UsernamePasswordCredential)
>>>>>
>>>>> But I agree, the partialValidationresult is not the best solution. But
>>>>> didn't found anything better (yet) which fulfills all the requirements (of
>>>>> passing Status and CallerCredentials) to the IdentityStore (except adding
>>>>> those 2 parameters).
>>>>>
>>>>>
>>>>>
>>>>>>
>>>>>>
>>>>>>> *Regarding Annotated / All discovery*
>>>>>>>
>>>>>>> When in annotated mode, only beans with a scope are considered. So
>>>>>>> when we introduce @IdentityStore, it needs to be a scope or it needs to be
>>>>>>> recognized by the CDI extension and registered 'manually'
>>>>>>> And we need to veto the normal procedure because otherwise the bean
>>>>>>> gets defined as CDI (because fulfills all requirements) and will be added
>>>>>>> by CDI extension.
>>>>>>>
>>>>>>
>>>>>> This is already the case now. The CDI extension doesn't so much add
>>>>>> user provided beans itself, but just checks if there's a normally activated
>>>>>> bean available that implements the IdentityStore interface.
>>>>>>
>>>>>> The confusion may be with the build-in beans, which are only
>>>>>> activated using the *IdentityStoreDefinition annotations. These beans
>>>>>> reside within the Soteria jar and are already excluded from being scanned.
>>>>>>
>>>>>> With or without our own annotation, user provided IdentityStore
>>>>>> implementations should always normally be activated by CDI.
>>>>>>
>>>>>>
>>>>>>> When we don't define @IdentityStore, the developer can always
>>>>>>> annotate his own implementations of the IdentityStore with @RequestScoped
>>>>>>> or @ApplicationScoped when he is using the annotated mode.
>>>>>>>
>>>>>>
>>>>>> That's true, so just asking the developer to put an existing scope on
>>>>>> the IdentityStore would solve the issue as well ;)
>>>>>>
>>>>>> In fact, at the moment such scope is actually required as I recently
>>>>>> found out. Soteria doesn't yet check if the identity store it obtains is
>>>>>> (implicitly) @Dependent. If it is, it has to release the reference,
>>>>>> otherwise proxy/reference leaks will occur :O
>>>>>>
>>>>>> Kind regards,
>>>>>> Arjan Tijms
>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>>>
>>>>>>>
>>>>>>> Any other thoughts about this?
>>>>>>>
>>>>>>> Best regards
>>>>>>> Rudy
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>> On 17 August 2016 at 17:07, Werner Keil <werner.keil_at_gmail.com>
>>>>>>> wrote:
>>>>>>>
>>>>>>>> Arjan/Rudy,
>>>>>>>>
>>>>>>>> Thanks a lot for the suggestion. Arjan's reply for some reason was
>>>>>>>> considered "suspicious" and possible fishing or malware by Gmail. Not sure,
>>>>>>>> why?
>>>>>>>>
>>>>>>>> I CC my reply to the new Google Group, because whatever Oracle may
>>>>>>>> do about JSR 375 after JavaOne, java.net is sure to go away and as
>>>>>>>> of now there's no sign JSRs, Glassfish or other projects (except OpenJDK
>>>>>>>> which only uses the mere URL but otherwise was said to have its own cluster
>>>>>>>> for a long time now) get seamless migration support of e.g. this mailing
>>>>>>>> list or JIRA.
>>>>>>>>
>>>>>>>> There is no harm sending future discussions to both lists. In the
>>>>>>>> unlikely event there's going to be some "java.oracle.com" or so
>>>>>>>> hosting a new mailing list and importing everything, we have a backup-copy.
>>>>>>>> Otherwise all that's left of the java.net list will be a huge
>>>>>>>> tarball (if Alex has the time to request it soon enouth, AFAIK only Spec
>>>>>>>> Leads and project owners on java.net are eligable to request that)
>>>>>>>>
>>>>>>>> Kind Regards,
>>>>>>>>
>>>>>>>> Werner Keil | JCP Executive Committee Member, JSR 363 Co Spec Lead
>>>>>>>> | Eclipse UOMo Lead, Babel Language Champion | Apache Committer
>>>>>>>>
>>>>>>>> Twitter @wernerkeil | @UnitAPI | @JSR354 | @AgoravaProj | @DeviceMap
>>>>>>>> | #DevOps | #EclipseUOMo
>>>>>>>> Skype werner.keil | Google+ gplus.to/wernerkeil
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>> On Wed, Aug 17, 2016 at 4:52 PM, arjan tijms <arjan.tijms_at_gmail.com
>>>>>>>> > wrote:
>>>>>>>>
>>>>>>>>> Hi Rudy,
>>>>>>>>>
>>>>>>>>> Looks really cool and thanks for putting the effort in!
>>>>>>>>>
>>>>>>>>> Big +1 from me on the very idea of having multiple stores. This is
>>>>>>>>> essential for a large array of use cases, specifically the one you mention
>>>>>>>>> in your example.
>>>>>>>>>
>>>>>>>>> >Proposal : *IdentityStoreHandler* which has the same signature
>>>>>>>>> as the IdentityStore.
>>>>>>>>>
>>>>>>>>> +1
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> > IdentityStore interface receives a new method which determines
>>>>>>>>> the order of the IdentityStores when there are multiple ones.
>>>>>>>>> *int priority();*
>>>>>>>>>
>>>>>>>>> I've been thinking about this for some time, contemplating whether
>>>>>>>>> @Priority would be an easier option, but Guillermo mentioned
>>>>>>>>> correctly that this would clash with @Alternative on an identity store. So
>>>>>>>>> with int priority() being available as a default method in the interface,
>>>>>>>>> users who don't care about priority don't really have to see it in their
>>>>>>>>> store implementations (which is always a big benefit of annotations, that
>>>>>>>>> you can use them optionally).
>>>>>>>>>
>>>>>>>>> One alternative, again hinted at by Guillermo, is to have an
>>>>>>>>> annotation for the identity store. We now kinda assume CDI scanning mode
>>>>>>>>> *all*, but users may prefer scanning mode *annotated*. If we were to
>>>>>>>>> introduce an annotation for the IdentityStore, we could also put the
>>>>>>>>> priority there. Then either the handler could read it from the annotation,
>>>>>>>>> or the default method could. The annotation would only be a convenience for
>>>>>>>>> custom stores not for the build-in ones.
>>>>>>>>>
>>>>>>>>> E.g.
>>>>>>>>>
>>>>>>>>> @CustomIdentityStore(priority=100)
>>>>>>>>> public class MyStore implement IdentityStore {
>>>>>>>>> ...
>>>>>>>>> }
>>>>>>>>>
>>>>>>>>> So +1 for me on the int priority() method, but worthwhile to
>>>>>>>>> discuss if "some annotation" that we may need anyway could also be used.
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> >* IdentityStores are *ordered by ascending values of the
>>>>>>>>> priority value*. This means that the IdentityStore with the
>>>>>>>>> lowest value is processed first. see next bullet.
>>>>>>>>>
>>>>>>>>> +1
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> >* The default IdentityStoreHandler follows this algorithm when
>>>>>>>>> the validate() method is called:
>>>>>>>>> - *Loop over all stores*, in order of the priority value,
>>>>>>>>> until ValidationResult.Status is INVALID or loop is terminated.
>>>>>>>>> - At the end of the loop, change the status in following cases
>>>>>>>>> * NONE -> INVALID
>>>>>>>>> * AUTHENTICATED -> VALID
>>>>>>>>>
>>>>>>>>> +1 for that loop.
>>>>>>>>>
>>>>>>>>> I do have a concern about the implementation as done by the
>>>>>>>>> current PR.
>>>>>>>>>
>>>>>>>>> The IdentityStore interface has been modified with a
>>>>>>>>> CredentialValidationResult as input (partialValidationResult).
>>>>>>>>>
>>>>>>>>> See
>>>>>>>>> https://github.com/rdebusscher/soteria/blob/f93aece6a04e57f073157b30ec5d50248bd50837/api/src/main/java/javax/security/identitystore/IdentityStore.java
>>>>>>>>>
>>>>>>>>> As far as I can see, this is for the implementations (like
>>>>>>>>> DataBaseIdentityStore) just an opaque object that they need to pass around
>>>>>>>>> and eventually put into the CredentialValidationResult that they return.
>>>>>>>>> E,g,
>>>>>>>>>
>>>>>>>>> See
>>>>>>>>> https://github.com/rdebusscher/soteria/blob/f93aece6a04e57f073157b30ec5d50248bd50837/impl/src/main/java/org/glassfish/soteria/identitystores/DataBaseIdentityStore.java#L81
>>>>>>>>>
>>>>>>>>> The CredentialValidationResult constructor then performs some
>>>>>>>>> logic on the passed in partial result:
>>>>>>>>>
>>>>>>>>> See
>>>>>>>>> https://github.com/rdebusscher/soteria/blob/f93aece6a04e57f073157b30ec5d50248bd50837/api/src/main/java/javax/security/identitystore/CredentialValidationResult.java#L166
>>>>>>>>>
>>>>>>>>> I wonder if this logic could not be moved to the
>>>>>>>>> IdentityStoreHandler. This one currently has a loop where it feeds the
>>>>>>>>> result continuously into the available stores:
>>>>>>>>>
>>>>>>>>> CredentialValidationResult result =
>>>>>>>>> CredentialValidationResult.NONE_RESULT;
>>>>>>>>> Iterator<IdentityStore> storeIterator = identityStores.iterator();
>>>>>>>>> while (storeIterator.hasNext() && result.getStatus() !=
>>>>>>>>> CredentialValidationResult.Status.INVALID) {
>>>>>>>>> result = storeIterator.next().validate(result, credential);
>>>>>>>>> }
>>>>>>>>>
>>>>>>>>> See
>>>>>>>>> https://github.com/rdebusscher/soteria/blob/f93aece6a04e57f073157b30ec5d50248bd50837/impl/src/main/java/org/glassfish/soteria/cdi/DefaultIdentityStoreHandler.java#L67
>>>>>>>>>
>>>>>>>>> This could become something like:
>>>>>>>>>
>>>>>>>>> CredentialValidationResult globalResult = NONE_RESULT;
>>>>>>>>> Iterator<IdentityStore> storeIterator = identityStores.iterator();
>>>>>>>>>
>>>>>>>>> while (storeIterator.hasNext() && globalResult.getStatus() !=
>>>>>>>>> INVALID) {
>>>>>>>>> CredentialValidationResult latestResult =
>>>>>>>>> storeIterator.next().validate(credential);
>>>>>>>>>
>>>>>>>>> if (!isOneOf(latestResult.getStatus(), AUTHENTICATED, VALID) {
>>>>>>>>> if (result != null) {
>>>>>>>>> latestResult.setGroups(globalResult.getGroups());
>>>>>>>>>
>>>>>>>>> latestResult.setCallerPrincipal(globalResult.getCallerPrincipal());
>>>>>>>>> } else {
>>>>>>>>> if (latestResult.getStatus() != NONE) {
>>>>>>>>> throw new IllegalArgumentException("non null
>>>>>>>>> global result required when Status is not NONE");
>>>>>>>>> } else {
>>>>>>>>> latestResult.setGroups(null);
>>>>>>>>> latestResult.setCallerPrincipal(null);
>>>>>>>>> }
>>>>>>>>> }
>>>>>>>>>
>>>>>>>>> if (globalResult != null && globalResult.getStatus() ==
>>>>>>>>> VALID && latestResult.getStatus() == AUTHENTICATED) {
>>>>>>>>> latestResult.setStatus(VALID);
>>>>>>>>> }
>>>>>>>>>
>>>>>>>>> globalResult = latestResult;
>>>>>>>>> }
>>>>>>>>>
>>>>>>>>> We could additionally split out the merging algorithm to a
>>>>>>>>> reusable method (and this method could be in CredentialValidationResult,
>>>>>>>>> going full circle ;)), so custom handlers can re-use it if they want. By
>>>>>>>>> externalizing this logic we not only keep the IdentityStore interface
>>>>>>>>> simpler and unburden the developer from passing around a partial result
>>>>>>>>> (which they may not care for), but it also allows custom handlers to
>>>>>>>>> customize the merge algorithm. You'd then get e.g.
>>>>>>>>>
>>>>>>>>> CredentialValidationResult globalResult = NONE_RESULT;
>>>>>>>>> Iterator<IdentityStore> storeIterator = identityStores.iterator();
>>>>>>>>>
>>>>>>>>> while (storeIterator.hasNext() && globalResult.getStatus() !=
>>>>>>>>> INVALID) {
>>>>>>>>> globalResult
>>>>>>>>> = CredentialValidationResult.merge(globalResult,
>>>>>>>>> storeIterator.next().validate(credential));
>>>>>>>>> }
>>>>>>>>>
>>>>>>>>> Kind regards,
>>>>>>>>> Arjan Tijms
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> On Sat, Aug 13, 2016 at 2:24 PM, Rudy De Busscher <
>>>>>>>>> rdebusscher_at_gmail.com> wrote:
>>>>>>>>>
>>>>>>>>>> Hi all,
>>>>>>>>>>
>>>>>>>>>> I have put together the text around my idea of the multi
>>>>>>>>>> IdentityStore.
>>>>>>>>>>
>>>>>>>>>> The code is not yet completely ready and is missing an example
>>>>>>>>>> and test. I'll try to create that in the next few days and make a pull
>>>>>>>>>> request at that time.
>>>>>>>>>>
>>>>>>>>>> *Multiple IdentityStore proposal*
>>>>>>>>>>
>>>>>>>>>> *Why multiple stores?*
>>>>>>>>>> There are various use cases where multiple identity stores can be
>>>>>>>>>> useful.
>>>>>>>>>> And it allows us to decouple the authentication and authorization
>>>>>>>>>> parts of the current mechanism. So that groups can be retrieved by another
>>>>>>>>>> store then the credential checking.
>>>>>>>>>>
>>>>>>>>>> *Examples*
>>>>>>>>>> * When your application should allow users which are defined in
>>>>>>>>>> multiple stores, like an LDAP for your internal users and a Database store
>>>>>>>>>> for the external ones.
>>>>>>>>>> * Users are authenticated by an OAuth2 provider and the groups
>>>>>>>>>> are retrieved from a database table.
>>>>>>>>>> * The first IdentityStore based on OAuth2 allows any Google
>>>>>>>>>> account, but the second store limits the access to a certain google domain.
>>>>>>>>>>
>>>>>>>>>> *Technical changes*
>>>>>>>>>> * When multiple stores are allowed, we need another interface
>>>>>>>>>> which can be injected into the AuthenticationMechanism.
>>>>>>>>>> Proposal : *IdentityStoreHandler* which has the same signature
>>>>>>>>>> as the IdentityStore.
>>>>>>>>>>
>>>>>>>>>> * IdentityStore interface receives a new method which determines
>>>>>>>>>> the order of the IdentityStores when there are multiple ones.
>>>>>>>>>> *int priority();*
>>>>>>>>>>
>>>>>>>>>> * The current **Definition annotations are extended by a member
>>>>>>>>>> which is transferred to the priority value of the IdentityStore.
>>>>>>>>>>
>>>>>>>>>> * The *ValidationResult.Status enum* is extended with some
>>>>>>>>>> constants. Values and meanings are
>>>>>>>>>>
>>>>>>>>>> *NONE* : The default status, indicating that no
>>>>>>>>>> IdentityStore has been consulted yet.
>>>>>>>>>>
>>>>>>>>>> *AUTHENTICATED* : Indicates that the credential is
>>>>>>>>>> validated but that no Groups are assigned yet.
>>>>>>>>>>
>>>>>>>>>> *NOT_VALIDATED* : Indicates that the credential could
>>>>>>>>>> not be validated
>>>>>>>>>>
>>>>>>>>>> *INVALID* : Indicates that the credential is not valid
>>>>>>>>>> after a validation attempt.
>>>>>>>>>>
>>>>>>>>>> *VALID* : Indicates that the credential is valid after a
>>>>>>>>>> validation attempt and Groups are assigned.
>>>>>>>>>>
>>>>>>>>>> * IdentityStores are *ordered by ascending values of the
>>>>>>>>>> priority value*. This means that the IdentityStore with the
>>>>>>>>>> lowest value is processed first. see next bullet.
>>>>>>>>>>
>>>>>>>>>> * The default IdentityStoreHandler follows this algorithm when
>>>>>>>>>> the validate() method is called:
>>>>>>>>>> - *Loop over all stores*, in order of the priority value,
>>>>>>>>>> until ValidationResult.Status is INVALID or loop is terminated.
>>>>>>>>>> - At the end of the loop, change the status in following
>>>>>>>>>> cases
>>>>>>>>>> * NONE -> INVALID
>>>>>>>>>> * AUTHENTICATED -> VALID
>>>>>>>>>>
>>>>>>>>>> * The IdentityStores logic is
>>>>>>>>>> - If the store decides to do *authentication logic* (a
>>>>>>>>>> store can also decide to perform only the logic in the case the Status is
>>>>>>>>>> NONE or NOT_VALIDATED, meaning the user is not authenticated yet) it should
>>>>>>>>>> set the status to
>>>>>>>>>> + *NOT_VALIDATED* : When credentials could not be
>>>>>>>>>> validated (should not set this Status when the Status was already
>>>>>>>>>> AUTHENTICATED or VALID)
>>>>>>>>>> + *AUTHENTICATED* : When credentials are valid but the
>>>>>>>>>> store didn't assign any groups (Should not set this status when the
>>>>>>>>>> original Status was VALID)
>>>>>>>>>> + *INVALID* : Credentials are not valid and the store
>>>>>>>>>> is allowed to veto another authentication by another IdentityStore.
>>>>>>>>>> + *VALID* : When credentials are valid and the store
>>>>>>>>>> did assign groups (which can be the empty set)
>>>>>>>>>>
>>>>>>>>>> - The IdentityStore can decide that only *authorization* is
>>>>>>>>>> performed, and should only do this in the case where Status has the value
>>>>>>>>>> AUTHENTICATED or VALID.
>>>>>>>>>> When the store adds Groups, it should change the Status to VALID.
>>>>>>>>>>
>>>>>>>>>> Best regards
>>>>>>>>>> Rudy
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>
>>>>>>>> --
>>>>>>>> You received this message because you are subscribed to the Google
>>>>>>>> Groups "Java EE Security API - JSR 375 - Experts" group.
>>>>>>>> To unsubscribe from this group and stop receiving emails from it,
>>>>>>>> send an email to jsr375-experts+unsubscribe_at_googlegroups.com.
>>>>>>>> To post to this group, send email to
>>>>>>>> jsr375-experts_at_googlegroups.com.
>>>>>>>> To view this discussion on the web visit
>>>>>>>> https://groups.google.com/d/msgid/jsr375-experts/CAAGawe0esYx-FJiGWCDnyHLYUMi6Aw0AjMJ%3DSyAzN5E17B%2BP9Q%40mail.gmail.com
>>>>>>>> <https://groups.google.com/d/msgid/jsr375-experts/CAAGawe0esYx-FJiGWCDnyHLYUMi6Aw0AjMJ%3DSyAzN5E17B%2BP9Q%40mail.gmail.com?utm_medium=email&utm_source=footer>
>>>>>>>> .
>>>>>>>> For more options, visit https://groups.google.com/d/optout.
>>>>>>>>
>>>>>>>
>>>>>>> --
>>>>>>> You received this message because you are subscribed to the Google
>>>>>>> Groups "Java EE Security API - JSR 375 - Experts" group.
>>>>>>> To unsubscribe from this group and stop receiving emails from it,
>>>>>>> send an email to jsr375-experts+unsubscribe_at_googlegroups.com.
>>>>>>> To post to this group, send email to jsr375-experts_at_googlegroups.com
>>>>>>> .
>>>>>>> To view this discussion on the web visit
>>>>>>> https://groups.google.com/d/msgid/jsr375-experts/CAL%2Bwt-6jiXHCKm1RnUzqB3VNgAQoh5X6XR04oXV2V4SuU9t0Lw%40mail.gmail.com
>>>>>>> <https://groups.google.com/d/msgid/jsr375-experts/CAL%2Bwt-6jiXHCKm1RnUzqB3VNgAQoh5X6XR04oXV2V4SuU9t0Lw%40mail.gmail.com?utm_medium=email&utm_source=footer>
>>>>>>> .
>>>>>>>
>>>>>>> For more options, visit https://groups.google.com/d/optout.
>>>>>>>
>>>>>>
>>>>>>
>>>>>
>>>>
>>>
>>
> --
> You received this message because you are subscribed to the Google Groups
> "Java EE Security API - JSR 375 - Experts" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to jsr375-experts+unsubscribe_at_googlegroups.com.
> To post to this group, send email to jsr375-experts_at_googlegroups.com.
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/jsr375-experts/CAE%3D-AhBpYD8g8q-1x%3D%3DuhvZvDwhyFZ%2BkdyyTVO9aBnLw9DK__Q%40mail.gmail.com
> <https://groups.google.com/d/msgid/jsr375-experts/CAE%3D-AhBpYD8g8q-1x%3D%3DuhvZvDwhyFZ%2BkdyyTVO9aBnLw9DK__Q%40mail.gmail.com?utm_medium=email&utm_source=footer>
> .
> For more options, visit https://groups.google.com/d/optout.
>