Can we set HttpOnly flag to KEYCLOAK_SESSION cookie? - keycloak

Why does the KEYCLOAK_SESSION cookie in Keycloak does not have HttpOnly flag set in first place as against other cookies?

As #besverino mentions in his comment, KeyCloak doesn't allow set KEYCLOAK_SESSION HttpOnly flag because KeyCloak needs to access the cookie from iFrame. Comment on this part of KeyCloak code is:
THIS SHOULD NOT BE A HTTPONLY COOKIE! It is used for OpenID Connect Iframe Session support!
References:
https://github.com/keycloak/keycloak/blob/16.1.1/services/src/main/java/org/keycloak/services/managers/AuthenticationManager.java#L751
https://lists.jboss.org/pipermail/keycloak-user/2017-September/011882.html

Related

JWT - Is saving the refresh token a cookie dangerous?

I've been reading about it for a few days and I have two questions
1) If I store the access token in localstorage and the refresh token in an HttpOnly cookie, do I have to worry about XSRF? If the attacker cheats to make a request, the response is received by the good user. It is not bad that it requests a new acces token and a refresh token, the attacker cannot steal the content of the response. This is true ?
If the attack is XSS it can make the same attacks as if it also stored the access token as an HttpOnly cookie ... which is bad. But if you stored the refresh token in localstorage it would be very bad and you could update the access token.
With this approach I should not worry about XSRF, but if I store the 2 tokens in HttpOnly cookie I have to worry about XSRF (about the token to avoid XSRF) and XSS. And if they make a successful attack, they can only do evil the lifetime of the access token.
2) If my authorization server is a micro service and I access through an internal IP (10.x.x.x) I have to continue worrying about XSS but not XSRF, is this true?
Have you considered saving both the refresh-token and the access-token (or id-token) to secure, httponly cookies? I do this and it works great. I also sign my cookies, and double xor them.
In your middleware function, you can check the validity of your access-token. If the access-token is valid, permit the access of the resource.
If the access-token has expired, check the refresh-token for validity (as it may be expired). If it's still valid, issue a new access-token via a cookie and permit the user access to the resource.
If the refresh-token is also expired, the user has to re-login.
I think this area is often misunderstood, and generally I recommend:
Being very careful about risks, first and foremost
Once done, store access tokens in browser memory
Refresh tokens in cookies give you better overall options
A couple of relevant blog posts of mine:
Web Architecture Goals
Browser Token Security
Interested in feedback also ..

Does the Domain attribute affect SameSite on an http cookie?

Will a CORS request set/send a cookie with SameSite=Strict if the cookie's domain attribute is set to the client's domain?
For example, if I make a request from cors.com to cors-api.com, will this configuration allow my cookie to be set and sent?
Set-Cookie: MY_KEY=<MY_VALUE>; Secure; HttpOnly; Domain=cors.com; SameSite=Strict;
No, you cannot set a Domain value that does not match the site setting the cookie - the browser should reject this.
https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie#Invalid_domains
The Domain is used to control if the cookie will be sent for subdomains of the originating site.
https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies#Scope_of_cookies
If you need cookies to be sent in a cross-site context, they must be set with SameSite=None; Secure.

Keycloak - Retrieve JWT token via OIDC Endpoint

