Hi,
On Mon, Dec 7, 2015 at 4:42 PM, Werner Keil <werner.keil_at_gmail.com> wrote:
> P.s.: I'm not sure, if the API would stick to a rather lengthy package
> name like: javax.security.authenticationmechanism ?;-)
>
> Werner
>
I hear you, this package name and specifically the classes inside it, have
not been given much thought yet, but since they were needed to get the
sample to work I had to put them somewhere.
In general when we are going to discuss this, there are some issues.
There is already an existing package javax.security.auth.message, which is
owned by JASPIC, so we won't touch it. But I was wondering about
just javax.security.auth, which is the prefix package. I guess we could
touch that (create new sub-packages of that), but this is a bit of an issue
too since we more or less agreed here that just "auth" is not desirable. It
can mean either "authentication" or "authorization".
But if we create a package javax.security.authentication next to the
existing javax.security.auth, where both mean "authentication", it kinda
looks messy as well.
Nevertheless, with a javax.security.authentication, we could put the
mechanism classes in javax.security.authentication.mechanism (but in total
this is actually 1 char longer). The alternative could be
javax.security.auth.mechanism, but yeah, troublesome...
Kind regards,
Arjan Tijms
>
> On Mon, Dec 7, 2015 at 10:45 AM, Werner Keil <werner.keil_at_gmail.com>
> wrote:
>
>> Thanks, I hope to have a closer look at it during the week or weekend.
>> Would be nice to show something like it in Tel Aviv in 10 days ;-)
>>
>> 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
>>
>>
>>
>> Werner Keil
>> [image: https://]about.me/wernerkeil
>> <https://about.me/wernerkeil?promo=email_sig>
>>
>>
>> On Mon, Dec 7, 2015 at 10:37 AM, arjan tijms <arjan.tijms_at_gmail.com>
>> wrote:
>>
>>> Hi,
>>>
>>> I have extended the example a little. To keep the original example as-is
>>> and as small/simple as possible, I did the extended work in a new repo
>>> here: https://github.com/arjantijms/mechanism-to-store-x
>>>
>>> This adds:
>>>
>>> * Working implementation and example of @DataBaseIdentityStoreDefinition
>>> * Example of custom (app provided) identity store.
>>>
>>> See:
>>>
>>> *
>>> https://github.com/arjantijms/mechanism-to-store-x/blob/master/app-db/src/main/java/test/Servlet.java
>>> *
>>> https://github.com/arjantijms/mechanism-to-store-x/blob/master/app-custom/src/main/java/test/TestIdentityStore.java
>>>
>>> I also fixed the "mechanism-to-store-app-1.0-SNAPSHOT" name. The example
>>> now uses simple names for the war and therefor the URL:
>>> localhost:8080/app-db, localhost:8080/app-mem, localhost:8080/app-custom.
>>>
>>> The examples were tested on GlassFish (4.1.1) and JBoss (WildFly 10rc4).
>>> Note that JBoss needs the proprietary JASPIC activation before this works
>>> (still hoping Darran can do something here to lift this).
>>>
>>> In order to work around a GlassFish bug (see
>>> https://java.net/jira/browse/GLASSFISH-21447) I had to put the data
>>> source in java:global. Due to another GlassFish bug where GF doesn't unbind
>>> the data source when the application is undeployed you actually have to
>>> stop and start GlassFish before the deploying the app again.
>>>
>>> Kind regards,
>>> Arjan Tijms
>>>
>>>
>>>
>>>
>>> On Sun, Oct 25, 2015 at 5:55 AM, Alex Kosowski <alex.kosowski_at_oracle.com
>>> > wrote:
>>>
>>>> Hi Arjan,
>>>>
>>>> That example app is terrific! I would like to demonstrate it during the
>>>> JavaOne JSR 375 BOF. The app does not look like much, but when you realize
>>>> the caller was authenticated using data from an annotation, you realize how
>>>> these simple standardizations will make a BIG impact.
>>>>
>>>> The only issue I ran into when deploying on GlassFish 4.1 was the
>>>> default app name was " mechanism-to-store-app-1.0-SNAPSHOT", which made the
>>>> context root " /mechanism-to-store-app-1.0-SNAPSHOT". But I changed the
>>>> context root to "/mechanism-to-store-app" in the GF admin console and the
>>>> example works as you described.
>>>>
>>>> Thanks again!
>>>> Alex
>>>>
>>>>
>>>> On 10/24/15 6:19 PM, Alex Kosowski wrote:
>>>>
>>>> Thanks Arjan,
>>>>
>>>> Perhaps you would provide an example of using the
>>>> @CredentialCapable(UsernamePasswordCredential.class) qualifier? Also,
>>>> perhaps you would have an example of extending a standard identity store
>>>> with a custom defined one to support a custom defined credential?
>>>>
>>>> Just some suggestions.
>>>>
>>>> With regards,
>>>> Alex
>>>>
>>>> On 10/19/15 2:53 PM, arjan tijms wrote:
>>>>
>>>> Hi,
>>>>
>>>> On Mon, Oct 19, 2015 at 7:46 PM, Alex Kosowski <
>>>> alex.kosowski_at_oracle.com> wrote:
>>>>
>>>>> Thanks Arjan! I cannot wait to try it!
>>>>
>>>>
>>>> Looking forward to hearing feedback, thanks.
>>>>
>>>> I'll try later this week to create another project that implements some
>>>> more identity stores and also has an example for a user defined one.
>>>>
>>>> Kind regards,
>>>> Arjan Tijms
>>>>
>>>>
>>>>
>>>>
>>>>
>>>>
>>>>>
>>>>>
>>>>> On 10/19/15 1:27 PM, arjan tijms wrote:
>>>>>
>>>>>> Hi,
>>>>>>
>>>>>> I've created a working zero config demo application that shows how an
>>>>>> authentication mechanism can use an identity store.
>>>>>>
>>>>>> It's located here: https://github.com/arjantijms/mechanism-to-store
>>>>>>
>>>>>> It uses a selection of the types Alex proposed, with the adjustments
>>>>>> as discussed. This demo app uses one of the two ways to set an Identity
>>>>>> Store; "declaratively for a standard provided store" as proposed by Reza in
>>>>>> issue https://java.net/jira/browse/JAVAEE_SECURITY_SPEC-9 (the other
>>>>>> option which is not demoed here is a store fully defined by the
>>>>>> application).
>>>>>>
>>>>>> The store is declared using an annotation corresponding to option 3
>>>>>> in the list presented earlier. I put this annotation on a test Servlet (but
>>>>>> it can be put anywhere):
>>>>>>
>>>>>> @EmbeddedIdentityStoreDefinition({
>>>>>> @Credentials(callerName = "reza", password = "secret1", groups =
>>>>>> { "foo", "bar" }),
>>>>>> @Credentials(callerName = "alex", password = "secret2", groups =
>>>>>> { "foo", "kaz" }),
>>>>>> @Credentials(callerName = "arjan", password = "secret3", groups =
>>>>>> { "foo" }) })
>>>>>> @DeclareRoles({ "foo", "bar", "kaz" })
>>>>>> @WebServlet("/servlet")
>>>>>> public class Servlet extends HttpServlet
>>>>>>
>>>>>> See:
>>>>>> https://github.com/arjantijms/mechanism-to-store/blob/master/app/src/main/java/test/Servlet.java
>>>>>>
>>>>>>
>>>>>> This annotation is picked up by a CDI extension and a Bean<T> is
>>>>>> created for it:
>>>>>>
>>>>>> public <T> void processBean(@Observes ProcessBean<T> eventIn,
>>>>>> BeanManager beanManager) {
>>>>>>
>>>>>> ProcessBean<T> event = eventIn; // JDK8 u60 workaround
>>>>>>
>>>>>> Optional<EmbeddedIdentityStoreDefinition> result =
>>>>>> getAnnotation(beanManager, event.getAnnotated(),
>>>>>> EmbeddedIdentityStoreDefinition.class);
>>>>>> if (result.isPresent()) {
>>>>>> identityStoreBean = new CdiProducer<IdentityStore>()
>>>>>> .scope(ApplicationScoped.class)
>>>>>> .types(IdentityStore.class)
>>>>>> .create(e -> new
>>>>>> EmbeddedIdentityStore(result.get().value()));
>>>>>>
>>>>>> }
>>>>>> }
>>>>>>
>>>>>> This Bean<T> is subsequently registered with the container:
>>>>>>
>>>>>> public void afterBean(final @Observes AfterBeanDiscovery
>>>>>> afterBeanDiscovery) {
>>>>>> if (identityStoreBean != null) {
>>>>>> afterBeanDiscovery.addBean(identityStoreBean);
>>>>>> }
>>>>>> }
>>>>>>
>>>>>> See:
>>>>>> https://github.com/arjantijms/mechanism-to-store/blob/master/jsr375/src/main/java/org/glassfish/jsr375/cdi/CdiExtension.java
>>>>>>
>>>>>>
>>>>>> The Identity Store implementation is vendor specific. It's not in the
>>>>>> javax.security API package. This way vendors can optimise the
>>>>>> implementation and/or map it to their existing artefacts.
>>>>>>
>>>>>> The sample implementation maps the data in the annotation to a Map:
>>>>>>
>>>>>> private Map<String, Credentials> callerToCredentials;
>>>>>>
>>>>>> public EmbeddedIdentityStore(Credentials[] credentials) {
>>>>>> callerToCredentials = stream(credentials).collect(toMap(
>>>>>> e -> e.callerName(),
>>>>>> e -> e)
>>>>>> );
>>>>>> }
>>>>>>
>>>>>> And in the validate() method it simply checks if the credentials for
>>>>>> the requested caller name are present:
>>>>>>
>>>>>> public CredentialValidationResult
>>>>>> validate(UsernamePasswordCredential usernamePasswordCredential) {
>>>>>> Credentials credentials =
>>>>>> callerToCredentials.get(usernamePasswordCredential.getCaller());
>>>>>>
>>>>>> if (credentials != null &&
>>>>>> usernamePasswordCredential.getPassword().compareTo(credentials.password()))
>>>>>> {
>>>>>> return new CredentialValidationResult(
>>>>>> VALID,
>>>>>> credentials.callerName(),
>>>>>> asList(credentials.groups())
>>>>>> );
>>>>>> }
>>>>>>
>>>>>> return INVALID_RESULT;
>>>>>> }
>>>>>>
>>>>>> See:
>>>>>> https://github.com/arjantijms/mechanism-to-store/blob/master/jsr375/src/main/java/org/glassfish/jsr375/identitystores/EmbeddedIdentityStore.java
>>>>>>
>>>>>>
>>>>>> The application uses a very basic SAM. This one uses the plain
>>>>>> non-simplified JASPIC API. The SAM obtains the identity store via CDI and
>>>>>> then utilises it to perform the "credential to identity data" function:
>>>>>>
>>>>>> String name = request.getParameter("name");
>>>>>> Password password = new
>>>>>> Password(request.getParameter("password"));
>>>>>>
>>>>>> // Obtain a reference to the Identity Store
>>>>>> IdentityStore identityStore =
>>>>>> CDI.current().select(IdentityStore.class).get();
>>>>>>
>>>>>> // Delegate the {credentials in -> identity data out} function to
>>>>>> // the Identity Store
>>>>>> CredentialValidationResult result = identityStore.validate(new
>>>>>> UsernamePasswordCredential(name, password));
>>>>>>
>>>>>> if (result.getStatus() == VALID) {
>>>>>> callbacks = new Callback[] {
>>>>>> // The name of the authenticated caller
>>>>>> new CallerPrincipalCallback(clientSubject,
>>>>>> result.getCallerName()),
>>>>>> // the groups of the authenticated caller (for test
>>>>>> // assume non-null, non-empty)
>>>>>> new GroupPrincipalCallback(clientSubject,
>>>>>> result.getCallerGroups().toArray(new String[0])) };
>>>>>> } else {
>>>>>> throw new AuthException("Login failed");
>>>>>> }
>>>>>>
>>>>>> See:
>>>>>> https://github.com/arjantijms/mechanism-to-store/blob/master/app/src/main/java/test/TestServerAuthModule.java
>>>>>>
>>>>>>
>>>>>> Finally the demo app uses a simple (non-protected) Servlet (the one
>>>>>> shown above) that prints out the details of the authenticated user. If the
>>>>>> application is deployed to a stock GlassFish without any configuration
>>>>>> whatsoever being done it can be requested via:
>>>>>>
>>>>>>
>>>>>> http://localhost:8080/mechanism-to-store-app/servlet?name=reza&password=secret1
>>>>>> <
>>>>>> http://localhost:8080/mechanism-to-store-app/servlet?name=reza&password=secret1
>>>>>> >
>>>>>>
>>>>>> If all went well this prints out the following:
>>>>>>
>>>>>> This is a servlet
>>>>>> web username: reza
>>>>>> web user has role "foo": true
>>>>>> web user has role "bar": true
>>>>>> web user has role "kaz": false
>>>>>>
>>>>>> Needless to say here that this is just for demo'ing one of the
>>>>>> smallest possible SAMs that interact with the caller. Putting the password
>>>>>> in the URL is of course not suited for any real live usage.
>>>>>>
>>>>>> Note that this particular demo only demonstrates a few of the
>>>>>> discussed options. I also made a few practical choices here and there to be
>>>>>> able to implement the application which can of course be discussed further.
>>>>>>
>>>>>> Thoughts?
>>>>>>
>>>>>> Kind regards,
>>>>>> Arjan Tijms
>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>
>>>
>>
>