Skip to content
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

What happens when the access token expires #400

Open
mlmarius opened this issue Jul 16, 2021 · 9 comments
Open

What happens when the access token expires #400

mlmarius opened this issue Jul 16, 2021 · 9 comments

Comments

@mlmarius
Copy link

Hi!

Looking through the sources of the backend and frontend I can't figure out what happens when the JWT access token expires. Is there a strategy in place to extend the access token if the user is using it frequently?

@csmcallister
Copy link

When the access token expires, a user would need to login again, sending a request to the backend's /login/access-token route to get a new access token.

@emsi
Copy link

emsi commented Aug 8, 2021

@csmcallister: Where in the code it is actually enforced?

@csmcallister
Copy link

csmcallister commented Aug 8, 2021

@emsi Take a look here first:

https://github.com/tiangolo/full-stack-fastapi-postgresql/blob/490c554e23343eec0736b06e59b2108fdd057fdc/%7B%7Bcookiecutter.project_slug%7D%7D/backend/app/app/api/api_v1/endpoints/login.py#L36

Then follow the core.security import to here:

https://github.com/tiangolo/full-stack-fastapi-postgresql/blob/490c554e23343eec0736b06e59b2108fdd057fdc/%7B%7Bcookiecutter.project_slug%7D%7D/backend/app/app/core/security.py#L15

As you can see there, the expiration is either pulled in from the app settings or can be overridden with a custom value. The jwt library is responsible for taking in that expiration value. Their docs explain how expiration is determined and enforced: https://pyjwt.readthedocs.io/en/latest/usage.html

@maximiliancw
Copy link

@emsi stumbled upon this today. In addition to @csmcallister's hints, you can use the /login/test-token endpoint (or any other one for that matter) to check if you're current token is still working. It feels a bit hacky though...

@hollowdew
Copy link

Is there something planned to handle the expiration?
Like implement a refresh endpoint in the backend and call the endpoint in the frontend?

@danieldiamond
Copy link

Yeah I'm definitely experiencing and endless loop of 403 Forbidden requests to http://localhost/api/v1/users/me when attempting to access the dashboard with an expired access_token.

It seems that, it doesn't actually check if token is expired, only that it is present.

const isLoggedIn = () => {
return localStorage.getItem("access_token") !== null
}

@abrichr
Copy link

abrichr commented Aug 26, 2024

Same issue here. If the user leaves the browser window open for a while then comes back, the app appears to be broken, i.e. the backend returns 403, but the frontend doesn't report this to the user, only hangs.

Suggestions:

  1. Add a refresh token endpoint on the backend. The frontend should automatically request a new access token when the current one is about to expire or has expired, using the refresh token. This prevents 403 errors caused by expired tokens.

  2. If a 403 error is returned for any other reason, the frontend should gracefully handle it by providing a clear message to the user and/or redirecting them to the login page.

Edit: here's a patch for the frontend (untested):

diff --git a/frontend/src/client/core/request.ts b/frontend/src/client/core/request.ts
index 080a6f4..f5700d9 100644
--- a/frontend/src/client/core/request.ts
+++ b/frontend/src/client/core/request.ts
@@ -7,6 +7,8 @@ import type { ApiResult } from './ApiResult';
 import { CancelablePromise } from './CancelablePromise';
 import type { OnCancel } from './CancelablePromise';
 import type { OpenAPIConfig } from './OpenAPI';
+import useAuth from '../../hooks/useAuth';
+import useCustomToast from '../../hooks/useCustomToast';
 
 export const isString = (value: unknown): value is string => {
 	return typeof value === 'string';
@@ -197,7 +199,22 @@ export const sendRequest = async <T>(
 	}
 
 	try {
-		return await axiosClient.request(requestConfig);
+		const response = await axiosClient.request(requestConfig);
+
+		// Handle 403 Forbidden error
+		if (response.status === 403) {
+			const auth = useAuth();
+			const showToast = useCustomToast();
+
+			// Logout and notify the user
+			auth.logout();
+			showToast("Session expired", "Your session has expired. Please log in again.", "error");
+
+			// Stop further processing
+			return response;
+		}
+
+		return response;
 	} catch (error) {
 		const axiosError = error as AxiosError<T>;
 		if (axiosError.response) {

frontend.patch

@storenth
Copy link

Similar issue found in case of start-stop the backend, so ah the same behaviour take into a place when token will expire. Spinner goes into an endless loop.
Screenshot 2024-11-16 at 11 54 02

storenth added a commit to storenth/full-stack-fastapi-template that referenced this issue Nov 16, 2024
@storenth
Copy link

storenth commented Dec 8, 2024

After some experiments with expired/Signature verification failed exceptions, faced with issue that the project need refresh token mechanism as @hollowdew and @abrichr says above, I'm also will looking to see this stuff here guys, can anyone share some sketches?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

8 participants