next-firebase-auth
next-firebase-auth copied to clipboard
Extend existing Authentication methods to provide Authorization features
Is your feature request related to a problem? Please describe.
Currently the authorization methods withAuthUserTokenSSR and withAuthUserSSR allow us to validate if a request for page is Authenticated or not. We require that users are not only Authenticated but that the user also has the Custom Claim admin.
Describe the solution you'd like and how you'd implement it
The existing withAuthUserTokenSSR and withAuthUserSSR methods will be extended to take 2 optional additional parameters; which will be used to verify if the Authenticated users is Authorized to access the page; and if not redirect them to an appropriate access denied page (provided by the developer).
whenAuthed?: AuthAction.RENDER | AuthAction.REDIRECT_TO_APPwhenUnauthed?: AuthAction.RENDER | AuthAction.REDIRECT_TO_LOGINappPageURL?: PageURLauthPageURL?: PageURLvalidator? (user: AuthUser) => booleanaccessDeniedPageURL?: PageUrl
The existing method will be extended to accept the 2 emboldened new parameters (validator and accessDeniedPageURL). The method will then, once we have verified the authUser with existing code, run the validator function (if it is provided). If the validator function returns false we should then redirect the users to the accessDeniedPageURL.
Is this a breaking change? No, the additional options would be optional and so an opt in approach to upgrading the interface.
Describe alternatives you've considered The alternative we are currentyl using is handling this in our own code. While this is okay, it would be (I think) a feature that would be nice to push up to the framework.
Auth0's Next.js API could provide some guidance: https://github.com/auth0/nextjs-auth0#api-reference
So Auth0 seems to handle (with their Page Wrapper) Authentication (the binary determination of has this request supplied some valid credentials), but they do not supply a means of Authorization (i.e., do these credentials that the request has supplied grant you access to this page) - They leave it up to the Developer (which is fair I guess) - https://github.com/auth0/nextjs-auth0/issues/321
I also would like to have this feature, for instance to only grant access to a page if the emailVerified key on the User object is true.
So Auth0 seems to handle (with their Page Wrapper) Authentication (the binary determination of has this request supplied some valid credentials), but they do not supply a means of Authorization (i.e., do these credentials that the request has supplied grant you access to this page) - They leave it up to the Developer (which is fair I guess) - auth0/nextjs-auth0#321
Could you share how you would implement this in your code with the package as it currently is?
I've tried using using a custom ´tokenChangedHandler´ which checks ´authUser.emailVerified´, but I am having trouble figuring out how to redirect the user:
const tokenChangedHandler = async (authUser) => {
const loginAPIEndpoint = "/api/login";
const logoutAPIEndpoint = "/api/logout";
let response;
// If the user is authed, call login to set a cookie.
if (authUser.id) {
console.log("authuser", authUser);
if (!authUser.emailVerified) {
// how to redirect user to "verify-email" page?
//this creates an infinite refresh loop:
window.location.replace("/verify-email");
//also I cannot use next/router here, as it is not top level of function component
}
const userToken = await authUser.getIdToken();
response = await fetch(loginAPIEndpoint, {
method: "POST",
headers: {
Authorization: userToken,
},
credentials: "include",
});
console.log(response);
if (!response.ok) {
//
const responseJSON = await response.json();
throw new Error(
`Received ${
response.status
} response from login API endpoint: ${JSON.stringify(responseJSON)}`
);
}
} else {
// If the user is not authed, call logout to unset the cookie.
response = await fetch(logoutAPIEndpoint, {
method: "POST",
credentials: "include",
});
if (!response.ok) {
const responseJSON = await response.json();
throw new Error(
`Received ${
response.status
} response from logout API endpoint: ${JSON.stringify(responseJSON)}`
);
}
}
return response;
};
@lazlothemonkey - I have not tested this but I was thinking that something like this GIST would work: https://gist.github.com/gavinharris-dev/7ef07eae561e34c05869c21eba6c717e
So what you do is use the withAuthUserSSR getServerSideProps handler, and then wrap the response in your Email Verified Guard. This can then be used to redirect your users (Server Side Redirect with a HTTP 302 and Location Header.
Let me know how this goes! It would be cool to integrate this directly into the withAuthUserSSR as a couple of additional parameters. May need to think about how one could chain the authorization guards though; you may want one guard that ensures that the user is an Admin (with a custom claim) and then another that ensures that the user has a verified email address...
Closing this as something we won't support. It's outside of the current scope of this package, and contributors won't likely have time to build it out and maintain it.