I'm currently trying to retrieve a user token from the keycloak token endpoint using a POST request (instead of using one of the designated adapters). I have set up a keycloak realm and added my own machine as a client. In the documentation the Token Endpoint is described as:
/realms/{realm-name}/protocol/openid-connect/token
As far as I have read in the openid specification, I will need to set the body parameter grant_type=authorization_code as well as the parameters code and redirect_uri. I will also need to set the Authorization header, for which I will need a Basic Token.
So far I will get the response:
"error": "unauthorized_client", "error_description":
"INVALID_CREDENTIALS: Invalid client credentials"
Where do I get the Basic Authorization Token from? I expected that I need to provide a username and a password, since the JWT token is what I'm trying to recieve as response. Do I need to set the redirect_url if I just want to request a token?
Keycloak offers more than one way to retrieve a user access token, following the OpenId Connect spec. Here you have the steps to do it for Authorization code flow (the one recommended for web applications) according to the openid connect spec: https://rograce.github.io/openid-connect-documentation/explore_auth_code_flow
Basically, if you're not using any adapter, when detecting a request to some protected resource you should:
Perform a redirection to the keycloak login page (keep in mind keycloak uses the REALM entity, so you'll need to specify it too):
HTTP/1.1 302 Found
Location: https://mykeycloakinstance.org/auth/realms/demo/protocol/openid-connect/auth?
response_type=code
&scope=openid
&client_id=s6BhdRkqt3
&state=af0ifjsldkj
&redirect_uri=https%3A%2F%2Fclient.example.org%2Fcb
You'll need to keep the state value in the client, as it needs to survive the redirection process:
It is recommended that client’s use this parameter to maintain state
between the request and the callback. Typically, Cross-Site Request
Forgery (CSRF, XSRF) mitigation is done by cryptographically binding
the value of this parameter with a browser cookie.
You don't interact with username/passwords. The keycloak authentication page does. Once the login is successful, it will redirect to your page with a valid code:
HTTP/1.1 302 Found
Location: https://client.example.org/cb?
code=SplxlOBeZQQYbYS6WxSbIA
&state=af0ifjsldkj
Here you'll need to either check that the state is the one you originally sent (you may need to track it through web session, using cookies) and also to obtain the token using that code. You do a POST to the authorization endpoint with this code:
POST /auth/realms/demo/protocol/openid-connect/auth HTTP/1.1
Host: https://mykeycloakinstance.org
Content-Type: application/x-www-form-urlencoded
Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW
grant_type=authorization_code&code=SplxlOBeZQQYbYS6WxSbIA
&redirect_uri=https%3A%2F%2Fclient.example.org%2Fcb
This is the flow in summary, I haven't tested the code myself, so use it as an example and don't hesitate to fix it if you consider ;-)
See also:
What are Keycloak's OAuth2 / OpenID Connect endpoints?

JWT stored in cookie - security concerns

I'm building SPA app with server side rendering, using JWT-based authentication.
Current implementation is:
JWT token is issued and transferred to client after successful username and password verification
token is then stored in cookie (not HttpOnly) - the purpose of that is to avoid the need to login again after full refresh or closing page
logging out deleted cookie with token
Authorization header is attached to every API request if token exists
full SSL traffic
I can't store token in LocalStorage because of server side rendering, also the there is no HttpOnly because I need to access cookie in order to construct Authorization header.
What are the possibilities of stealing the token in such architecture?
One major risk is that any single cross-site scripting vulnerability in your application could be used to steal the token from the cookie, because it's not httpOnly (while I understand why that is the case). XSS in a javascript-heavy application like an SPA is very common and hard to avoid.
Also you're saying the token is kept in the cookie so that after closing the browser, the user is still logged in. On the one hand, that's bad practice, a user closing the browser probably expects being logged out. On the other hand, this means the cookie is persisted to disk, so it is much easier for an attacker to steal it from the client.
Another thing that comes to mind is cross-site request forgery (CSRF), but if I understand correctly, authentication is actually based on the Authorize header, where the token is copied in each request. If that's the case, CSRF is not an issue for you (but it would be, if sending the token in the cookie was enough).
So at the very least, I think you should
not use a persisted cookie for the token
try to minimize the chance of XSS (eg. by automatically scanning your code, but that will never be 100%, also by carefully choosing secure by default technologies)
make sure auhentication is based on the Authorize header and not the cookie
Still mainly because of the XSS risk, I would probably not recommend doing it this way in a security-critical application.

Set LTPA token in HTTP Request header

I want to invoke a REST service that is hosted on WAS.
I would like to know how to set the ltpa token in the HTTP Request header while invoking the service using SOAPUI.
Can I set the token in the Cookie field of the header?
If so, what is the format ?
You must set this value in the cookie. My answer works on our WAS 8.5 servers. The cookie value must be:
LtpaToken2=<your token value goes here>
or
LtpaToken=<token here>
NOTE: you must have generated this token in the same realm as your server is running. If you have different realms, dev/test vs. production, your tokens don't work across these realms.
Be sure you have No Authentication selected in SOAPUI so you can validate that the token is working.