Hi,
On Mon, Mar 21, 2016 at 10:55 PM, Darran Lofthouse <
darran.lofthouse_at_redhat.com> wrote:
> I will have a look, the Elytron approach for multiple mechanisms is coming
> together, will see if we can adapt something similar specifically for use
> with the Servlet APIs.
>
Okay, would be interesting.
Once small concern is perhaps that this approach has not really been tried
in practice, or has it? Until now most things in JSR 375 are "merely'
standardised and CDI-fied versions of things that all or most servers
already do. I don't think this is an absolute requirement, but something to
keep in mind,
>
> A wrapper is always quite hard as you really also need the mechanism to be
> split into two steps so it knows it is in the 'attempting to authenticate'
> phase or 'challenging' state.
As I understand your approach now, my feeling says it should be doable.
It's not so much a wrapper. It's more an early entry point in the request
processing pipe line where you get the request and response objects. From
there you can basically do anything.
That entry point would then be the validateRequest() method, and from there
you can call the multi step aware mechanisms
(HttpServerAuthenticationMechanism in your earlier example) which of course
don't have to be related in any way to the HttpAuthenticationMechanism.
Something like:
public class MultiAuthenticationMechanism implements
HttpAuthenticationMechanism {
public AuthStatus validateRequest(HttpServletRequest request,
HttpServletResponse response, HttpMessageContext httpMsgContext) {
List<HttpServerAuthenticationMechanism> mechanisms =
getFromSomewhere();
List<HttpServerRequestImpl> requests = new ArrayList();
// First phase
for (HttpServerAuthenticationMechanism mechanism : mechanisms) {
HttpServerRequestImpl httpServerRequest = new
HttpServerRequestImpl (request);
requests.add(httpServerRequest);
mechanism.evaluateRequest(httpServerRequest);
if (httpServerRequest.authenticationComplete() {
SecurityIdentity identity =
httpServerRequest.getIdentity();
return httpMsgContext.notifyContainerAboutLogin(
identity.getPrincipal(),
toList(identity.getRoles()));
}
}
// Second phase
for (HttpServerRequestImpl httpServerRequest : requests) {
httpServerRequest.getResponder().sendResponse(response);
if (httpServerRequest.authenticationInProgress()) {
return SEND_CONTINUE;
}
}
}
I don't know yet how your API exactly works, so the above is just a rough
sketch ;)
Kind regards,
Arjan Tijms
>
>
> On 21/03/16 18:31, arjan tijms wrote:
>
>> True, but remember the mechanism as it's defined now is only EDR1
>> status. Much can still be changed.
>>
>> Time as always is a bit of the issue. I only have so much hours I can
>> spend on JSR 375, and there's quite an amount of other things that also
>> would be really nice to have. For instance, we also don't have the
>> multiple identity stores done yet.
>>
>> As for the multiple mechanisms though, is there any other server or
>> security framework that you know of that has this? Or is
>> Undertow/Elytron currently the only one?
>>
>> To get the multiple authentication mechanisms story going, perhaps best
>> to start with creating an issue at the JSR 375 tracker and coding up a
>> proposal for the
>> https://github.com/javaee-security-spec/javaee-security-proposals repo?
>> Do you think the multiple mechanisms could be implemented for the
>> proposal using the current mechanism as a base? E.g. a single
>> HttpAuthenticationMechanism implementation that does the 2-phased
>> "try-authenticate" as you explained before?
>>
>> Additionally, I wonder if any of the other EG members have a particular
>> opinion, idea or use case for the multiple mechanisms story. Would be
>> great to collect the ideas around this.
>>
>> Kind regards,
>> Arjan Tijms
>>
>>
>>
>>
>>
>> On Mon, Mar 21, 2016 at 6:53 PM, Darran Lofthouse
>> <darran.lofthouse_at_redhat.com <mailto:darran.lofthouse_at_redhat.com>> wrote:
>>
>> I still think there is big gap here in that multiple mechanisms will
>> not be able to operate concurrently.
>>
>>
>> On 13/03/16 23:58, arjan tijms wrote:
>>
>> Hi,
>>
>> I just implemented a clone of Servlet's FORM authentication
>> mechanism
>> using the proposed JSR 375 API. A demo app showing it can be
>> found at
>>
>> https://github.com/javaee-security-spec/soteria/tree/master/test/app-mem-form
>>
>> The mechanism itself looks like this:
>>
>> @AutoApplySession
>> @LoginToContinue
>> @Typed(FormAuthenticationMechanism.class)
>> public class FormAuthenticationMechanism implements
>> HttpAuthenticationMechanism, LoginToContinueHolder {
>> private LoginToContinue loginToContinue;
>>
>> @Inject
>> private IdentityStore identityStore;
>> @Override
>> public AuthStatus validateRequest(HttpServletRequest request,
>> HttpServletResponse response, HttpMessageContext
>> httpMessageContext)
>> throws AuthException {
>> if ("POST".equals(request.getMethod()) &&
>> request.getRequestURI().endsWith("/j_security_check")) {
>> if (notNull(request.getParameter("j_username"),
>> request.getParameter("j_password"))) {
>>
>> CredentialValidationResult result =
>> identityStore.validate(
>> new UsernamePasswordCredential(
>> request.getParameter("j_username"),
>> new
>> Password(request.getParameter("j_password"))));
>>
>> if (result.getStatus() == VALID) {
>> return
>> httpMessageContext.notifyContainerAboutLogin(
>> result.getCallerPrincipal(),
>> result.getCallerGroups());
>> } else {
>> throw new AuthException("Login failed");
>> }
>> }
>> }
>> return httpMessageContext.doNothing();
>> }
>>
>> See
>>
>> https://github.com/javaee-security-spec/soteria/blob/master/impl/src/main/java/org/glassfish/soteria/mechanisms/FormAuthenticationMechanism.java
>>
>>
>> This leans heavily on the @AutoApplySession and @LoginToContinue
>> interceptors, which can both be re-used by other mechanisms,
>>
>> The heart of the @LoginToContinue interceptor contains this code:
>>
>> private AuthStatus validateRequest(InvocationContext
>> invocationContext,
>> HttpServletRequest request, HttpServletResponse response,
>> HttpMessageContext httpMessageContext) throws Exception {
>>
>> if (isOnProtectedURLWithStaleData(httpMessageContext)) {
>> removeSavedRequest(request);
>> }
>> if (isOnInitialProtectedURL(httpMessageContext)) {
>> saveRequest(request);
>> return httpMessageContext.forward(
>>
>> getLoginToContinueAnnotation(invocationContext).loginPage());
>> }
>> if (isOnLoginPostback(request)) {
>> AuthStatus authstatus = null;
>> try {
>> authstatus = (AuthStatus)
>> invocationContext.proceed();
>> } catch (AuthException e) {
>> authstatus = FAILURE;
>> }
>> if (authstatus == SUCCESS) {
>> if (httpMessageContext.getCallerPrincipal() ==
>> null) {
>> return SUCCESS;
>> }
>> RequestData savedRequest =
>> getSavedRequest(request);
>> if (!savedRequest.matchesRequest(request)) {
>> saveAuthentication(request, new
>> CredentialValidationResult(
>> VALID,
>> httpMessageContext.getCallerPrincipal(),
>> httpMessageContext.getGroups()));
>> return
>> httpMessageContext.redirect(savedRequest.getFullRequestURL());
>> } // else return success
>> } else {
>> return httpMessageContext.redirect( // TODO:
>> or forward?
>> getBaseURL(request) +
>>
>> getLoginToContinueAnnotation(invocationContext).errorPage());
>> }
>> }
>>
>> if (isOnOriginalURLAfterAuthenticate(request)) {
>> return httpMessageContext
>> .withRequest(new
>> HttpServletRequestDelegator(request,
>> requestData))
>> .notifyContainerAboutLogin(
>> result.getCallerPrincipal(),
>> result.getCallerGroups());
>> }
>> return httpMessageContext.doNothing();
>> }
>>
>> See:
>>
>> https://github.com/javaee-security-spec/soteria/blob/master/impl/src/main/java/org/glassfish/soteria/cdi/LoginToContinueInterceptor.java
>>
>>
>> FORM is a rather nasty mechanism to implement, and going for the
>> re-usable parts took a little extra time, but it does show that
>> the
>> proposed mechanism API is capable of implementing a quite
>> demanding set
>> of requirements (FORM is really surprisingly demanding for such
>> an old
>> mechanism).
>>
>> Do note that both design and implementation are rather rough at
>> the
>> moment and could do with some refinements still. But I think
>> this could
>> work for an early draft.
>>
>> Kind regards,
>> Arjan Tijms
>>
>>
>>
>>
> --
> Darran Lofthouse - Principal Software Engineer
>
> Registered in England and Wales under Company Registration No. 03798903
> Directors: Michael Cunningham (US), Michael O'Neill(Ireland), Paul Argiry
> (US)
>