NuxtJS and Auth Route Exemptions - javascript

I'm current using Nuxt.js and the authentication module it comes with.
Is it possible to create exemptions in auth to prevent automatic redirection to the login page when a user is not logged in?
Take the following as an example:
User is not logged in and navigates to: http://localhost:3000/#/password-reset
They will be redirected to the login screen: http://localhost:3000/#/login
I want to create an exemption so that all routes are protected by auth, which they already are, with the exception of the page to reset passwords (http://localhost:3000/#/password-reset).
How is this possible?

I assume your are using nuxt-auth.
Create a middleware middleware/isAuth.js:
export default function({ app, error }) {
if (!app.$auth.loggedIn) {
// If you want to redirect to login page
app.router.push('/password-reset')
// If you want to throw error, use this:
return error({
statusCode: 403,
message: 'You are not allowed to see this'
})
}
}
In page you want to protect, declare your middleware:
export default {
...
middleware: ['isAuth'],
...
}
It will prevent page if user is not logged in.
To log user, you should use loginWith.

Related

Auth0 with Vue not staying logged in after refresh on mobile devices

I am using Auth0 with a Vue application. Auth0 is acting strange and I have no idea where to begin.
If I am on a computer, then when switching pages in my app, the user gets logged out for a few seconds, the page loads and then Auth0 "loads" and logs the user back in. This is not desirable since it takes a few seconds to load up certain data on the page that only a user who is logged in should be able to see.
But this is my main problem:
On mobile devices, the user gets logged out when navigating to a new page within the app but the user never gets logged back in. Same thing happens when I refresh the page. The user gets logged out and I have to click the login button again.
Can't I make Auth0 work more efficiently where the user is immediately logged in when switching pages or never logged out in the first place?
This is all of my relevant code:
This is where Auth0 is imported into the app in main.ts:
import { createAuth0 } from "#auth0/auth0-vue";
app.use(
createAuth0({
domain: 'SOME_DOMAIN.auth0.com',
client_id: 'SOME_ID',
audience: 'SOME_AUDIENCE',
redirect_uri: window.location.origin,
scope: 'openid'
})
)
And then in each of the components that need to check if a user is logged in, I have this code:
import { useAuth0 } from '#auth0/auth0-vue'
// only showing relevant code here
setup() {
const { user, isAuthenticated, getAccessTokenSilently } = useAuth0()
return {
user,
isAuthenticated,
getAccessTokenSilently
}
}
And this is pretty similar code here but this is in the header component (rendered on every single page in the app) and contains the login/logout buttons:
setup() {
const { user, isAuthenticated, getAccessTokenSilently, loginWithRedirect, logout } = useAuth0()
return {
user,
isAuthenticated,
getAccessTokenSilently,
login: () => {
loginWithRedirect();
},
logoutUser: () => {
logout({ returnTo: window.location.origin })
}
}
},
So what am I missing? I need Auth0 to be more persistent. Am I missing some code?
Edit: not sure if this is important but this is how I navigate from one page to another:
router.push({ path: `/place/${store.selectedListView?._id}` })
I'm dealing with a similar problem using auth0 with react running on localhost. When I log in using loginWithRedirect(), auth0 places cookies on my browser but they would be cleared when I refresh the browser.
One solution to this was to enable 3rd party cookies for the localhost domain by going to browser settings, privacy and security, cookies and other site data, in "Sites that can always use cookies", add "http://localhost" and enable third party cookies for this site. This would let me stay logged in after reloading/refreshing.
However, I'm pretty sure there is a way to make this work without 3rd party cookies. I'll post it if found.

why is my firebase authentication display name not getting updated properly with react js?

I am trying to build firebase authentication for my react app..After I sign in I am trying to update the displayName and then redirect..On the redirected page I am trying to greet the user by fetching the display name saved while signing up with firebase..This page works properly immediately after I redirect but if I reload this page then it is not able to show the displayName and throws this error:
TypeError: Cannot read property 'displayName' of null
This is the function which gets triggered when signup button is clicked..
const signup = async () => {
try{
await firebaseApp.auth().createUserWithEmailAndPassword(email, password)
await firebaseApp.auth().currentUser.updateProfile({displayName:username})
console.log(firebaseApp.auth().currentUser)
if (!firebaseApp.auth().currentUser){
setLoading(true)
}
history.push('/home')
}catch (error){
alert(error.message)
}
}
This is the JSX of the page which is being redirected to by signup page:
<div className="greetings">
Good Evening {firebaseApp.auth().currentUser.displayName}
</div>
Why is this issue happening and how to resolve it?
firebaseApp.auth().currentUser is always null when a page first loads. It won't contain a User object until some time later, after the SDK is able to load and verify the auth token for that user. Instead of using currentUser, you should set up an auth state observer as shown in the documentation. This observer will get invoked as soon as the User object is known.
firebase.auth().onAuthStateChanged(function(user) {
if (user) {
// User is signed in.
// ...
} else {
// User is signed out.
// ...
}
});
You can use the results of this observer function to know when the user is signed in or signed out over time. To learn more about how it works, read this blog post.

Is it possible to use session cookies in Firebase to stay logged in without firebase-admin package?

I'm using firebase in my next.js app to login. My login works but logs out every time a user changes paths inside the site. Once logged in, the user is redirected to the front page with path=/ if a user changes paths to path=/question/page firebase immediately logs them out but their session cookie has not expired. I would like to use the session cookie to keep a user logged in until it expires no mater where they navigate on the site. I am not about to use the package firebase-admin because it keeps crashing my next.js site. I can only use the regular firebase package which includes firebase.auth() along with js-cookie package. Here is the code I am using to set my cookie:
componentDidMount() {
let user = firebase_auth.currentUser;
console.log("User: ", user);
if (user) {
this.setState({user_logged_in: true});
return firebase_auth.currentUser.getIdToken(true).then(function (token) {
Cookies.set('__session', token, {expires: 7});
})
}
else {
this.setState({user_logged_in: false})
}
}
How would I be able to use the session cookie being called in the code above so that my users aren't being logged out every time they navigate to a new path?
Thanks for your help in advance!
Firebase Authentication SDKs automatically persist the user state between page/app reloads, and try to restore that state upon the restart.
The most likely cause of your problems, is that Firebase is still checking whether the authentication state is valid when you access firebase.auth().currentUser.
In that case, the solution is to use an auth state listener:
componentDidMount() {
firebase.auth().onAuthStateChanged(function(user) {
if (user) {
this.setState({user_logged_in: true});
firebase_auth.currentUser.getIdToken(true).then(function (token) {
Cookies.set('__session', token, {expires: 7});
})
} else {
this.setState({user_logged_in: false})
}
});
}

Redirect Vue Router to intended page after a user signs in

I'm working on an application that blocks a user from accessing any page besides home and signup unless they are signed in. I have a catch all route guard that checks if the user is signed in when trying to access a page and redirects to the sign in if it returns false. In the sign in component, once the user signs in, they are directed to the home page. What I want to set up is when the user signs in it redirects to the last page on the app if they had previously been on a page or had typed in a direct url to a page, if not redirect to the home page. For example:
User navigates to my.app/{somePage} -> route guard check for signin returns false -> redirect to my.app/sigin -> user successfully signs in -> redirects to my.app/{somePage}
//Route Guard
router.beforeEach((to, from, next) => {
if(!signedIn()){
router.replace('/signin')
}
else{
next()
}
})
//Successful signin
signInSuccess(){
//Want this to redirect to intended page if exists
this.$router.replace('/')
}
I've tried redirecting using this.$router.go(-1) but when I redirect to the signin page in the route guard the intended route doesn't seem to get pushed into the history.
I've also tried to set up the state in my vuex store to capture the intended route and use that to redirect after sign in but the route guard seems to reload the entire page so the store state gets reset.
The only other thing I can think of is to store the intended page route in the browser localstorage but that doesn't seem like a reliable solution.
Try to add
next({
path: '/signin',
query: { redirect: to.fullPath }
})
instead of
router.replace('/signin')
The whole guard function would be like this:
router.beforeEach((to, from, next) => {
if (to.matched.some(record => record.meta.requiresAuth)) {
// this route requires auth, check if logged in
// if not, redirect to login page.
if (!signedIn()) {
next({
path: '/signin',
query: { redirect: to.fullPath }
})
} else {
next()
}
} else {
next() // make sure to always call next()!
}
})
It's taken from the vue-router docs and it helped in my case.
https://router.vuejs.org/guide/advanced/meta.html
For anyone landing here in the future, #ilnicki010's answer is correct. Once it takes you to the login page and user signs in successfully, you'll have access to router.currentRoute.value.query.redirect that you can supply to router.push() to get back to the page that the user was on.
This is according to Vue Router 4 and Vue 3.

Authentication logic for sessions that last while tab is open

Assume you are working on a front end application that performs authentication through 3rd party api. Successful authentication returns a json web token.
What would be best practices to store such token and create some sort of session for user while he is active on the website i.e. didn't close a tab or browser, however refreshing / reloading a page should not destroy such session.
Also, how can this session be used to protect routes? I am working with a stack consisting of react / redux / node / express and quiet a few other libraries. I believe I can perform certain checks within my react-router, however wouldn't it be better to do these on the express side?
You can store the token in localStorage or sessionStorage, and include it in every API request.
Local storage outlives the tab, it's stored there until you explicitly delete from it, so refreshing a page won't be a problem. Even closing a tab and then coming back won't be.
Session storage allows you to store data. Page refreshes are fine, but tab closing isn't, which is closer to the behavior you want.
As for protecting routes, the server should obviously check the token on requests to all protected API routes.
On the browser side, you will probably want to show a login form if a user tries to visit a protected route but the token isn't there (or is invalid).
With react-router, you could do it like the official repo shows in the example, via onEnter hooks: https://github.com/reactjs/react-router/blob/master/examples/auth-flow/app.js
An alternative would be to create two top-level components, one for protected routes, one for public routes (like a landing page or the sign in/sign up forms). The protected handler will then in componentWillMount check if there's a token:
- PublicHandler
+ SignIn
+ SignUp
+ Index
- ProtectedHandler
+ Dashboard
+ MoneyWithdrawal
it may looks like that , with sessionStorage (JWT token is accesseble, untill browser or tab closed)
///action creator redux
export const signupUser = creds => dispatch =>{
dispatch(requestSignup());
return API.auth.signup(creds)
.then(res => {
sessionStorage.setItem('token', res.token);// <------------------
dispatch(receiveSignup(res));
return res;
})
.catch(err => {
dispatch(SignupError(err));
);
});
};
On client : handling auth through HOC redux-auth-wrapper
On server on server you can use passport-jwt strategy
passport.use('jwt',new JwtStrategy(opts, function(jwt_payload, done) {
User.findOne({where:{ id: jwt_payload.user.id }}).then(user=>{
if (user) {
done(null, jwt_payload.user);
} else {
done(null, false);
// or you could create a new account
}
},err=>{
console.log('Error ',err);
return done(err,false);
});
}));
then just add route handler
var checkJWT = passport.authenticate('jwt')
router.get('/protected',checkJWT, (req, res) =>{
res.json(req.user);
});
You don't need sessions on server for that

Categories

Resources