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

[jsr375-experts] Identity Store Proposal 2.0

From: arjan tijms <arjan.tijms_at_gmail.com>
Date: Sat, 20 Jun 2015 23:49:08 +0200

Hi,

On Saturday, June 20, 2015, Rudy De Busscher <rdebusscher_at_gmail.com> wrote:

> Arjan,
>
> I agree when you say that we should try to use CDI to select the
> IdentityStrore.
>
> But you need a Qualifier for this, and since the UsernamePasswordCredentials
> for example is a concrete class, it is not usable as qualifier (=
> annotation)
>

True, the credentials themselves would normally not be used directly.



> How are we going to link certain implementation classes with a Qualifier?
> Or am I missing something?
>

No, I was just a bit too brief in the example I guess ;)

The idea was just to point out that an annotation literal can be used to
select a specific implementation. In that example you'd hypothetically
match a credential type with an annotation literal. So if you used
UsernamePasswordCredential, you'd use a UserNamePasswordAnnotationLiteral
to look up an identity store. This assumes that the code instantiating the
credential would be the same code that does the identity store lookup.

But the example wasn't meant to be used exactly as is, just as mentioned a
very quick way to show that CDI can do finer grained selections beyond just
the type of the class.



> *How I see this working using CDI:*
>
> What we can do is to create an annotation (say @IdentityStoreVariant, not
> a very good name) which has a value parameter which takes the class which
> will have the credentials, like this
>
> *_at_Inject*
> *_at_IdentityStoreVariant(UsernamePasswordCredentials.class)*
> *private IdentityStore identityStore;*
>
> Now the CDI producer can look at the InjectionPoint info and find the
> annotation and the requested Credentials class. And select the correct
> identityStore out of all CDI beans implementing this interface.
>

Yes, that works ;)

In addition to injection, this form also makes it really easy to look up
beans which support a given credential type programmatically. Incidentally,
this is the exact mechanism we use in the JSF 2.3 EG to select beans.

E.g. in UIData.java

cdi.select(e.getValue(), new FacesDataModelAnnotationLiteral(e.getKey())

(e.getValue() is a DataModel implementation class, which has some parallels
with an IdentityStore here, while e.getKey() is the class the DataModel is
handling, which has some parallels with the credential type here)

See
https://github.com/omnifaces/mojarra/blob/master/jsf-api/src/main/java/javax/faces/component/UIData.java#L1907

We use this pattern for more things, e.g. Converters, Behaviors and
Validators are now created like that as well. See e.g.
https://github.com/omnifaces/mojarra/blob/master/jsf-ri/src/main/java/com/sun/faces/cdi/CdiUtils.java#L148



> The IdentityStore interface (abstract class) must have a method which
> returns the supported (or list of) Credentials classes. And we can select a
> suitable one based on this info as explained above.
>

Can you give an example of this?

There are a couple of options here I guess, but it does depend a little on
whether we want a single store implementation to support more than one
credential type. A single credential type would simply be:

@RequestScoped
@IdentityStoreVariant(UsernamePasswordCredentials.class)
public class MyStore implements IdentityStore {

    // ....

}

Multiple types (with an OR relation for lookup or injection) are a bit more
work to implement. There's at least a method via extensions and a method
via producers, which looks as follows:

@RequestScoped
@IdentityStoreVariant(UsernamePasswordCredentials.class)
public class MyStore implements IdentityStore {

    @Produces
    @IdentityStoreVariant(TokenCredential.class)
    protected IdentityStore token() {
        return this;
    }

    // ...

}

Kind regards,
Arjan Tijms