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

Bug: No support for expired sessions #172

Closed
4 tasks done
Thinkscape opened this issue May 27, 2024 · 9 comments
Closed
4 tasks done

Bug: No support for expired sessions #172

Thinkscape opened this issue May 27, 2024 · 9 comments
Assignees
Labels
bug Something isn't working

Comments

@Thinkscape
Copy link

Prerequisites

Describe the issue

The issue

Neither AuthProvider nor KindeBrowserClient respect the token expiry times and don't handle expired sessions and re-authentication. There is no mention of expiration handling anywhere in docs. Nothing in source code.

After the token expires, if the app is still open and tries to fetch data (as most RIA apps do) everything will start failing - i.e. with 405 as described in #171 or plain 403 401.

Expected

All other auth sdks I know provide implicit or explicit expiration handling - usually by checking the exp claim and making sure that before it expires (with some buffer), token is regenerated or redirection happens to auth page/route to prevent errors.

Library URL

https://github.com/kinde-oss/kinde-auth-nextjs

Library version

2.2.10

Operating system(s)

macOS

Operating system version(s)

23E224

Further environment details

No response

Reproducible test case URL

No response

Additional information

No response

@Thinkscape Thinkscape added the bug Something isn't working label May 27, 2024
@Thinkscape
Copy link
Author

Thinkscape commented May 27, 2024

Here's a snippet from my custom TS implementation of the AuthProvider that supports token refresh:

// Auto-refresh token before it expires
  useEffect(() => {
    let timeoutId: Timer;

    const scheduleTokenRefresh = () => {
      if (state.accessToken) {
        try {
          const expClaim = state.getClaim("exp", "access_token");
          if (expClaim && typeof expClaim.value === "number") {
            const currentTime = Math.floor(Date.now() / 1000);
            const timeToExpiry = expClaim.value - currentTime;

            // Refresh the token 60 seconds before it actually expires
            if (timeToExpiry > 60) {
              timeoutId = setTimeout(
                // eslint-disable-next-line @typescript-eslint/no-misused-promises
                async () => {
                  await checkSession();
                },
                (timeToExpiry - 60) * 1000,
              );
            }
          }
        } catch (error) {
          console.error("Error fetching exp claim:", error);
        }
      }
    };

    void scheduleTokenRefresh();

    return () => {
      timeoutId && clearTimeout(timeoutId);
    };
  }, [state.accessToken, state.getClaim, checkSession, state]);

Note: checkSession() is a fixed and cleaned up TS version of https://github.com/kinde-oss/kinde-auth-nextjs/blob/main/src/frontend/AuthProvider.jsx#L61

@Thinkscape
Copy link
Author

Here's a TS implementation of tokenFetcher() with support for redirecting the browser session to login page in case auth has expired while the page is still open:

const tokenFetcher = async (
  url: string,
  router: ReturnType<typeof useRouter>,
): Promise<KindeSetupResponse | undefined> => {
  let response;
  try {
    response = await fetch(url);
  } catch (e) {
    throw new Error("AuthProvider: Failed to fetch auth data", {
      cause: e as Error,
    });
  }

  if (response.ok) {
    return await response.json();
  } else {
    if (response.status === 401) {
      const loginUrl = response.headers.get("location") || LOGIN_PAGE;
      logger.debug(
        "AuthProvider: Auth token expired, redirecting to login page",
        { location: loginUrl },
      );
      router.push(loginUrl);
    } else {
      logger.error(
        "AuthProvider: Unknown error while trying to obtain auth data",
        {
          response: {
            status: response.status,
            statusText: response.statusText,
          },
        },
      );
    }
  }
};

@tak0m0
Copy link

tak0m0 commented Jul 3, 2024

I having the same problem. I think that problem is very serious, is there any progress??😢

@peterphanouvong
Copy link
Collaborator

Extremely sorry for letting this one slip through - I'll be better at addressing these issues.
I'm assuming this is for Pages router?

I'll prioritise this!

@tak0m0
Copy link

tak0m0 commented Aug 7, 2024

Thank you! I think this problem is also happen in app router.

@peterphanouvong
Copy link
Collaborator

Hey @tak0m0 would you be able to share any extra details or code snippets to help me reproduce this error in the App Router w/ useKindeBrowserClient

@tak0m0
Copy link

tak0m0 commented Aug 8, 2024

I’m using “useKindeBrowserClient” in the header and user menu, but it doesn’t handle expired sessions and re-authentication. It often returns a 401 error. Many authentication libraries try to authenticate again with a refresh token even if the main token has expired, but this does not appear to be possible with this library.
I set a 1,296,000 seconds refresh token expiry but realized that it expires earlier than that time.
image

@peterphanouvong
Copy link
Collaborator

Hey guys, I made a release 2.3.7-beta.20 which should fix the problems. It's still in beta because it needs some testing.

@peterphanouvong
Copy link
Collaborator

I will close this for now, if there are any other issues I can re-open :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

3 participants