quarkiverse / quarkus-renarde

Server-side Web Framework with Qute templating, magic/easier controllers, auth, reverse-routing
Apache License 2.0
78 stars 19 forks source link

JAX-RS endpoints no longer being hit with 3.0.3 or 3.0.4 #174

Open tmulle opened 1 year ago

tmulle commented 1 year ago

Trying the latest versions of renarde security (3.0.3 or 3.0.4) with Quarkus 3.4.1 causes my endpoints to no longer be hit.

I have a /login endpoint which works fine with previous versions, but trying them with the latest versions causes them to either silenty fail or not be hit at all (hard to tell since there are no errors).

Using this request for both versions and changing nothing else in the code. curl -v -c support_cookiefile --data "email=crmbot@foo.local&password=secret" http://localhost:8080/login

CURL OUTPUT

3.0.2

*   Trying 127.0.0.1:8080...
* Connected to localhost (127.0.0.1) port 8080 (#0)
> POST /login HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/8.1.2
> Accept: */*
> Content-Length: 41
> Content-Type: application/x-www-form-urlencoded
>
< HTTP/1.1 303 See Other
< Location: http://localhost:8080/
* Added cookie QuarkusUser="eyJjdHkiOiJKV1QiLCJhbGciOiJSU0EtT0FFUCIsImVuYyI6IkEyNTZHQ00ifQ.fUeT_LmPODjBm4vQibv2s2TygiLWLX9NRIL0sFx7Pe2VPtavXAup8C2KZuJ5lhy_71rMBCvEnUX3Rojw26wcaFndreEn_3QQv_XW2lS2PkFpHILqd65BE_mpU6qNX37VyYYp52nKovOrdx5tyooDLukRiKLeBQ4Kmc8yttcknsl4tCAPT9ltVUzDkARfnwH_rc5jbumI4UlURGpPJLs7dH1IgcVw5yMtFoHHdiMKC0Jjsq6c7fCTCSaZ3MVlXfejw3TwHjZvs2lV6wYE8DPpGKTKYF9v_M0-4Vq1DaQVhlf5jui0d7LDkODZbOskoYOvmqOJnDLLr16p_USgyDJUVQ._G6AsoEFOEaSU2ht.mgCfkCfxYo9BYmaHqBZjuD8e7C6kFjkzK2-WAIPXjOjgzXutd05c4OU7_DqvyWAj8-DeTVrtAjWSxoB0HAfyGHeDbVewxOj3dQ-7a1mFNIByLPK-2OiRcnbs6dwpATBPt_yfBlLSIZhxw1AkHL9hB6orrDDUsm3o0Dp3vVuuVSJPgcPKMLkr8Sk2tgeyQB8M2ueKYYd4FVoqce4bhP2bQgKgb0eG6RAksHRI_2Zx4_m4xKugYEb8uxNvSPAGDR_bFL0qE9CMyl9mTwBRk1RJcZfuWq6PZLwL8_Gb7jJ5ghVviq45ZydCyzUWP2TQGwh9VKLNCRgTCvu908m1kDXqqAPiIHYwmZNlU8Dltifef1wDQMF5TkKYi8QSbTxxP2nVC0fNJFwWhXDXaAlANEbf_yeWYyU6xBZrhGjNuaiPfmWhi0DS0x6SLLrzFKfTxSE72jLGUsjizfwun281ciY3bfGdMqXMumJvz-SLQnow8J0ZMStPMLZP-jMnuGgiSfGwzLjla9WJR8KT8vp9BHh9O24zbsEZ24PuTjuWmkTUYb3SScUyegbz0sqOjd4dFyNTkkN62NrI-WhSB2UaxA06UJHS4NNVIgfUC8dpSN2wrKA98kpR8-5oigNXQcCTk_WKwdJ7rEXErngtdEszoInZ-BqT6o7ku0F00j5AikUGJjLOEQ8X2xAzleRa1XSqojfEldx2ZN--DqAAxlqZJ9mUYhJwZmcCok7U02Y5QqDFqxLxges3t1aep2ObViEhLadqBuLYcDnFP4RhZ85IvCRhqqyEHCyumGNDv1o.1Fz016ChznUmU5yerw1NOg" for domain localhost, path /, expire 0
< Set-Cookie: QuarkusUser=eyJjdHkiOiJKV1QiLCJhbGciOiJSU0EtT0FFUCIsImVuYyI6IkEyNTZHQ00ifQ.fUeT_LmPODjBm4vQibv2s2TygiLWLX9NRIL0sFx7Pe2VPtavXAup8C2KZuJ5lhy_71rMBCvEnUX3Rojw26wcaFndreEn_3QQv_XW2lS2PkFpHILqd65BE_mpU6qNX37VyYYp52nKovOrdx5tyooDLukRiKLeBQ4Kmc8yttcknsl4tCAPT9ltVUzDkARfnwH_rc5jbumI4UlURGpPJLs7dH1IgcVw5yMtFoHHdiMKC0Jjsq6c7fCTCSaZ3MVlXfejw3TwHjZvs2lV6wYE8DPpGKTKYF9v_M0-4Vq1DaQVhlf5jui0d7LDkODZbOskoYOvmqOJnDLLr16p_USgyDJUVQ._G6AsoEFOEaSU2ht.mgCfkCfxYo9BYmaHqBZjuD8e7C6kFjkzK2-WAIPXjOjgzXutd05c4OU7_DqvyWAj8-DeTVrtAjWSxoB0HAfyGHeDbVewxOj3dQ-7a1mFNIByLPK-2OiRcnbs6dwpATBPt_yfBlLSIZhxw1AkHL9hB6orrDDUsm3o0Dp3vVuuVSJPgcPKMLkr8Sk2tgeyQB8M2ueKYYd4FVoqce4bhP2bQgKgb0eG6RAksHRI_2Zx4_m4xKugYEb8uxNvSPAGDR_bFL0qE9CMyl9mTwBRk1RJcZfuWq6PZLwL8_Gb7jJ5ghVviq45ZydCyzUWP2TQGwh9VKLNCRgTCvu908m1kDXqqAPiIHYwmZNlU8Dltifef1wDQMF5TkKYi8QSbTxxP2nVC0fNJFwWhXDXaAlANEbf_yeWYyU6xBZrhGjNuaiPfmWhi0DS0x6SLLrzFKfTxSE72jLGUsjizfwun281ciY3bfGdMqXMumJvz-SLQnow8J0ZMStPMLZP-jMnuGgiSfGwzLjla9WJR8KT8vp9BHh9O24zbsEZ24PuTjuWmkTUYb3SScUyegbz0sqOjd4dFyNTkkN62NrI-WhSB2UaxA06UJHS4NNVIgfUC8dpSN2wrKA98kpR8-5oigNXQcCTk_WKwdJ7rEXErngtdEszoInZ-BqT6o7ku0F00j5AikUGJjLOEQ8X2xAzleRa1XSqojfEldx2ZN--DqAAxlqZJ9mUYhJwZmcCok7U02Y5QqDFqxLxges3t1aep2ObViEhLadqBuLYcDnFP4RhZ85IvCRhqqyEHCyumGNDv1o.1Fz016ChznUmU5yerw1NOg;Version=1;Path=/;HttpOnly;SameSite=LAX
< content-length: 0
* Added cookie _renarde_crsf="3fDvp1ZeCiO/SwUJqWKMdA==" for domain localhost, path /, expire 0
< set-cookie: _renarde_crsf=3fDvp1ZeCiO/SwUJqWKMdA==; Path=/
* Added cookie _renarde_flash="e30=" for domain localhost, path /, expire 0
< set-cookie: _renarde_flash=e30=; Path=/; HTTPOnly; SameSite=Lax
<
* Connection #0 to host localhost left intact

3.0.4


*   Trying 127.0.0.1:8080...
* Connected to localhost (127.0.0.1) port 8080 (#0)
> POST /login HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/8.1.2
> Accept: */*
> Content-Length: 41
> Content-Type: application/x-www-form-urlencoded
>
< HTTP/1.1 400 Bad Request
< content-length: 0
* Added cookie _renarde_flash="e30=" for domain localhost, path /, expire 0
< set-cookie: _renarde_flash=e30=; Path=/; HTTPOnly; SameSite=Lax
<
* Connection #0 to host localhost left intact
FroMage commented 12 months ago

You're doing a POST without a CSRF token, that's why it doesn't work. I agree there should be an error message, though. If you're using {#form ...} you will get a CSRF token. If not, you need to obtain it before-hand with a GET request, which you can do with:

public Application extends Controller {
 @Inject
 CsrfTokenParameterProvider csrf;

 public String csrf(){
  return csrf.getToken();
 }
}

All of this works OOTB if using {#form} and Qute templates, or even in JUnit tests, using renarde-test.

What is the context in which you're calling this POST /login? Client Java library, or AJAX, or curl, or else?

tmulle commented 11 months ago

I was calling it from the curl command line and in the previous versions it would automatically work as I showed in the output above.

When using the latest version that automatic redirection no longer works.

FroMage commented 11 months ago

Well, it's not that it doesn't work, it's that it requires a CSRF token. All POST methods with a form body now require it. That has always been the goal, but issues prevented it from working properly.

Can you obtain a token before making your curl call?

Note that if you actually login from your browser, this will work out of the box.

tmulle commented 11 months ago

Ok, so you're saying it's a new requirement to have a CSRF token now, where before it was optional or it just worked without it.

Well, we have people who use their old scripts which use the CURL method to do the login and obtain the auth cookie. That would mean they need to make two calls now? One to get the token and then pass that somehow in their curl request?

Is there a way I can modify my login endpoint to grab the token for them and then complete the login if it isn't present?

We have two login points, one for the browser and another for the curl endpoints.

I've tested the browser one with the latest version and it works as you said.

FroMage commented 11 months ago

The problem is that the minute you serve HTML and have forms, you want CSRF protection. But this is not convenient for REST users. But, whatever endpoint you make available in your application will be callable via the browser via injection if you're out of luck.

If your scripts can make two calls, they can obtain a CSRF token using the method I posted above. Or perhaps you may want to support another form of authentication for your script calls? What login method do you use ATM to obtain an auth cookie?

tmulle commented 11 months ago

This application is a legacy application that was written in Scala/Play 2.x. It used the built in authentication mechanism in Play security.

I converted the application to use Renarde and Renarde Security with JDBC authentication since they were storing their user information and passwords in the database.

FroMage commented 11 months ago

With this, you mean? https://quarkus.io/guides/security-jdbc

tmulle commented 11 months ago

Well, unfortunately no, they are doing their own lookups in a few tables to get the id and then find the password (hash) in another table and then use BCrypt to compare the incoming passwords with the one stored in the database.

Then if found, they return the User object, otherwise throw error.

For example, they hit the /ws/login endpoint with FORM data and then have a securityService which then performs all the database lookups.

Ideally, I would've used what you mentioned but the code I'm working with is many years old and not well laid out so I couldn't touch a lot.

Even better, I would use Keycloak and OIDC but that is a big upgrade for them and no time at the moment.

FroMage commented 11 months ago

OK, so are you using this? https://docs.quarkiverse.io/quarkus-renarde/dev/security.html#custom_authentication_with_jwt

tmulle commented 11 months ago

Yes that it.

FroMage commented 11 months ago

For scripts, there are two alternatives, IMO:

I tried to find how to enable basic auth in Renarde and it appears I must do something to support it. Would it make your clients easier or are you more interested in option 1?