Pass jwt refresh token on header or body - jwt

When access token is expired, it should re-issued refresh token.
At this point, I'm little hesitate which method is better.
For access token, it passed HTTP header per every request.
pass refresh token on HTTP header.
pass refresh token on HTTP POST body(payload).
Which one is recommended?

The jwt specification recommends (but does not require) sending the access tokens in an authorization header of type Bearer. But there is no mention of the refresh tokens.
Refresh tokens are an Oauth2 concept. If you read the Rfc6749 specification, to refresh an access token, the refresh token is sent using a form parameter in a POST request
6. Refreshing an Access Token
...
POST /token HTTP/1.1
Host: server.example.com
Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW
Content-Type: application/x-www-form-urlencoded
grant_type=refresh_token&refresh_token=tGzv3JOkF0XG5Qx2TlKWIA
You can use the example of oauth2 as reference (pass it in the body), although if you do not use oauth2, you have no obligation, so use the method to send that best suits your project.

Related

how do I return a Bearer Token supplied by my server

I'm using Vapor to handle http requests. I've implemented a registration and login, as well as other functioning code. On registration, a Bearer Token is generated, so I can return that to or write it into the page I'm about to render.
The page contains two forms, one of which generates a request that requires authorization, so I need to associate that request with the bearer token. How do I do this? Through explicitly setting headers for the form request that will be sent to the server? Via a cookie?
If you're writing a traditional web app using HTML then bearer authentication is not suitable as you can't attach custom headers with requests. You should use session based authentication as described in the docs

How to make an axios request with JWT?

Hello I'm trying to figure out how to use JWT and axios. I was wondering if you could explain me what's the point to add "bearer" and if I should use "Authorization" or "x-access-token" name please ?
Axios.get(`http://localhost:3001/posts`, {
headers: { 'Authorization': `bearer ${token}` }
}).then((response) => {
console.log(response)
});
If I need to explain JWT Token in pretty simple words then I'll say something like this:
Access tokens are used in token-based authentication to allow access to an API. Access tokens are received after users successfully authenticate and authorize themselves.
And about the Authorization Token:
To set the authorization header, call it like this:
headers: { 'Authorization': `bearer ${token}`
Now the bearer token basically refers to the token type which in this case is a bearer type, read more here
The abstract of the provided link is something like this:
This specification describes how to use bearer tokens in HTTP
requests to access OAuth 2.0 protected resources. Any party in
possession of a bearer token (a "bearer") can use it to get access to
the associated resources (without demonstrating possession of a
cryptographic key). To prevent misuse, bearer tokens need to be
protected from disclosure in storage and in transport.
Now let's get to the Authorization vs x-access-token
Authorization:
The HTTP Authorization request header contains the credentials to authenticate a user agent with a server, usually, but not necessarily, after the server has responded with a 401 Unauthorized status and the WWW-Authenticate header.
Read more about Authorization here
X-Access-Token:
In case of 'x-auth-token' user has to supply username/password for the first time and server returns a access-token in header field 'x-auth-token'. For further sessions this token is exchanged, not the username/password.
Now the conclusion. You'll use whatever your project really requires example if your working on an application which has a lot of users might use you'll have to implement as much security as possible which means using JWT Token and other security steps.
On the other hand if your application only requires one admin login to input some data and you have a pretty small window then you might want to go with session based login.

Is it bad to have access token in OAuth redirect URL

I am building an oauth login flow and I am not sure if I have done it wrong because I will need to send the bearer token back via redirect URL, like /oauth2/redirect?token=[TOKEN]. But isn't it not recommended to have token passed along through URL? As it is pointed out in this thread:
Don't pass bearer tokens in page URLs: Bearer tokens SHOULD NOT be passed in page URLs (for example, as query string parameters).Instead, bearer tokens SHOULD be passed in HTTP message headers or message bodies for which confidentiality measures are taken. Browsers, web servers, and other software may not adequately secure URLs in the browser history, web server logs, and other data structures. If bearer tokens are passed in page URLs, attackers might be able to steal them from the history data, logs, or other unsecured locations.
I must have missed something in the whole flow and would like to understand more about this matter. Any input is appreciated!
UPDATE
Might not be correct but this is my understanding after some digging. The three means to pass token:
URL (not preferable)
Auth header
Request body
But under the oauth redirect use case, option 2 and 3 not feasible. So option 1 is the only option available. If really needed, token can be encrypted to ensure security.
I think this only means, that you should not use a GET request when the server requires the token, instead you should use POST or whatever is appropriate. In a GET request the parameters are included in the URL and those can end up in logs or other histories, other request types will send the paramters separat from the request URL.
P.S. BTW if you are not implementing the OAuth server yourself, you won't have to send a redirect url containing the token.
The basic auth header which provides a little extra security as it's required to be through TLS:
In the case of a "Basic" authentication like shown in the figure, the exchange must happen over an HTTPS (TLS) connection to be secure.
https://developer.mozilla.org/en-US/docs/Web/HTTP/Authentication
Also, the headers aren't logged in easy places like browser history.
From the spec,
it SHOULD NOT be used
unless it is impossible to transport the access token in the
"Authorization" request header field or the HTTP request entity-body.
https://www.rfc-editor.org/rfc/rfc6750#section-2.3

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 and CSRF differences

I've been reading about JWT, and from what I understand, it's a token that the server sends after a user logs in. The user will have to send that token with all future HTTP requests. This creates a stateless way for the server to verify a user's request.
Now what I don't understand is that if the JWT is sent in the header and marked as HTTP only, why is a CSRF token also needed for prevention of CSRF attacks? My understanding is that both JWT and CSRF tokens are tied to a user, and that a JWT would serve both purposes.
I understand that CSRF tokens are used so HTTP requests from other sites won't be accepted. How does a JWT not accomplish that? What separates a CSRF token from a JWT token, and allows it to accomplish that difference?
I've been reading articles on JWT's and CSRF tokens as well as the double submit method, but there is just something I can't seem to understand or I'm missing.
An authentication system based on tokens (JWT or random) stored in cookies is vulnerable to CSRF attacks, because cookies are sent automatically to server in each request and an attacker could build a harmful url link to your site.
https://yoursite.com/delete?something=1
To protect your site it is needed to use a CSRF token that your application must send in the following request (not in a cookie).
Alternatively you could store the JWT in localStorage and send it in a Authorization header, then your site is protected against CSRF, but it could be vulnerable to XSS attacks. Take in account always the security considerations of the technical solution you choose
Update ¿why storing JWT in localstorage could be vulnerable to XSS attacks?
See this comparison between storing tokens in localstorage and http-only cookies https://academind.com/tutorials/localstorage-vs-cookies-xss
An attacker could inject javascript code to read the token from the localstorage and send it to his own server. However, this type of attack is not possible with an http-only cookie because it is not accessible from javascript
All your questions are relative to the fact that a CSRF token in NEVER included in a cookie and that a JWT token MAY be sent in a cookie.
A JWT token can be sent:
1- in a cookie
2- in another type of header
3- outside the headers, in some POST attribute
4- outside the headers, in some GET parameter (not very common)
But for stateless authentication, you MUST use cookie (case 1).
So, for stateless authentication, you are prone to CSRF, with your JWT token. This is why you need to add some CSRF mitigation mechanism, based on some more information not included in a cookie, or not only included in a cookie.
All of this would not apply if you were accepting to implement a stateful authentication.