Re: Welcome to the new JSR-375 mailing list


Arjan Tijms
 

Hi,

On Tue, May 16, 2017 at 11:41 AM, Will Hopkins <will.hopkins@...> wrote:
I agree that the existing mechanisms aren't modern, and that there may be use cases where developers want or need to modify the process. That said, I think the legitimate use cases are probably few and far between. Existing implementations of FORM and BASIC have been refined over the years, such that they are robust and handle most reasonable requirements.

The entire purpose of the JSR was though to modernise security and make it more easy for users to us. Sure everything in the various Java EE servers have been refined over the years and handle most reasonable requirements, but if we take that as our most important principal, JSR 375 might not even have been needed (which I don't think is the case).

FORM in it's current uhm form is not modern and certainly not easy to use. There's a mismatch in the mental model between how FORM is to be used and how modern applications are programmed.

 
The example you provide above demonstrates the capability, but doesn't demonstrate the need -- in my view, intervening to check username/password length before actually validating the credentials is misguided on separation of duties grounds -- only the identity store can authoritatively say whether the credentials are valid or not -- and is potentially insecure. Best practice when validating credentials is to return "login failed" for all failure cases, regardless of the cause.

I do agree about not giving the user too much information, that's definitely true. But the fact that you have to enter anything at all is not the kind of information you need to withhold. The password length and various constraints can already be learned when you sign up for a new account, so it's also not something you need to withhold in many cases (cases of public websites mostly).

Look at what e.g. Oracle.com does when you login; https://login.oracle.com/mysso/signon.jsp

If you don't enter anything it says:

"Please enter your username and password"

But even if you don't like the binding and bean validation, the part where you continue the dialog programmatically and set the single "login failed" message from the backing bean is already very valuable. This too is non-obvious how to do when posting to j_security_check,

 
I have not heard feedback from our customers that they need or want to extend the functionality provided by FORM or BASIC authentication in WebLogic.

When I was working on various projects for various companies this need came up quite often. As said, especially in JSF/CDI applications the existing authentication mechanisms are contrived and arcane. I've seen people either struggling to get it integrated, or even more often, don't use the Servlet mechanisms at all but just use Shiro or roll their own variant.

There was a request for this in the JSF JIRA tracker as well, the issue with the most votes actually. We closed it in JSF because we felt such concern would be better handled by the Security JSR.


 
Also -- is it not possible to reference a CDI bean, or perform validation on j_username/j_password in some other way, from a login form using the existing mechanism?

All the existing ways are not so obvious. Sure, it's possible, but that's not the main point of the JSR, which is not only about making things possible, but about making things easier and more aligned with modern Java EE.

 
My proposal would be specify that the container should use an application-supplied IdentityStore for FORM/BASIC if present, but also that the container is permitted to override an application-provided IdentityStore with one of its own. i spent some time reading the CDI spec, and it appears to me that this would be possible by observing events during bean discovery and replacing the application's bean with a container bean when the appropriate event is fired -- I'm still not sure which event is the most appropriate one, though -- I'd be interested in your thoughts, as you clearly know CDI better than I.

Yes, the latter should indeed be possible via CDI. I would say the container is allowed to override the IdentityStoreHandler even, as that one is the true entry point to the identity stores.

By overriding the handler it would make sure that only the container's version is used of everything.

Additionally, the container could also be allowed to just add one or more identity stores, as the default handler is capable of working with multiple ones. That way it would be relatively easy to have the container provided store be at the highest priority with the app provided one as the fallback, or the other way around.

 
Agreed, and I'm generally a fan of consistency. In this case, the question in my mind is whether consistency alone is a good enough reason to require containers to provide this functionality when it would impose an implementation cost on container vendors and there is no clear functional requirement driving it.

The consistency aspect is already one advantage, while being able to decorate or intercept the mechanism is quite an advantage too. That way you can add a lot of things, from auditing (logging the calls to the mechanism and its response), adding SSO capabilities, and what have you. It basically gives applications (and libraries) more handles to extend Java EE security, where the existing mechanisms don't have any.

And containers using the RI and not wishing to put extra effort in can always use the RI provided ones, which are there to be used as well.


Your concern is valid, but we took this into account earlier. I think we had discussions with Alex and perhaps David about this way in the beginning. That's why it says "as defined by the Servlet spec". A lot of thought went onto that seemingly simple fragment of text.

Good to know. Does he existing RI implementation meet that requirement?

It should be, certainly in spirit, as both were implemented following the Servlet spec to the letter, and well over a year of practical testing didn't reveal any inconsistencies. Of course there's always more tests that can be done, but the intend is it follows that requirement indeed.


 
If a vendor chooses to provide two implementations of FORM/BASIC, that problem will still remain. Mandating functionality to drive testing seems like the tail wagging the dog; a focus on a robust TCK seems like a better approach.

That too, of course. But in practice having extension APIs actually be used instead of just being an extension waiting for a user to implement them, has seem to be incredibly useful.

Like I mentioned, in JSF the default component set uses the UIComponent type itself too. So a number of issues were discovered with it because we ourselves had to use it too.

The problem with the TCK only approach is that once it's final, it's final. So you have to predict all cases in advance. But you often can't predict it when you're not actually using it.


 
I don't know these technologies well enough to have an informed opinion on whether h:outputText is duplicative of c:out, but it does seem that JSF is layered on JSP/JSTL in a way that, in my conception, JSR-375 is not layered on Servlet. Although JSR-375 and Servlet are different specs, they are tightly integrated, rather than one being simply layered on top of the other.

Functionality wise h:outputText and c:out are duplicates in JSP.

In Facelets, JSF re-implemented JSTL, meaning you have the exact same tags and namespaces but with a different implementation. That doesn't just concern c:out but the entire JSTL library.

In JSR 375 some things are layered on Servlet, some things are integrated. As it stands the RI is mostly layered, but there are various options in the spec for vendors choosing more integration.

 
I still feel like RememberMe is not well-defined. If it's really a session management facility, then it's under-specified, it shouldn't be delegating to an IdentityStore, and there's no clear rationale for implementing a new session management capability in addition to what the container already provides. Existing container session management is almost certainly more robust and more secure than RememberMe. I would argue that long-lived sessions are a bad idea (as distinct from long-lived authentication tokens), but existing containers allow for configurable session lifetimes.

Configurable session lifetimes would absolutely not help, as a longer session has many side effects, mostly massively increased memory usage.

The major point is that remember me represents a long-lived authentication token. It's really not a session management facility.

 
If it's really an authentication token service, then, again, it's underspecified. There are certainly use cases for long-lived tokens, but the specifics of the token matter.

That's a detail of the implementation of the remember me identity store. The token has to be sufficiently random and the application should store a hash of it, not the token itself.

But at this point these are not concerns for JSR 375. The token only has to be read back by the application that vended it, there's no requirement for any interoperation. Compare this to e.g. a string based password. The mechanism and store only have to accept an opaque string, but what's in the string is an application / business logic concern, not a spec concern.


 
The best way to think about RememberMe is probably in terms of a generic mechanism for token issuance, and that seems to be the intent of RememberMeIdentityStore. But it's not fully "plumbed" -- since HAMs are supposed to interact only with IdentityStoreHandler, not IdentityStore,

The key insight perhaps is that remember me is an authentication mechanism interceptor. It doesn't work primarily on the identity store level, but on the authentication  mechanism level.

As explained in the previous mail, when a request comes in the interceptor chain first looks at the session, then inspects the request for a token to be present (which is at the authentication mechanism level) and then when it encounters such token it will validate this token against the RememberMeIdentityStore.

So it's quite a fully plumbed and integrated whole, but you need to be aware of it working not only at the identity store level, but at the authentication mechanism level as well. This is also one example of what can be done with interceptors for authentication mechanisms.

 
shouldn't IdentityStoreHandler expose generateLoginToken()?

No, this was considered, but ultimately it was agreed that the RememberMeIdentityStore is a sufficiently different kind of store that we should not burden the handler with its extra complexity.

The remember me identity store is to be used exclusively by the remember me interceptor, and therefor should not even be mixed with the collection of stores that are to be invoked by the authentication mechanisms.

 
Also, the removeLoginToken() method is more consistent with a session model than a token issuance model -- issued tokens, especially long-lived ones, are typically not cached because there's no need to -- they can be cryptographically verified, and they contain all the information needed for user identification and authentication.

They can, but in remember me you often want to revoke a specific token. For instance, at an application level the tokens can be assigned names (library, work, home, ...) or IP addresses can be stored, which gives the application the ability to show users a list of all locations they are currently "logged-in" and the ability to remove that login.

Of course it's not an actual login, but just the acceptance of a specific token that happens to be stored at that location.

 
Lastly, the RememberMe annotation provides very little configurability -- it only supports cookies (not, e.g., HTTP headers, or form fields), and even for cookies allows configuration only for cookie name and lifetime.

Those can be expanded over time, of course. For a 1.0 release cookies should be fine. They are the most commonly used artefact. See e.g. http://stackoverflow.com/a/244907/472792 and https://paragonie.com/blog/2015/04/secure-authentication-php-with-long-term-persistence#title.2

Annotations, which are the entry point to configurability, are very easily extendable (add attributes to them in a backwards compatible way).

It may be a good idea though to add a general key/value map, so vendors can extend the configuration (of which the most popular ones can be put up for standardisation later). Then again, a second vendor specific annotation is always an option as well, so we as spec would not have to worry about that.

 
RememberMe doesn't seem sufficiently well thought out yet.

It really is; a lot of alternatives were considered and rejected, and we looked a lot at existing implementations both in Java and elsewhere. 

Also, as I mentioned, I tested the RI implementation for well over a year, and my previous website https://zeef.com used an approach quite like this since half of 2013 and later on was updated to use exactly this approach. With 200k pageviews a month and ~5k logins a month over a period of 4 years this must certainly count as something that was extensively tested in practice and tuned over the years.

Additionally, this feature was extensively discussed with JSF EG member and general web expert (SO top user) Bauke Scholtz, so we had input from there too.

 
As noted above, that sounds more like a long-lived authentication token than a session.


Indeed, that's exactly what I mentioned above ;) It is a long-lived authentication token and not a session management facility of any kind.


 
I think a key conceptual difference between what happens in step 2 and what happens in step 3. Step two is the container identifying an authentication token and using it to authenticate the user. The function/behavior of step 3 depends on whether FORM is just an alternative authentication mechanism (because multiple acceptable mechanisms are available), or whether step 3 is really a redirect to a token issuance service. (Not necessarily a literal redirect, but a logical redirect.)


Indeed, step 2 and step 3 are conceptually different. Step 1 and 2, while different have a number of things in common.

In both cases, step 1 and 2 prevent the caller from having to go through an authentication dialog for every request. But they are an hierarchy, for step 1, step 2 seems to be the source authentication mechanism, while for step 2 it seems step 3 is (and here it actually is).

 
I think the answer is that one is a session cookie and the other is not (it's an authentication token).

True

 
If the model is really token issuance, the fact that only cookies are supported seems like a bit limitation.

Not sure if it's really a limitation as such at the moment. Especially for the 1.0 release Alex mentioned to go for the low hanging fruit first, which here are cookies. It's designing the initial version of the spec for the 80% out there. The fact that cookies are used now does not exclude other things to be used at a later stage.
 
Yes -- thanks for the explanations. I still don't think RememberMe is ready to specify, but I'm more comfortable with the FORM and BASIC annotations. Do you think you could send me a brief write-up of those today?

I could for sure. The core specification of them is in the annotation now, but as appeared in this conversation it certainly wouldn't hurt to provide more clarification about this in the spec document.

Kind regards,
Arjan Tijms


 

Thanks,

Will


Thanks for your thorough review!

Kind regards,
Arjan Tijms


 


Will

-- 
Will Hopkins | WebLogic Security Architect | +1.781.442.0310
Oracle Application Development
35 Network Drive, Burlington, MA 01803


-- 
Will Hopkins | WebLogic Security Architect | +1.781.442.0310
Oracle Application Development
35 Network Drive, Burlington, MA 01803


Join javaee-security-spec@javaee.groups.io to automatically receive all group messages.