Google Identity Service (GIS) and id_token - google-oauth

I'm using the new Google Identity Services to login a user to my web app, calling google.accounts.id.initialize().
I then send that id_token as credentials to the server on every request, which uses OAuth2Client.verifyIdToken() to verify the user's identity.
However, that id_token eventually expires and I'm not sure how to refresh the token on the client. Is that possible?

Rather than sending the ID token to the server on every request, I would suggest you send the ID token to your server only once (which is the first time you have tried to authenticate the particular user).
The first time you send the ID token to your server, use it to validate the ID token and then issue a JWT token back to your client. Your client can send this JWT to your server anytime authentication or authorization is required. That way, you can control when it expires and how to refresh it when it does.
This might be the best way to go about it because I'm not sure google returns a refresh token for regenerating an ID token and you also cannot control when the ID token expires.

Related

Cookie-based JWT token refresh: is a separate call to the `/refresh` API endpoint really necessary?

I'm using .NET 6 with HttpOnly cookie-based JWT authentication in my WebAPI, and I'm now implementing token refresh.
I store the JWT and a Refresh Token in cookies, e.g.:
X-Access-Token: eyJhbGciO...
X-Refresh-Token: d8085ec8-d0bc-4e5c-b6b6-cd76146c419f
Most flows I've found for token refresh look like this, with the client calling the /refresh endpoint to get a new JWT:
client sends request to server
server rejects request with a 401 Unauthorized
client requests new JWT (expired JWT and Refresh Token automatically sent to server in cookie)
server validates cookie Refresh Token, generates new JWT and Refresh Token, assigns to cookies
client sends original request to server, with the new JWT and Refresh Token in the cookie
My question is:
When the initial request with the expired JWT is received by the server, since the server already has the refresh token (sent in the X-Refresh-Token cookie), can't the server issue a new JWT and Refresh Token at that time and successfully complete the request? This completely eliminates the need for a separate request and response to refresh the tokens. This is the flow:
client sends request to server
JWT is expired, but Refresh Token is valid
server creates new JWT and Refresh Token, assigns to cookies
server successfully completes the request
Is there a vulnerability or security risk implementing the refresh this way? I cannot think of one, but I could not find any examples with this flow.
Thanks!
Why are you using JWT access tokens? If the server could respond with an updated access token by looking at the refresh token, then why wouldn't the server just look at refresh tokens every time, and then the JWT access tokens aren't needed?
The point of using JWTs, and access tokens in general, is that it allows stateless authentication with services that have no access to the refresh token store. Usually, you will have an authentication service, it stores the refresh tokens, and calls to /refresh get routed to it, and it will validate the refresh token, and issue the access token. Then, calls to other services are able to validate the access token, without needing to make any calls on the authentication service. So, the reason why they don't just reply with a new access token when authentication fails is because those services are incapable of checking the refresh token, they don't have access to the refresh token store, only the authentication service does.
If however your application is one big monolith, where every endpoint is hosted by the same server and therefore is capable of checking refresh tokens and issuing access tokens, then there is absolutely no reason for you to be using access tokens or JWTs in general. You should just use refresh tokens, which, in this case, would be better called a session token.

Should access tokens be refreshed automatically or manually?

In the last few days I've been reading on Authentication with refresh and access tokens, but this is one thing I can't find the answer to. Let's say an expired access token is sent. Should the backend automatically refresh it (if a refresh token was provided), or the refreshing should only be done at a refresh endpoint?
As an example, consider the two following auth flows:
Automatically Refreshing
User authenticates with username and password. The API sends back a short lived access token containing his data, and a long lived refresh token.
For every request that requires authentication/authorization, the user will send both tokens on the request headers.
If the access token is expired, the API will check if a valid refresh token was sent, if it is active and if it belongs to the same user as the access token. If everything looks good then it will sign a new access token and update the response headers with it.
Front-end doesn't have to worry about refreshing the token, but it still has to look up response headers after each request to check if a new token was sent.
Manually Refreshing
User authenticates with username and password. The API sends back a short lived access token containing his data, and a long lived refresh token.
For every request that requires authentication/authorization, the user will send his access token.
When the access token expires, the user will send his refresh token to the refresh/ route. The API checks if the token is valid. If everything looks good, it returns a new access token.
After every request, the client has to check if the token expired, and if it did it will have to perform a new request to refresh the token. More requests are being made to the server, but on the other hand responsibilities are better separated, since auth route is only responsible for handling access tokens, while the refresh token handling lives in another route.
I've had some hard time finding resources on the subject, so I'm not quite about sure which solution is better, or even if the solutions I described are correct at all. If I had to pick one, I would go with Automatically Refreshing, since less requests are made, and the client side usability looks better, but as I said, I'm not 100% on this, and thus I'm making that thread.
How should access tokens be refreshed?
It feels to me that you are missing a role here, which is that of the Authorization Server (AS):
UI redirects to AS to authenticate the user via password
AS issues an access token and refresh token, then returns them to the UI
UI calls the API for a while with the access token
Eventually the access token expires and the API returns a 401 response
The UI then calls the AS with the refresh the token to get a new access token
The UI then retries the API call with the new access token
Eventually the refresh token expires and the refresh attempt will fail
The UI then redirects the user to sign in again and the cycle repeats
It is always the client's responsibility to refresh tokens and only the access token should be sent to the API. The API's only OAuth job is verify the access token and authorize based on its contents.
It is possible that you have an API that is doing the job of the Authorization Server. I would aim to separate these roles. If it helps my Messages Blog Post has a lot of detail on the messages in a full UI and API solution.
The implementations of the OAuth2-protocol I know use the flow you are describing under "Manual Refreshing". The client has to care himself about the refreshing.
The client can either check the access_token if it is still valid before every request or do a refresh after a failed request due to an invalid token response.
The access_token is short lived and so the risk sending it with every request and having it eavesdropped and misused is limited. The refresh_token is long lived. If you send the refresh_token with every request an attacker has a much greater chance to get hold of it.
If you send both token with every request you would not need the distinction between these two types. You would work with one long lived token only.
Following is the Main Disadvantage of using Automatic Refresh Token Rotation Scheme :-
Let's say the Client makes 2 API calls (API A and API B) at the same time. At the time of triggering these two API calls, the access token was expired. Both of these API calls are carrying the same expired access token and the refresh token (let's assume this refresh token is valid).
Let's assume API A gets handled by the server first. According to the Automatically Refreshing Scheme, the server will check the API A's access token, if that token is expired, server will check the refresh token and if that refresh token is verified (this refresh token is present in the database too), the server will create a new access token and a new refresh token (the refresh token that came with the API will be deleted from the database and will be updated with this new refresh token). These new tokens will be returned to the Client.
API B will follow the same flow. BUT its Refresh Token will be invalid because during the handling of API A, the refresh token was replaced in the database by a new token. API B's Refresh Token is not present in the Database and thus this request will fail.
If you have multiple APIs being called at the same time, Automatic Refresh Token Rotation Scheme will fail as the First API request will replace the Refresh Token when renewing the tokens and the remaining API requests will be coming with a Refresh Token which is not present in the Database !
My experience has been that the OAuth2 access_token requests dont like extra data meaning that you wont be able to send both the access_token and the refresh_token. That would lead to the Manual Refreshing scenario youve described as the only option

