Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Multiple authentication mechanisms simultaneously #188

Open
tofflos opened this issue Jul 5, 2018 · 17 comments
Open

Multiple authentication mechanisms simultaneously #188

tofflos opened this issue Jul 5, 2018 · 17 comments

Comments

@tofflos
Copy link

tofflos commented Jul 5, 2018

I'm curious whether there has been any talk of supporting multiple authentication mechanisms simultaneously? The use case would be writing a JAX-RS endpoint that provides an API, some HTML/JS that provides an UI on top that API, and then bundling them together as a single application. I would then like to offer BASIC authentication for "machines" interacting directly with the API and FORM-based authentication for "humans" interacting indirectly via the UI.

@arjantijms
Copy link
Contributor

Yes, there have been multiple discussion about this.

Not just about having multiple authentication mechanisms next to each other, but also having them stacked (so that for e.g. for JAX-RS multiple ones are tried automatically), as well as allowing users to select one (for things like giving users a chose to login with facebook and login with email).

Darran from JBoss even drafted a detailed proposal for the stacked ones.

Your question basically comes down to installing authentication mechanisms per URL pattern, which has been discussed in less details, but certainly has been mentioned.

This is in scope for EE Security 1.1, so I'm hoping we're able to get to it ;)

@tofflos
Copy link
Author

tofflos commented Jul 7, 2018

Thank you for the response. I found the issue and mention in https://github.com/javaee/security-spec/issues/37:

