spring-projects / spring-security

Spring Security
http://spring.io/projects/spring-security
Apache License 2.0
8.82k stars 5.9k forks source link

FormLogin to be configurable to take in username and password as json. #10966

Open Toerktumlare opened 2 years ago

Toerktumlare commented 2 years ago

Expected Behavior

FormLogin should be configurable to take in username and password as a predefined json object.

Current Behavior

FormLogin currently only accepts requests with form parameters.

Context

Most people today that write front end application deal with json and not form parameters. Its very easy to send form parameters using javascript fetch, but most just dont do it. They usually want to send data using json, and in 99% of the cases they send it as:

{
    "username": "foobar",
    "password": "secret"
}

currently the only way to get spring security to handle this is to completely opt-out from form login, and instead write either a custom filter or a custom endpoint which has to create the security context manually. This leads to many confusing questions on stack overflow, faulty implementations, and general opinions on spring security being overly complex just to do something as simple as a json formatted login.

My proposal is that either formLogin should be, just like the oauth resource server part of spring security (that can be configured to either take an opague token or a jwt) configurable to take form login parameters or json login parameters.

Example:

formLogin(formLoginSpec::json)

Many also wish to return JWTs after login to establish a session (which im not a big fan of but that is my personal opinion) then they can leverage features in form login like AuthenticationSuccessHandlers to build their JWTs, which i find fits the spring security features better than many constructing custom filters etc.

sjohnr commented 2 years ago

@Tandolf, thanks for the suggestion! Have a look at AuthenticationFilter. This class has strong parity with AuthenticationWebFilter and is highly flexible, yet isn't used in any built-in configurers as of yet. I'm curious what your thoughts are on using this class for this use case.

Toerktumlare commented 2 years ago

Hi @sjohnr i had a look at it and that class does look viable for the usercase above. But in the case of using that filter there needs to be a written a custom AuthenticationConverter supplied as a Bean that will convert the given json to a Authentication object.

But i believe that the filter you linked with a custom converter does solve the usercase. And then the option to configure the usage of it when opting in for formLogin.

I dont know if it even should be called formLogin, or if it should be called jsonLogin or just login. I leave the api up to the spring team.

sjohnr commented 2 years ago

Hi @Tandolf, I agree that naming is tough, often the most difficult part! 😄 This definitely sounds different from formLogin. But perhaps we can forestall that decision and focus on the converter first.

We could look at OAuth2AccessTokenResponseHttpMessageConverter in oauth2-client module for possible inspiration.

Toerktumlare commented 2 years ago

i cloned spring security and tried to get it to build but im not that well versed with gradle. I get a 401 unauthorized when it is trying to fetch a plugin io.spring.gradle-enterprise-conventions.gradle.plugin-0.0.2.jar during build.

But i looked a bit at the class you suggested but guess we could maybe use MappingJackson2HttpMessageConverter to convert the incoming json?

sjohnr commented 2 years ago

I'd have to double check in all scenarios, but I believe Jackson is an optional dependency (at least in oauth2-client). Therefore, OAuth2AccessTokenResponseHttpMessageConverter uses an internal utility HttpMessageConverters.getJsonMessageConverter() to resolve a GenericHttpMessageConverter. That's one possible approach to think about.