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

How to logout user if password was changed? #286

Open
Finalet opened this issue Nov 29, 2024 · 2 comments
Open

How to logout user if password was changed? #286

Finalet opened this issue Nov 29, 2024 · 2 comments
Assignees
Labels
question Further information is requested

Comments

@Finalet
Copy link

Finalet commented Nov 29, 2024

Prior to all, thank you for this library and extremely detailed answers you've been giving in other issues. My problem is similar to 282 and 136.

I am stuck at the user's password reset flow. After resetting the password, the credentials become invalid. The Starter Example crashes with these steps:

  1. Create account
  2. Reset password from a separate browser
  3. Click Refresh cookies w/ server action
  4. Crash

The crash is caused by refreshServerCookies which throws INVALID_CREDENTIAL.

One of the solutions is to set checkRevoked: true, but we need figure out when exactly to do that, since keeping it true forever is not optimal. Even if I do that, until the user refreshes the page or navigates to another page, they are logged in and are allowed to execute actions on the server.

So, what is an optimal way to detect if the password was changed via a password reset email that is sent by firebase?

@awinogrodzki
Copy link
Owner

Hey @Finalet!

The crash is caused by refreshServerCookies which throws INVALID_CREDENTIAL.

Could you share some logs with stack trace? I'd like to know if the refresh token is rejected by Google after password change.

So, what is an optimal way to detect if the password was changed via a password reset email that is sent by firebase?

The question has basically been answered in this thread

Basically, there is no easy way to do it on the backend, since Firebase does not provide any asynchronous communication with the backend itself. Probably you could detect it on the client side. For that you'd need to remove inMemoryPersistence strategy or use signInWithCustomToken to fetch latest current user state on the client side.

The main problem lies in the fact that you have to make a call to Firebase to check if the token was revoked. When to do it – it's the problem that has to be solved by the developer depending on their use case – there's no simple solution to that

@awinogrodzki awinogrodzki self-assigned this Dec 22, 2024
@awinogrodzki awinogrodzki added the question Further information is requested label Dec 22, 2024
@Finalet
Copy link
Author

Finalet commented Dec 23, 2024

Hi @awinogrodzki!

Thank you for getting back to me. Below is the full error for your reference:

AuthError: Invalid credentials: Error fetching access token: {"code":400,"message":"TOKEN_EXPIRED","status":"INVALID_ARGUMENT"} 
    at refreshExpiredIdToken (webpack-internal:///(action-browser)/./node_modules/next-firebase-auth-edge/lib/auth/index.js:103:15)
    at process.processTicksAndRejections (/Users/grantoganyan/Documents/GitHub/Pressdeck/lib/internal/process/task_queues.js:105:5)
    at async handleTokenRefresh (webpack-internal:///(action-browser)/./node_modules/next-firebase-auth-edge/lib/auth/index.js:159:60)
    at async refreshNextCookies (webpack-internal:///(action-browser)/./node_modules/next-firebase-auth-edge/lib/next/cookies/index.js:120:32)
    at async refreshServerCookies (webpack-internal:///(action-browser)/./node_modules/next-firebase-auth-edge/lib/next/cookies/index.js:181:26)
    at async RefreshCookiesAction (webpack-internal:///(action-browser)/./src/authentication/RefreshCookiesAction.tsx:23:9)
    at async /Users/grantoganyan/Documents/GitHub/Pressdeck/node_modules/next/dist/compiled/next-server/app-page.runtime.dev.js:157:2088
    at async handleAction (/Users/grantoganyan/Documents/GitHub/Pressdeck/node_modules/next/dist/compiled/next-server/app-page.runtime.dev.js:156:20859)
    at async renderToHTMLOrFlightImpl (/Users/grantoganyan/Documents/GitHub/Pressdeck/node_modules/next/dist/compiled/next-server/app-page.runtime.dev.js:161:17838)
    at async doRender (/Users/grantoganyan/Documents/GitHub/Pressdeck/node_modules/next/dist/server/base-server.js:1587:34)
    at async responseGenerator (/Users/grantoganyan/Documents/GitHub/Pressdeck/node_modules/next/dist/server/base-server.js:1834:28)
    at async DevServer.renderToResponseWithComponentsImpl (/Users/grantoganyan/Documents/GitHub/Pressdeck/node_modules/next/dist/server/base-server.js:1878:28)
    at async DevServer.renderPageComponent (/Users/grantoganyan/Documents/GitHub/Pressdeck/node_modules/next/dist/server/base-server.js:2292:24)
    at async DevServer.renderToResponseImpl (/Users/grantoganyan/Documents/GitHub/Pressdeck/node_modules/next/dist/server/base-server.js:2330:32)
    at async DevServer.pipeImpl (/Users/grantoganyan/Documents/GitHub/Pressdeck/node_modules/next/dist/server/base-server.js:984:25)
    at async NextNodeServer.handleCatchallRenderRequest (/Users/grantoganyan/Documents/GitHub/Pressdeck/node_modules/next/dist/server/next-server.js:281:17)
    at async DevServer.handleRequestImpl (/Users/grantoganyan/Documents/GitHub/Pressdeck/node_modules/next/dist/server/base-server.js:877:17)
    at async /Users/grantoganyan/Documents/GitHub/Pressdeck/node_modules/next/dist/server/dev/next-dev-server.js:373:20
    at async Span.traceAsyncFn (/Users/grantoganyan/Documents/GitHub/Pressdeck/node_modules/next/dist/trace/trace.js:157:20)
    at async DevServer.handleRequest (/Users/grantoganyan/Documents/GitHub/Pressdeck/node_modules/next/dist/server/dev/next-dev-server.js:370:24)
    at async invokeRender (/Users/grantoganyan/Documents/GitHub/Pressdeck/node_modules/next/dist/server/lib/router-server.js:183:21)
    at async handleRequest (/Users/grantoganyan/Documents/GitHub/Pressdeck/node_modules/next/dist/server/lib/router-server.js:360:24)
    at async requestHandlerImpl (/Users/grantoganyan/Documents/GitHub/Pressdeck/node_modules/next/dist/server/lib/router-server.js:384:13)
    at async Server.requestListener (/Users/grantoganyan/Documents/GitHub/Pressdeck/node_modules/next/dist/server/lib/start-server.js:142:13) {code: 'INVALID_CREDENTIAL', stack: 'Error: Invalid credentials: Error fetching ac…/next/dist/server/lib/start-server.js:142:13)', message: 'Invalid credentials: Error fetching access t…TOKEN_EXPIRED","status":"INVALID_ARGUMENT"} '}

As for detecting the password change, thank you for your input. So far my method is to catch this INVALID_CREDENTIAL error and set a new AUTH_CREDENTIAL_ERROR cookie to true. Then, in the middleware I check if this cookie is true and set checkRevoked to true:

const shouldCheckRevoked = req.cookies.get("AUTH_CREDENTIAL_ERROR")?.value === "true";

This would throw an error in the middleware which calls handleError where I clear this cookie and force logout the user.

This works fine so far, although feels a little hacky.

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

No branches or pull requests

2 participants