Note that this feature is distinct from having different authentication mechanisms for different resources, like e.g. FORM for the web based UI part at /app/* of an application and BASIC for the REST part at say /rest/*.

Do you think it would be a good idea to create a dedicated issue for authentication-mechanism-per-URL-pattern?

I'm also curious whether the JSR or the RI is actively looking for contributors? I'm not great at application server internals but I'm pretty good at communication and evaluation. That could translate into unit/integration testing, proofreading and writing of documentation.

@arjantijms
Copy link
Contributor

Do you think it would be a good idea to create a dedicated issue for authentication-mechanism-per-URL-pattern?

Yes, absolutely. Best place for the issue would be https://github.com/eclipse-ee4j/security-api

That's the API project, and authentication-mechanism-per-URL-pattern would be an API addition first.

That could translate into unit/integration testing, proofreading and writing of documentation.

Sure, that's always needed. Basically just creating issues and providing comments (feedback) is already a contribution ;)

@ggam
Copy link
Contributor

ggam commented Jul 8, 2018 via email

@arjantijms arjantijms transferred this issue from eclipse-ee4j/soteria Sep 17, 2021
@keilw
Copy link
Member

keilw commented Sep 17, 2021

Given JAX-RS has no plans for Jakarta EE 10, that should be from 11 onwards, either in 3.0 (if that also got postponed there) or a 3.x follow-up.

@arjantijms
Copy link
Contributor

@keilw Essentially it would still work for Jakarta REST in most cases, and practically all cases for the given scenario, as most implementations layer on top of Servlet. So an authentication mechanism set for Servlet on a specific path or paths automatically applies to Jakarta REST. That's essentially how 99.9% AFAIK paths for REST are secured now; by setting constraints in web.xml.

@OndroMih
Copy link
Contributor

Is there any progress with this issue?

I created this proposal to support injection of built-in authentication mechanisms into a custom mechanism, which could be a light-weight solution to having multiple authentication mechanisms and choose from them either based on the URL, cookie, query parameter, etc.: jakartaee/security-examples#11.

The core idea is to make it possible to choose programmatically which of the built-in authentication mechanisms should be used based on configuration or user input. It would be possible to inject one or more mechanisms configured using the existing definition annotations (e.g. @BasicAuthenticationMechanismDefinition) and delegate authentication to them from a custom HttpAuthenticationMechanism bean.

Then it would be possible to choose between multiple mechanisms based on info in the request, e.g. URL, query parameters, cookies, etc. We can extend it by some helper functionality, e.g. to have a simple mechanism to select from the injected mechanisms using URL pattern matching, etc. Any suggestions welcome.

What do you think about it?

@m-reza-rahman
Copy link

m-reza-rahman commented Apr 10, 2023

Glad to see some movement on this issue. To be honest, this one might be the pragmatic way forward for JWT alignment, as long as the multiple mechanisms can include “external” mechanisms too. This may be a way for vendors to align older things they already have like SAML, SiteMinder, etc too.

@arjantijms
Copy link
Contributor

@darranl said:

"For 2 the problem is generally more complex than just one mechanism calling another, you generally need multiple mechanisms to be prompting at the same time to allow the client to select the mechanism it can support."

@arjantijms
Copy link
Contributor

For 2, we discussed back then the option to handle multiple mechanisms that way using phases. If I remember correctly, Elytron / Undertow / Picketbox had just started to experiment with that at the time

@darranl whatever happened to that experiment? Did Elytron / Undertow / Picketbox incorporate it and is it a mainstream feature now? Did you change / tune the API and/or process compared to what you presented in 2016/2017?

@arjantijms
Copy link
Contributor

@OndroMih said:

"My proposal would address the points 1. and 3. from the above. Actually, even 2. could be implemented, because a custom auth mechanism could call a built-in mechanism, and based on the result, it could call another auth mechanism. I believe my proposal is very light-weight, doesn't add any new API, and leaves a lot of power on the implementor of the custom auth mechanism. Without this, it's impossible to combine the built-in mechanisms in any way, because when a built-in mechanism is enabled, no other mechanism can be enabled with it."

@arjantijms
Copy link
Contributor

Without this, it's impossible to combine the built-in mechanisms in any way, because when a built-in mechanism is enabled, no other mechanism can be enabled with it.

At the moment this is an explicit check, since we didn't agree on how to handle the case in a portable way (as we did agree on for identity stores). The check can of course be fairly easily removed in newer versions of the specification.

That said, the idea to layer the support for multiple authentication mechanisms on top of a single one had been discussed indeed. As with the IdentityStoreHandler, it might still be good to introduce a new type though.

The "handler" is the one that handles the multiple other authentication mechanisms. A default can be provided (that just calls the one and only available one) with default behaviour on how to call multiple ones. Since it is its own type, the handler, and only the handler, can then be replaced using standard CDI alternatives with a custom implementation.

@OndroMih
Copy link
Contributor

The "handler" is the one that handles the multiple other authentication mechanisms. A default can be provided (that just calls the one and only available one) with default behaviour on how to call multiple ones. Since it is its own type, the handler, and only the handler, can then be replaced using standard CDI alternatives with a custom implementation.

Do you mean that a strategy to handle available authentication mechanisms would be implemented as a CDI bean, with a default bean just delegating to the first available auth. mechanism? And it would be possible to replace this strategy with a CDI alternative?

It looks like the main difference to what I proposed is that a user wouldn't inject other HAMs into the custom HAM, but would inject HAMs into a bean of a different type (e.g. name HAMStrategy?), which is a bit cleaner code and allows for more flexibility and less boiler plate in some cases. But it's also more complicated to design - for example, what would the handler/strategy do? Just delegate to other HAMs? Would it have different methods than the HAM interface?

@OndroMih
Copy link
Contributor

So, what do you think about my proposal in jakartaee/security-examples#11 about injecting built-in auth mechanisms into a custom HAM? I think it's a simpler solution than supporting a HAM strategy. We can add support for a custom HAM strategy later, I think both approaches make sense - mine is simpler for simpler usecases, HAM strategy is more complex for more complex usecases.

I'd like to create a PR in the spec project to add the feature I proposed in jakartaee/security-examples#11.

@arjantijms @keilw @tomas-langer @ggam @darranl @tofflos

@OndroMih
Copy link
Contributor

OndroMih commented Feb 2, 2024

I also have an example test in Soteria here, with slightly modified API, which doesn't require changes in Security API: https://github.com/OndroMih/soteria/blob/ondromih-auth-mech-injection-proposal/test/app-auth-mech-injection/src/main/java/org/glassfish/soteria/test/client/DelegatingAuthMechanism.java#L23

It doesn't pass because Soteria doesn't implement it yet, but my plan is to implement this in Soteria first, and then bring it up into the Security spec with a cleaner API, which I proposed initially.

@OndroMih
Copy link
Contributor

OndroMih commented Jul 21, 2024

I think that the combination of #309 and #311 already addresses this. The combination of those allows creating 2 different authentication mechanisms, or just define 2 standard auth mechanisms annotated with qualifiers, and then dynamically choose which to use inside a HttpAuthenticationMechanismHandler that can inject them and delegate to them.

Something like this:

@BasicAuthenticationMechanismDefinition ( realmName = "myRealm" )
@CustomFormAuthenticationMechanismDefinition ( loginToContinue = @LoginToContinue( loginPage = "/login.xhtml" ) )
@ApplicationScoped
public class MyAuthHandler implemens HttpAuthenticationMechanismHandler {
    @Inject
    @BasicAuthenticationMechanism // qualifier for the built-in BASIC mechanism
    HttpAuthenticationMechanism basicAuth;

    @Inject
    @CustomFormAuthenticationMechanism // qualifier for the built-in CUSTOM FORM mechanism
    HttpAuthenticationMechanism formAuth;


    AuthenticationStatus validateRequest ( HttpServletRequest request, HttpServletResponse response, HttpMessageContext context ) throws AuthenticationException {
        HttpAuthenticationMechanism chosenAuth = isRequestFromBrowser ( request ) ? formAuth : basicAuth;
        chosenAuth.validateRequest( request, response, context );
    }
}

@tofflos, would that be enough for your usecase? Can we close this issue?

@OndroMih
Copy link
Contributor

@m-reza-rahman, I think that this is also a good base for aligning MP JWT and Jakarta Security. The only thing missing is to have an authentication mechanism compatible with MP JWT. MP JWT only secures REST services, a general auth mechanism compatible with Jakarta Security is going to be provided by the new MP JWT Bridge specification I think. Vendors can provide their own mechanisms that integrate with MP JWT and could be injected and used from an HttpAuthenticationMechanismHandler.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants