-
Notifications
You must be signed in to change notification settings - Fork 2.7k
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
CORS Error when Keycloak Token Timesout #10185
Comments
@tomsontom Thanks. |
It feels like it is about tweaking the same origin browser policy somehow. |
@sberyozkin well why should the first request lead to a redirect? The user logs when one fetches the index.html site and hence the token is valid at that point. Now the page does not get reloaded for $x minutes and when issuing a request afterwards no cookie is sent with the request: Working GET-Call:
Failing GET-Call
Well failing is wrong - this call leads to 302-response with the location-header set. What I'm not sure about is keycloak is at fail or quarkus. So could it be that keycloak is the one responsible for the abortion because it gets a cross-domain request? Or maybe what I write is completely bogus because this is clearly not my area of expertise ;-) |
@tomsontom My assumption has been that the user logins with the very 1st GET to the hello endpoint... It will give us a clear view of what is different between the two cases. Sorry I'm not helping much at the moment as I'm coding something else right now :-), but we are very close :-) |
Ok so the initial fetch of index.html looks like this: General:
Response Headers:
Request Headers:
which leads to: General
Response Headers:
Request Headers:
Query String Parameters:
|
Now executing the log-in leads to:
Response Headers:
Request Headers:
Query String parameters:
Form Data:
followed by the following request sequence General
Response headers:
Request headers:
Query String Parameters:
followed by the following sequence: General
Response headers:
Request headers:
|
If i now rerequest the index.html after the timeout i get the following perfectly fine series of calls:
Response Headers:
Request Headers:
leading the following call sequence: General:
Response Headers:
Request Headers:
Query String parameters:
who then leads to the following call: General:
Response Headers:
Request Headers:
*Query String Parameters:
finally leading to: General:
Response Headers:
Request Headers:
This what I expect and because in that case to Cross-Domain-Request is issued using XHR this does not lead to any problem - the problem is only if the 302 is issued to a XHR request forcing it into calling another host. |
The very same call sequence is work if I enter
Response Headers:
Request Headers:
leading to:
Response Headers:
Request Headers:
Query String Parameters:
Leading to: General:
Response Headers:
Request Headers:
Query String Parameters:
finally leading to
Response Headers:
Request Headers:
|
Well now it gets interesting when I compare the response provided by keycloak by invoking "/hello" via the browser I see
When if that happens through an XHR it is:
|
Hi @tomsontom |
@tomsontom Example, mauriciovigolo/keycloak-angular#91, or search for |
we also tried with using "Access Type": Public but that did not change anything |
@pedroigor Hi Pedro, can you have a look please ? I'm pretty sure now that it is a Keycloak issue. Have a look at the image which @tomsontom attached in the issue description for a summary of the problem. |
Hi @tomsontom If you are not too tired with tracing it :-), can you please do one more trace with XHR on:
|
Not sure I can follow to provide the required information correctly let me rephrase to see if I got this right:
our do you want me to rewrite the app the fetch index.html via XHR or how should i initialize a XHR without loading some html/js code. Once I know exactly what you require I'm happy to help get this sorted, and documented for the future developers doing this stuff! |
@tomsontom sorry, never mind, I think I have a clear picture now of what is going on. |
so one more info: If I turn off CORS in Chrome then everything is working fine so it is definately a client problem |
@tomsontom Thanks. By the way, what Keycloak version do you use ? |
See https://github.com/tomsontom/keycloak-cors/#environments but locally i also gave 10.0.2 a try without any difference - if time permits in the evening i‘ll put a proxy infront of both and experiment what headers are missing |
So yesterday I hacked into quarkus and added the following headers:
But that did not change anything (I already suspected that) adding them to keycloak is a bit trickier so I have not yet done that. As we already suspected this looks like a keycloak problem because it does not send CORS-Headers required to make things work (although we clearly configured them). I hope I find the time today to hack the Keycloak-Codebase to add those headers to see if that makes a difference - I'd still like to keep this issue open for now |
Hi @tomsontom Right, CORS headers returned by Quarkus are only needed when the Quarkus resources are accessed (they will likely need to be setup anyway once Keycloak CORS issue is resolved since the user will be getting via XHR back to Quarkus). |
@tomsontom Can you do a quick try and set the Keycloak web-origin property to |
So well yesterday I had a looong night and hacked myself into the keycloak codebase and I'm not sure anymore this is a keycloak problem. The problem as it looks to me is that the request the browser is sending to the keycloak server has not all information and so keycloak in reality responds with the login-page (I can proof that by hacking CORS headers into the response from the endpoint). I instrumented the keycloak code base as bit and to make things work correctly keycloak exepects the request to contain KEYCLOAK_IDENTITY_LEGACY. .... cookies but those are not present in the failure case: Auth-Request WRONG:
I don't yet know why but if I turn of websecurity in my chrome the browser is sending the following request:
Notice the *_LEGACY-Cookies!?! upon who it responses with
Notice the Location-Header - so the question now is: Why is the browser not sending the *_LEGACY-Cookies if I turn on Websecurity. |
Well another interesting datapoint. Those cookies get set in the response to the login-from submission: Sending of form:
Response:
|
Ok the not sending of the cookie is because one has to turn that on explicitly - we are getting closer! |
I can imagine it must've taken some time :-) |
i can report success and I can now definately say it is a problem in keycloak. For completeness what had to be done:
I'm still investigating if there's anything one could pass to make keycloak include them but for the moment it looks like quarkus is doing every correct. |
@tomsontom This is a very thorough investigation, thanks.
Different port to
|
Well the origin you see is the login-form in keycloak hence the origin is correct!
|
@tomsontom |
so the keycloak post is https://keycloak.discourse.group/t/authorizationendpoint-does-not-support-cors/3495 |
@tomsontom sorry for kicking in so late, I've replied to that thread. It is not really a Quarkus issue, neither KC. But something you should handle in your frontend if you really want to stick with that deployment model. |
Hi @pedroigor thanks |
I think suggesting to fix this on the client-side is a none started. As a frontend application provider I'm not interested if the backend is written in Quarkus, Wildfly, SpringBoot, .net, ... nor am I interested if the backend is deployed in an environment who is protected by Keycloak, SpecialAuthService-X, SpecialAuthService-Y, ... - in an ideal world this is completely transparent to the client. As already said as long as you are in a single domain all is fine (as long as you know that you need to set the clientCredentials-flag) already today. |
@tomsontom But that is pretty much how OpenID Connect is supposed to work. You would need something like https://openid.net/specs/openid-connect-session-1_0.html to make that work. See the RP iframe part. In Keycloak, we have a JS adapter that already does that for you, however, the use cases involved are usually the frontend and backend as distinct applications. And your frontend as a client authenticating using some OpenID Provider. Your frontend does not need to be a Quarkus application at all to make this work. But only served by some web server. The authentication should be done by libraries like Keycloak JS Adapter. Even if you do your frontend served by a Quarkus application, you can just change it to be a "service" type application and use a library like that JS Adapter in your HTMLs. It won't involve As I said, we could support that on Quarkus by having some config option that could check whether or not the request is a XHR. if so, does not return a 302 but 401 or 403. But again, I'm not sure if this type of deployment is what we would recommend for people. For instance, most of our server-side adapters have support for this behavior but I remember our team not very happy about this capability as it may lead to a wrong design/usage. |
@sberyozkin Exactly, that is why I think a web-app like this one we are discussing is not really a valid usage. I think that for this case, we don't need |
@pedroigor What about the confidential client support though... With the JS adapter it is no longer a confidential client... |
I'm going to try to implement something on top of that application to show what I'm proposing. |
@sberyozkin @tomsontom Could you check https://github.com/pedroigor/keycloak-cors ? Basically, what I did was to:
Does it make sense? |
Btw, ideally, the frontend would be a distinct client (public). Where the backend would be a confidential one. I didn't do that to just showcase the changes to the frontend. |
I've also added support for token refresh in that example. So that when the token expires, the token is refreshed without forcing user to re-authenticate. |
Very cool but and I think it might make sense to provide samples of the different solutions (although you said the OpenID solution is nothing you are in favor I still think is a valid solution see below why) As I outlined already my main concern is that with the client-side solution this application can only be deployed in a keycloak environment, whereas the original frontend application is totally agnostic how and if it is secured by any technology from basic-auth to OpenID to ... . So as long as I can make sure i can serve all from one domain I'd always go for the initial OID approach because it is much more flexible. Unfortunately as you made very clear the multi-domain approach won't be supported by Keycloak so I think in the end we could provide 2 flavors:
|
BTW - I'd be very happy to provide a Guide to Quarkus - https://quarkus.io/guides/ once we aggreed in what should be presented/advertised. |
@tomsontom Good summary.
I do think it solves the problem. But the use case does not justify having that change, IMO. The main reason being that in the OpenID Connect world you already have the necessary means to solve the same problem. But this is opensource, let's see if we get more feedback in that discussion, mainly from others in the team.
I see your point. But once you have a decision to use OpenID you have a set of different authentication methods available. And you are not tied with Keycloak, but free to use with any JS library that does the same thing as our JS adapter.
If the flexibility you mean is in terms of security capabilities, I would say that any OID approach is more flexible. But if you really, really, want to have one domain as you started this thread, it should still be possible if we all agree that we could have a I'm not really in favor of adding this until we have more people trying to solve the same problem. But if @sberyozkin thinks this is an option, then I have no objection.
I would say that the Maybe the idea around that config property helps too? |
Hi @pedroigor, OK, how will this property help with the |
@sberyozkin It will help so that you don't need to change your app to I'm only proposing this approach because it is related to the requirement from @tomsontom where he would like to have all the authentication dance performed by the backend where the frontend will just propagate cookies without having to deal with bearer tokens. |
Hey Pedro, missed it too, yeah, lets go ahead with |
@tomsontom FYI, #10651 |
Describe the bug
If you enable OIDC Support with Keycloak calls to REST-APIs start to fail once the Token provided by Keycloak is timed out with an CORS-Failure like this:
Expected behavior
The timeout of the token should not lead to an error
Actual behavior
CORS Error produced
To Reproduce
Clone https://github.com/tomsontom/keycloak-cors/ and follow the steps there
Configuration
Screenshots
Environment (please complete the following information):
uname -a
orver
: Darwin Toms-MacBook-Pro.local 19.5.0 Darwin Kernel Version 19.5.0: Tue May 26 20:41:44 PDT 2020; root:xnu-6153.121.2~2/RELEASE_X86_64 x86_64java -version
: openjdk version "11.0.6" 2020-01-14mvnw --version
orgradlew --version
): 3.6.3Additional context
Working request/response look like this:
General:
Response Headers:
Request Headers:
Failing request/response look like this:
General:
Response Headers:
Request Headers:
General:
Response Headers:
Request Headers:
Query String Parameters:
The text was updated successfully, but these errors were encountered: