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

[jsr375-experts] Re: Working example app demonstrating identity store usage

From: arjan tijms <arjan.tijms_at_gmail.com>
Date: Thu, 24 Dec 2015 16:55:40 +0100

Hi,

On Thu, Dec 24, 2015 at 12:05 PM, Werner Keil <werner.keil_at_gmail.com> wrote:

> Great, thanks.
> Where they do, as a first step the "embedded" API module might still go
> into examples (or "proposals" sandbox, which one you think was best) but
> soon it would be great to have the Spec/API repo filled with life, too.
>
Okay, for the authentication mechanism draft proposal I added the
implementation as well.

As for the demo applications, I think we could do with a top level
repository "demo-apps", so we could get
https://github.com/javaee-security-spec/demo-apps

Unfortunately I noticed I have insufficient permissions to create a new
repository. I guess Alex as the organization owner has these permissions.

Alternatively I could add the demo applications to a folder in
https://github.com/javaee-security-spec/javaee-security-examples


> I dedicated at least a chapter on security to JSR 375 in my upcoming
> Social Java book, too. I should have a bit of time after Christmas to
> continue writing ;-)
>
Sounds great!

Kind regards,
Arjan Tijms




> Kind Regards,
> Werner
> Am 24.12.2015 11:28 schrieb "arjan tijms" <arjan.tijms_at_gmail.com>:
>
>> Hi,
>>
>> Yet another update; I extracted interfaces for the classes involved with
>> the authentication mechanism proposal. That way we can have a proper
>> API/implementation split. I think the example apps are reasonable ready now
>> to be moved to the javaee-security-spec repo.
>>
>> I also added the simplified identity store proposal (a copy from the
>> example app) here:
>> https://github.com/javaee-security-spec/javaee-security-proposals/tree/master/authentication/identity-store/identity-store-readonly-simplified
>>
>> I think this properly reflects what had been discussed earlier by Alex,
>> me and others, but please check if I did it correctly.
>>
>> For completeness I'll add the first draft of the authentication mechanism
>> as well. This is based on my earlier experiments in OmniSecurity as well as
>> various bits and pieces as discussed here. I still think this needs some
>> more discussion though, but that can be done in the dedicated thread.
>>
>> Kind regards,
>> Arjan Tijms
>>
>>
>>
>>
>>
>> On Wed, Dec 23, 2015 at 3:16 PM, arjan tijms <arjan.tijms_at_gmail.com>
>> wrote:
>>
>>> Hi,
>>>
>>> Added another update. I added a build-in authentication mechanism (I
>>> used a BASIC implementation) and an associated annotation analogous to the
>>> ones for build-in identity stores: @BasicAuthenticationMechanismDefinition
>>>
>>> As mentioned before, it's open question on how to align this with the
>>> Servlet EG, but at least there's now an example.
>>>
>>> With that in place, I created the smallest example application until
>>> now. It's basically a single class:
>>>
>>> @BasicAuthenticationMechanismDefinition(
>>> realmName="test realm"
>>> )
>>>
>>> @EmbeddedIdentityStoreDefinition({
>>> @Credentials(callerName = "reza", password = "secret1", groups = {
>>> "foo", "bar" }),
>>> @Credentials(callerName = "alex", password = "secret2", groups = {
>>> "foo", "kaz" }),
>>> @Credentials(callerName = "arjan", password = "secret3", groups = {
>>> "foo" }) }
>>> )
>>>
>>> @WebServlet("/servlet")
>>> @DeclareRoles({ "foo", "bar", "kaz" })
>>> @ServletSecurity(@HttpConstraint(rolesAllowed = "foo"))
>>> public class Servlet extends HttpServlet {
>>>
>>> private static final long serialVersionUID = 1L;
>>>
>>> @Override
>>> public void doGet(HttpServletRequest request, HttpServletResponse
>>> response) throws ServletException, IOException {
>>>
>>> // ...
>>> }
>>>
>>> }
>>>
>>> As can be seen this chooses and configures both the authentication
>>> mechanism as well as the identity store. Both adhere to the highlander rule
>>> (there can be only one).
>>>
>>> The authentication mechanism is implemented as follows:
>>>
>>> public class BasicAuthenticationMechanism implements
>>> HttpAuthenticationMechanism {
>>> private final String basicHeaderValue;
>>>
>>> public BasicAuthenticationMechanism(String realmName) {
>>> this.basicHeaderValue = format("Basic realm=\"%s\"", realmName);
>>> }
>>>
>>> @Override
>>> public AuthStatus validateRequest(HttpServletRequest request,
>>> HttpServletResponse response, HttpMsgContext httpMsgContext) throws
>>> AuthException {
>>> String[] credentials = getCredentials(request);
>>> if (!isEmpty(credentials)) {
>>>
>>> IdentityStore identityStore =
>>> CDI.current().select(IdentityStore.class).get();
>>>
>>> CredentialValidationResult result = identityStore.validate(
>>> new UsernamePasswordCredential(credentials[0], new
>>> Password(credentials[1])));
>>>
>>> if (result.getStatus() == VALID) {
>>> return httpMsgContext.notifyContainerAboutLogin(
>>> result.getCallerName(), result.getCallerGroups());
>>> }
>>> }
>>> if (httpMsgContext.isProtected()) {
>>> response.setHeader("WWW-Authenticate", basicHeaderValue);
>>> return httpMsgContext.responseUnAuthorized();
>>> }
>>> return httpMsgContext.doNothing();
>>> }
>>> private String[] getCredentials(HttpServletRequest request) {
>>> String authorizationHeader = request.getHeader("Authorization");
>>> if (!isEmpty(authorizationHeader) &&
>>> authorizationHeader.startsWith("Basic ") ) {
>>> return new
>>> String(parseBase64Binary(authorizationHeader.substring(6))).split(":");
>>> }
>>> return null;
>>> }
>>> }
>>>
>>> Btw, both very good and some less good news concerning JBoss (WildFly).
>>> Since WildFly 10rc5 (just released today) ***it's no longer necessary to
>>> modify standalone.xml*** :) All JASPIC based examples just run out of the
>>> box now. It's not 100% perfect yet, since the archive still needs to
>>> contain jboss-web.xml, but that's a minor concern for now.
>>>
>>> Unfortunately, the basic authentication mechanism doesn't work on
>>> WildFly for now, because of this bug:
>>> https://issues.jboss.org/browse/UNDERTOW-577
>>>
>>> The other ones do run though.
>>>
>>> Kind regards,
>>> Arjan Tijms
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>> On Thu, Dec 17, 2015 at 9:25 PM, arjan tijms <arjan.tijms_at_gmail.com>
>>> wrote:
>>>
>>>> Hi,
>>>>
>>>> On Thu, Dec 17, 2015 at 7:01 PM, Werner Keil <werner.keil_at_gmail.com>
>>>> wrote:
>>>>
>>>>> Dear All,
>>>>>
>>>>> A little follow-up. I'll also plan to upload the slides either today
>>>>> or over the weekend.
>>>>> The app-db example feels like something gets stuck, either the data
>>>>> source is no longer accessible or similar. Even adding and removing the app
>>>>> to GlassFish 4 did not help..
>>>>>
>>>>
>>>> Unfortunately data sources seem to be a little buggy on GlassFish, at
>>>> least embedded ones. java:app doesn't work at all, I encountered some
>>>> issues with XA connection pooling, and indeed, data sources stick around
>>>> and you need to restart GlassFish :(
>>>>
>>>> Payara recently fixed this last bug though, see
>>>> https://github.com/payara/Payara/pull/565
>>>>
>>>> A couple of other data source problems are in the associated issue:
>>>> https://github.com/payara/Payara/issues/510
>>>>
>>>> In general, bugs in various servers is part of what causes some
>>>> seemingly simple example applications to take up quite a lot of time.
>>>>
>>>>
>>>>
>>>>
>>>>> One question I'm not entirely sure, if it's applicable was, if vendors
>>>>> of JCE implementations were to adopt JSR 375. Maybe it's simply the
>>>>> "java.security" package name that created such impression. The only area
>>>>> which I brushed answering someone else's question was, that at least in
>>>>> production where passwords aren't masked using aliasing the actual password
>>>>> store should always be encrypted, too.
>>>>>
>>>>
>>>> Indeed, so password aliasing is as you know on the schedule of this JSR
>>>> and I assume this may use JCE, but this is a topic Alex likely knows more
>>>> about.
>>>>
>>>> Btw, the provided examples are all aimed at demonstrating the API
>>>> interactions, and the current implementations are as simple as can be. The
>>>> data in the various stores is now all unencrypted. Naturally this should
>>>> never be done in production.
>>>>
>>>>
>>>>
>>>>> Not from Tel Aviv, but the host of Hackergarten Zürich, Oliver
>>>>> Nautsch asked based on actual needs we help the current client meet on Java
>>>>> EE 6 with proprietary extensions to CDI and other frameworks built
>>>>> in-house. Taking the "Movie" DB test case
>>>>> https://github.com/javaee-security-spec/javaee-security-examples/tree/master/roles-allowed-and-runas
>>>>> he hinted, whether it was possible to add a "content aspect" to the
>>>>> SecurityContext / RunAs. Say "Manager1" could only manipulate or see movies
>>>>> by "Quentin Tarantino" while "Manager2" could only do so for "Joel Coen".
>>>>>
>>>>
>>>> It sounds interesting and a bit like the entity equivalent of row level
>>>> security in a SQL DB. I have to leave it to Alex to answer anything
>>>> definite here about this being in scope of this JSR.
>>>>
>>>> As mentioned by Alex, an important goal of the JSR is to grab the
>>>> really low hanging fruit; the obvious things that for some reason or the
>>>> other never have been standardised before. It's an open question if we'll
>>>> be able to get to the more advanced things.
>>>>
>>>>
>>>>>
>>>>> Actually looking at the large PDF Alex presented at least in Paris
>>>>> (and probably also London or JavaOne?) this sounds like involving "Dynamic
>>>>> Role Mapping" with roles like "EDIT_ACCOUNTS", "CLOSE_ACCOUNT", etc. If
>>>>> this was done on a fine grained level like "EDIT_TARANTINO_FILMS" vs.
>>>>> "EDIT_COEN_FILMS" just to give an example (or say "VIEW_ADULT_FILMS" based
>>>>> on a person's age;-) it might go in the direction of what the client uses
>>>>> here and Oliver suggested.
>>>>>
>>>>
>>>> In case of the row level security equivalent, my guess would be that
>>>> (JPA) entities have to support some notion of security constraints; a kind
>>>> of cross between bean validation and @RolesAllowed. I.e. a roles allowed
>>>> placed on a "value", and the entity manager checking this for various
>>>> operations.
>>>>
>>>> Fine grained roles could be done by simply giving user "Manager1" the
>>>> role "EDIT_TARANTINO_FILMS", etc, right?
>>>>
>>>> Or is "Manager1" a role name here, and do you mean that someone with
>>>> role "Manager1" should also get role "EDIT_TARANTINO_FILMS"? If that's the
>>>> case it would more be a matter of (standardised) group to role mapping
>>>> perhaps.
>>>>
>>>> Dynamic role mapping, where for every authorization decision roles are
>>>> dynamically evaluated is in fact today possible via JACC. A (custom) JACC
>>>> provider is called every time @RolesAllowed and access to a URL is
>>>> evaluated and can do things like taking time into account.
>>>>
>>>> JEUS has a native authorization system that is very JACC like. They
>>>> have some interested added concepts, like that in a role mapping you have
>>>> the tuple {role name, action, class name}.
>>>>
>>>> See
>>>> https://translate.google.com/translate?&u=http%3A%2F%2Ftechnet.tmaxsoft.com%2Fupload%2Fdownload%2Fonline%2Fjeus%2Fpver-20150722-000001%2Fsecurity%2Fchapter_security_system_API_programming.html
>>>>
>>>> Taking age into account is more difficult, since the authorisation
>>>> system has to know where it can find the age of the caller. For the
>>>> proposed new annotation that takes an EL expression this should be quite
>>>> doable (you pass the age in), but for web.xml security constraints this is
>>>> more difficult.
>>>>
>>>> But these are all good points for the authorization epic of this JSR ;)
>>>>
>>>>
>>>>
>>>>
>>>>
>>>>>
>>>>> Kind Regards,
>>>>> Werner
>>>>>
>>>>> On Thu, Dec 17, 2015 at 5:24 AM, Werner Keil <werner.keil_at_gmail.com>
>>>>> wrote:
>>>>>
>>>>>> All,
>>>>>>
>>>>>> Had a great talk yesterday. At least 50-70 people (guess DevoXX Be
>>>>>> probably had more, not sure about FR or Uk?) in a cinema very similar to
>>>>>> Antwerp ;-)
>>>>>>
>>>>>> I invited those interested to join the mailing list or Github. Right
>>>>>> before my Session was one on the value of Open Source which was a good
>>>>>> introduction. Will Post slides on Slideshare. Thanks everyone especially
>>>>>> Arjan.
>>>>>>
>>>>>> Regards,
>>>>>> Werner
>>>>>> Am 15.12.2015 18:48 schrieb "arjan tijms" <arjan.tijms_at_gmail.com>:
>>>>>>
>>>>>>> Hi,
>>>>>>>
>>>>>>> Another update: I finally came around to implementing an
>>>>>>> experimental version of the simplified SAM.
>>>>>>>
>>>>>>> This version is based on the HttpServerAuthModule that was used in
>>>>>>> several examples before, and which in turn was based on the one from
>>>>>>> OmniSecurity.
>>>>>>>
>>>>>>> The difference is that instead of a base class, it's now an
>>>>>>> interface (as previously discussed). It closely follows the methods of a
>>>>>>> SAM, but the type implementing it is no longer a SAM itself.
>>>>>>>
>>>>>>> For now I've defined the interface as follows:
>>>>>>>
>>>>>>> public interface HttpAuthenticationMechanism {
>>>>>>>
>>>>>>> AuthStatus validateRequest(HttpServletRequest request,
>>>>>>> HttpServletResponse response, HttpMsgContext httpMessageContext) throws
>>>>>>> AuthException;
>>>>>>>
>>>>>>> default AuthStatus secureResponse(HttpServletRequest request,
>>>>>>> HttpServletResponse response, HttpMsgContext httpMessageContext) throws
>>>>>>> AuthException {
>>>>>>> return SEND_SUCCESS;
>>>>>>> }
>>>>>>>
>>>>>>> default void cleanSubject(HttpServletRequest request,
>>>>>>> HttpServletResponse response, HttpMsgContext httpMessageContext) {
>>>>>>> httpMessageContext.cleanClientSubject();
>>>>>>> }
>>>>>>>
>>>>>>> }
>>>>>>>
>>>>>>> See
>>>>>>> https://github.com/arjantijms/mechanism-to-store-x/blob/master/jsr375/src/main/java/javax/security/authenticationmechanism/http/HttpAuthenticationMechanism.java
>>>>>>>
>>>>>>>
>>>>>>> The JSR 375 CDI extension scans for the one and only implementation
>>>>>>> of HttpAuthenticationMechanism, and if found installs a bridge SAM for it
>>>>>>> that calls this implementation for each method: E.g. for validateRequest it
>>>>>>> looks like this:
>>>>>>>
>>>>>>> public AuthStatus validateRequest(MessageInfo messageInfo, Subject
>>>>>>> clientSubject, Subject serviceSubject) throws AuthException {
>>>>>>> HttpMsgContext msgContext = new HttpMsgContext(handler, options,
>>>>>>> messageInfo, clientSubject);
>>>>>>> return CDI.current()
>>>>>>> .select(HttpAuthenticationMechanism.class).get()
>>>>>>> .validateRequest(msgContext.getRequest(),
>>>>>>> msgContext.getResponse(), msgContext);
>>>>>>> }
>>>>>>>
>>>>>>> Just like the identity store, applications can now use a "sam" by
>>>>>>> only having an implementation of HttpAuthenticationMechanism on their
>>>>>>> classpath. The code now looks much simpler too. E.g. the example SAM used
>>>>>>> before is simplified into this:
>>>>>>>
>>>>>>> @RequestScoped
>>>>>>> public class TestAuthenticationMechanism implements
>>>>>>> HttpAuthenticationMechanism {
>>>>>>>
>>>>>>> @Inject
>>>>>>> private IdentityStore identityStore;
>>>>>>>
>>>>>>> @Override
>>>>>>> public AuthStatus validateRequest(HttpServletRequest request,
>>>>>>> HttpServletResponse response, HttpMsgContext httpMessageContext) throws
>>>>>>> AuthException {
>>>>>>>
>>>>>>> if (request.getParameter("name") != null &&
>>>>>>> request.getParameter("password") != null) {
>>>>>>>
>>>>>>> // Get the (caller) name and password from the request
>>>>>>> // NOTE: This is for the smallest possible example only.
>>>>>>> In practice
>>>>>>> // putting the password in a request query parameter is
>>>>>>> highly
>>>>>>> // insecure
>>>>>>> String name = request.getParameter("name");
>>>>>>> Password password = new
>>>>>>> Password(request.getParameter("password"));
>>>>>>>
>>>>>>> // Delegate the {credentials in -> identity data out}
>>>>>>> function to
>>>>>>> // the Identity Store
>>>>>>> CredentialValidationResult result =
>>>>>>> identityStore.validate(
>>>>>>> new UsernamePasswordCredential(name, password));
>>>>>>>
>>>>>>> if (result.getStatus() == VALID) {
>>>>>>> // Communicate the details of the authenticated user
>>>>>>> to the
>>>>>>> // container. In many cases the underlying handler
>>>>>>> will just store the details
>>>>>>> // and the container will actually handle the login
>>>>>>> after we return from
>>>>>>> // this method.
>>>>>>> return httpMessageContext.notifyContainerAboutLogin(
>>>>>>> result.getCallerName(),
>>>>>>> result.getCallerGroups());
>>>>>>> } else {
>>>>>>> throw new AuthException("Login failed");
>>>>>>> }
>>>>>>> }
>>>>>>>
>>>>>>> return httpMessageContext.doNothing();
>>>>>>> }
>>>>>>>
>>>>>>> }
>>>>>>>
>>>>>>> See:
>>>>>>> https://github.com/arjantijms/mechanism-to-store-x/blob/master/app-db/src/main/java/test/TestAuthenticationMechanism.java
>>>>>>>
>>>>>>> One partially unsolved problem, which I happen to have discussed
>>>>>>> with Ron Monzillo some time ago, is how module options should neatly arrive
>>>>>>> in this CDI enabled SAM. Currently they can be obtained from the
>>>>>>> HttpMsgContext. Ideally though, you may want to inject them and do
>>>>>>> something in the @PostConstruct method.
>>>>>>>
>>>>>>> But as those module options are per SAM, and there can be multiple
>>>>>>> SAMs, even of the same class type, I was struggling a little on how to
>>>>>>> support that.
>>>>>>>
>>>>>>> CDI itself has something like this with their Bean<T>, and they use
>>>>>>> a unique ID for that that is typically set to just the classname, but can
>>>>>>> be more eloborate if needed. Typically the values of constructor parameters
>>>>>>> are included if the Bean<T> has one. See e.g.
>>>>>>> https://github.com/javaserverfaces/mojarra/blob/master/jsf-ri/src/main/java/com/sun/faces/cdi/CdiProducer.java#L97
>>>>>>>
>>>>>>> Kind regards,
>>>>>>> Arjan Tijms
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>> On Mon, Dec 14, 2015 at 11:43 AM, Werner Keil <werner.keil_at_gmail.com
>>>>>>> > wrote:
>>>>>>>
>>>>>>>> Hi,
>>>>>>>>
>>>>>>>> Thanks for the update. I will try it in WildFly at some point, but
>>>>>>>> especially the current client and environment (where especially some ideas
>>>>>>>> in the JSR like "roles allowed" found here
>>>>>>>> https://github.com/javaee-security-spec/javaee-security-examples
>>>>>>>> would be of interest in theory) are not even able to use WildFly or Java EE
>>>>>>>> 7 and probably won't be for another decade, so it is not so urgent before
>>>>>>>> codemotion.
>>>>>>>>
>>>>>>>> Kind Regards,
>>>>>>>>
>>>>>>>> Werner Keil
>>>>>>>>
>>>>>>>> On Mon, Dec 14, 2015 at 11:21 AM, arjan tijms <
>>>>>>>> arjan.tijms_at_gmail.com> wrote:
>>>>>>>>
>>>>>>>>> Hi,
>>>>>>>>>
>>>>>>>>> On Mon, Dec 14, 2015 at 12:25 AM, Werner Keil <
>>>>>>>>> werner.keil_at_gmail.com> wrote:
>>>>>>>>>
>>>>>>>>>> It works well in Glassfish 4, Wildfly 10 did not,
>>>>>>>>>
>>>>>>>>> [...]
>>>>>>>>>
>>>>>>>>> Yes, I did not modify it
>>>>>>>>>>
>>>>>>>>>
>>>>>>>>> Again a life "proof" of how important it is that WildFly does not
>>>>>>>>> require the modification ;)
>>>>>>>>>
>>>>>>>>> You're not the first one to fall into this. Quite a few people
>>>>>>>>> think it doesn't work on JBoss, since this modification is so non-obvious.
>>>>>>>>>
>>>>>>>>> Or the modification is done once, and then later a new install of
>>>>>>>>> JBoss (WildFly) is done and the modification is forgotten again (this
>>>>>>>>> happens all the time over at the Java EE 7 samples project for the CI).
>>>>>>>>>
>>>>>>>>> Kind regards,
>>>>>>>>> Arjan Tijms
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>
>>>>>>>
>>>>>
>>>>
>>>
>>