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

Request for a feature to secure custom API endpoints. #450

Closed
hunghvu opened this issue Mar 16, 2022 · 10 comments
Closed

Request for a feature to secure custom API endpoints. #450

hunghvu opened this issue Mar 16, 2022 · 10 comments
Labels
needs info/repro Needs more info or a reproduction from the reporter

Comments

@hunghvu
Copy link
Contributor

hunghvu commented Mar 16, 2022

Is your feature request related to a problem? Please describe.
It appears the package does not provide server-side authentication for custom Next.js API endpoints. The current features only work for SSR pages with Firebase API call (e.g., Render page with populated information or redirect to Auth page), but there is nothing like a middleware, guard for custom endpoints.

A practical example is when users want to host applications on Google Cloud and use Google Identity Platform (IdP) for their organization authentication (for regulatory compliance purposes). Firebase/Admin SDK is required to interact with IdP, but users don't use any other Firebase functionalities. If there is an internal an endpoint api/get-info/, only authenticated users are able to access it.

Describe the solution you'd like and how you'd implement it

  1. Using Firebase's verifySessionCookie internally, we need a unified cookie (Support one unified cookie with a custom name, such as __session, for Firebase hosting #190). The two current cookies AuthUser and AuthUserTokens do not work with that API. This can be done either by having an option to return a unified cookie, or perform a server-side processing to transform the two current cookies into one.
  2. In InitConfig, have an option for onVerifySessionCookieError.
  3. Have an API to access verifySessionCookie.
  4. This can also utilize Next.js middleware feature (RFC: discuss value of Next.js middleware #418).

Is this a breaking change?
No.

Describe alternatives you've considered
If using Firebase Admin SDK directly, then this is achievable via a middleware with Firebase's verifySessionCookie. However, the downside is users need to rebuild the whole authentication flow, which is not desirable.

There is a chance my proposal is wrong in some ways, please feel free to correct the mistakes.

@hunghvu hunghvu added the enhancement New feature or request label Mar 16, 2022
@kmjennison
Copy link
Contributor

Thanks for the issue.

If you're looking to protect an endpoint, here's an example using the Authorization header and a Firebase token:
https://github.com/gladly-team/next-firebase-auth/blob/main/example/pages/api/example.js

You can create a reusable module to handle authorization across multiple endpoints.

If you're specifically looking to use cookies for auth, there's an open issue to support the functionality: #223

Possibly related: #418, #278

Do these address your issue? If so, I'll close this.

@kmjennison kmjennison added needs info/repro Needs more info or a reproduction from the reporter and removed enhancement New feature or request labels Mar 18, 2022
@hunghvu
Copy link
Contributor Author

hunghvu commented Mar 18, 2022

Thanks for the issue.

If you're looking to protect an endpoint, here's an example using the Authorization header and a Firebase token: https://github.com/gladly-team/next-firebase-auth/blob/main/example/pages/api/example.js

You can create a reusable module to handle authorization across multiple endpoints.

If you're specifically looking to use cookies for auth, there's an open issue to support the functionality: #223

Possibly related: #418, #278

Do these address your issue? If so, I'll close this.

  1. Yes, that addresses my issue. I did miss the example.
  2. Am I right to say the front page documentation is lacking in this regard? It's mostly about securing pages, not endpoints. Although, If I read the documentation more carefully, I may not have opened this issue.
  3. Regarding verifyIdToken in the example, it seems token revocation is not checked or is it done underneath? What I mean is a call using verifyIdToken(yourID, true).

@kmjennison
Copy link
Contributor

kmjennison commented Mar 18, 2022 via email

@hunghvu
Copy link
Contributor Author

hunghvu commented Mar 18, 2022

This discussion might derail from an original PR purpose, but please correct me if I'm wrong.

I believe Firebase does not check for token revocation by default. An explicit option must be added. This is under the assumption that a user does not use any Firebase features (e.g. security rules) aside from authentication service. For example, a server is on another cloud provider.

References

  1. Verify ID Token documentation
  2. Manage user session documentation

@kmjennison
Copy link
Contributor

Sorry, I wasn't very clear. Yes, you're right about that: we don't pass true to the second argument to Firebase's verifyIdToken, so this library won't know immediately that a token was revoked. However, I believe revoked tokens will lose access within an hour, because attempts to refresh the ID token will fail (whether called by the Firebase JS SDK or by this library's Firebase Admin logic). Does this sound right to you?

@hunghvu
Copy link
Contributor Author

hunghvu commented Apr 1, 2022

You're right, the short-lived ID Token will expire after an hour. A revoked token cannot be refreshed afterward. However, during that 1-hour timeframe, the application is vulnerable if a token is compromised. Or does next-firebase-auth have a way to prevent the scenario underneath?

// Securing an API
try {
      await verifyIdToken(token) // Always true unless one hour has passed after the revocation.
} catch (e) {
      return res.status(403).json({ error: 'Not authorized' })
}

@kmjennison
Copy link
Contributor

kmjennison commented Apr 4, 2022

during that 1-hour timeframe, the application is vulnerable if a token is compromised

That's correct.

Fixing this is out of scope for this library, but we could expose an option to allow developers to always check for token revocation. In that case, the library would pass true to the second argument to Firebase's verifyIdToken. That would come with the performance hit of a round-trip call to Firebase. (Edited: added missing word "could".)

I believe there are discussions elsewhere about how other apps deal with this in Firebase; for example, you might keep recently-revoked UIDs in memory for a quick lookup on your auth server.

@hunghvu
Copy link
Contributor Author

hunghvu commented Apr 4, 2022

but we expose an option to allow developers to always check for token revocation

May I ask how to use that option? As far as I can see withAuthUserTokenSSR does have a token revocation check, but it is not designed for API. Both initConfig and verifyIdToken do not seem to expose the boolean option.

However. we have a refresh token (retrievable from firebase-admin-sdk or cookies?) as a second argument that immediately triggers a refresh action when passing to verifyIdToken. This workaround is equivalent to check revocation, is that what you mean? If that is the case then I think the document is unclear regarding this.

@kmjennison
Copy link
Contributor

@hunghvu My mistake, I missed typing word that changed this a lot. "we could expose an option" -- we don't have this option now but could consider adding it if developers need it.

@hunghvu
Copy link
Contributor Author

hunghvu commented Apr 4, 2022

Sounds great. Thanks for answering all of my questions. From the discussion, the following may have their own issues.

  1. Improve README on ways to secure API endpoints.
  2. Option to expose check ID token verification option.

I will close this issue.

@hunghvu hunghvu closed this as completed Apr 4, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
needs info/repro Needs more info or a reproduction from the reporter
Projects
None yet
Development

No branches or pull requests

2 participants