Why don't APIs use access token instead of refresh token?

I've already seen
Why Does OAuth v2 Have Both Access and Refresh Tokens?
https://auth0.com/blog/refresh-tokens-what-are-they-and-when-to-use-them/
As per my understanding, this is how OAuth v2 works:
1) user sends his credentials to the server which validates it and returns an access_token and a refresh_token
2) user sends this acsess_token along with further requests to identify himself
3) when the access_token expires, the user sends another request to the server with refresh_token and other required parameters asking for a new access_token and refresh_token
Here's my question:
What's the need of a separate refresh_token ? Why not send the old access_token ( which is about to be expired anyway ), for a new one ??
What's the additional advantage of using a refresh_token ?
The access token is, in theory, more in play. It could be in a browser, on the server-side of a client, on the authorization server or on a resource server. The access token will be attached to every API request whereas the refresh token should be used much less frequently.
A couple quotations from the web...
Unlike access tokens, refresh tokens are intended for use only with authorization servers and are never sent to resource servers.
https://www.rfc-editor.org/rfc/rfc6749#section-10.4
[Refresh tokens] are usually subject to strict storage requirements to ensure they are not leaked.
https://auth0.com/learn/refresh-tokens/
Basically, if we only had access token, the attack surface would be greater.

Is this JWT based authentication method safe?

Trying to implement a secure authentication method with JWT for an API which will be consumed for many clients including web (Single Page App), desktop, mobile I've came up with this system:
Client calls /auth/login with username and password set
After verifying server returns two tokens an auth_token and a refresh_token
Auth token is short lived 15 minutes and is used on every following API call
Refresh token is long lived maybe a 12 hrs to a week BUT is signed with a secret key in the format user_pass + long_string
After the token expires a called to /auth/renew is called
The auth token is sent to check how long it's expired (no longer than an hour)
The refresh token is sent as well and is validated using the user's password
If refresh token isn't expired and the auth token isn't expired for a long time, a new auth token is sent back
If the user's password has changed, the refresh token is invalid and the user is required to re-authenticate after their existing short lived auth token has expired
While there is a small window for the auth token to be expired and still be valid, and there is calls to the database made; is this an overall secure way to authenticate using JWT and to handle password changes and token refresh?
Don't try to implement your own authentication infrastructure. Chances you'll get a secure implementation are minimal and now you'll have to maintain all that code also.
Better use a authorization server from a reputable origin, like Thinktecture IdentityServer or Azure Active Directory and use standard libraries and protocols.
Some problems I see with your proposal:
if you do not sign the access token, what prevents me from changing
the claims inside?
if you need the user's password to validate the refresh token, you must store it in a way that you can retrieve it in clear text. Passwords should only be stored as a salted hash preventing you from getting to the clear text.

Custom (Non-OAuth) Refresh Token Implementation

I'm working on an application that uses a token-based authentication system, where the user provides their username / password and receives a token in return (the token gets saved to the database as well). Then subsequent requests will include this token as a custom header and we can use this to identify the user. This all works fine.
Right now if the user doesn't login for 3 days, we expire the token. I was reading a little about refresh tokens in OAuth and I was wondering if I could somehow implement something similar. i.e. when providing the auth token, I also provide a refresh token which can be used later to request a new auth token. In terms of security though, it seems quite similar to just never expiring the user's auth token in the first place. Should I be sending additional information with the refresh token to validate the user?
In OAuth2, the resource server and authorization server are often not the same.
The refresh token is sent back to the client when the access token is issued and when the token is refreshed. The client needs to authenticate itself (using client id and client secret) to use the refresh token. The resource server never sees the refresh token.
Also, access tokens are not stored at the server side as they have a limited lifetime. Refresh tokens are stored and can therefore be revoked.