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

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

Open
tmulle opened this issue Oct 2, 2023 · 11 comments
Open

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

tmulle opened this issue Oct 2, 2023 · 11 comments

Comments

@tmulle
Copy link

tmulle commented Oct 2, 2023

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 protected]&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
Copy link
Contributor

FroMage commented Oct 11, 2023

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
Copy link
Author

tmulle commented Oct 15, 2023

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
Copy link
Contributor

FroMage commented Oct 17, 2023

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
Copy link
Author

tmulle commented Oct 17, 2023

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
Copy link
Contributor

FroMage commented Oct 17, 2023

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
Copy link
Author

tmulle commented Oct 17, 2023

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
Copy link
Contributor

FroMage commented Oct 17, 2023

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

@tmulle
Copy link
Author

tmulle commented Oct 17, 2023

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
Copy link
Contributor

FroMage commented Oct 18, 2023

@tmulle
Copy link
Author

tmulle commented Oct 18, 2023

Yes that it.

@FroMage
Copy link
Contributor

FroMage commented Oct 20, 2023

For scripts, there are two alternatives, IMO:

  • you can generate a JWT token on the script's end, given that you have access to the server's private key, there's probably CLI tools for that
  • you could use basic auth instead of relying on the login+obtaining the JWT cookie

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?

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

2 participants