I have a Keycloak Gatekeeper proxy (https://localhost:8080) in front of my application (http://localhost:8081) to offload OAuth2. It connects against a Keycloak server (https://keycloak.my.company). Login and accessing the app through Gatekeeper works fine.
Now I have an AJAX snippet that is executed every 10s to reload certain content. This works only until the JWT life time is exceeded. Then Gatekeeper sends a redirect to Keycloak (as it's supposed to do) but the AJAX request can't follow it due to a CORS error.
The requests look like this:
OPTIONS https://keycloak.my.company/auth/realms/demo/protocol/openid-connect/auth
? client_id=demo-app-spring
& redirect_uri=http%3A%2F%2Flocalhost%3A8080%2Foauth%2Fcallback
& response_type=code
& scope=openid+email+profile
& state=33a3da4d-1c83-4363-857c-511b26706649
Host: keycloak.my.company
User-Agent: ...
Accept: */*
Accept-Language: ...
Accept-Encoding: gzip, deflate, br
Access-Control-Request-Method: GET
Access-Control-Request-Headers: x-requested-with
Origin: http://localhost:8080
DNT: 1
Connection: keep-alive
The response is:
HTTP/1.1 200 OK
Content-Length: 93
Content-Type: application/json
Date: Mon, 20 Jan 2020 14:20:33 GMT
Set-Cookie: _0bc78=http://172.26.12.34:8080; Path=/
Vary: Accept-Encoding
Firefox tells me:
Quellübergreifende (Cross-Origin) Anfrage blockiert: Die Gleiche-Quelle-Regel verbietet das Lesen der externen Ressource auf https://keycloak.my.company/auth/realms/demo/p…nid+email+profile&state=c758c30a-1c1c-46f7-9155-f71b906ac61a. (Grund: CORS-Kopfzeile 'Access-Control-Allow-Origin' fehlt).
(translated: Blocked as Same-Origin-Policy forbids reading the resource. Reason CORS header 'Access-Control-Allow-Origin' is missing)
Questions that come to my mind:
- Why doesn't count the Redirect as "CORS simple request", because of the X-Requested-With header?
- Why doesn't Keycloak answer the CORS request? It has "+" as CORS Origin and the "https://localhost:8080/*" as Valid Redirect URL
- Is this the correct way to refresh a token after all? Or does the standard mandate that the client (Javascript) checks the Time To Live and refreshes the JWT before it does the actual request?
Thanks in advance for any hints!
Edit: The configuration:
verbose: true
listen: :8080
redirection-url: https://localhost:8080
tls-cert: local/localhost.crt
tls-private-key: local/localhost.key
upstream-url: http://localhost:8081/
skip-upstream-tls-verify: true
client-id: demo-app-spring
client-secret: xxx
discovery-url: https://keycloak.my.company/auth/realms/internal
secure-cookie: true
enable-logging: true
enable-refresh-tokens: true
encryption-key: xxx
store-url: redis://localhost:6379/
enable-default-deny: true
resources:
- uri: /
white-listed: true
...
enable-cors: true
cors-origins:
- 'https://localhost:8080'
...
cors-methods:
- GET
- POST
- OPTIONS
- DELETE
- PUT
cors-headers:
- authorization
- content-type
- Cookie
- authorization
- content-type
- accept
- x-requested-with
- origin
- referer
My first attempts were without redis. With Redis I now run into the very issues described in https://issues.redhat.com/browse/KEYCLOAK-11077