This past period I was working on some project that included building Single Page Application in Nuxt that was on one domain, and building API in L...
For further actions, you may consider blocking this person and/or reporting abuse
Hey,
For some reason I keep getting
message: "Your refresh token is expired."
I suspect that here:
const {token, expiresIn} = await this.$axios.$post('refresh-token');
I am not sending a request with a
refresh_token
cookie attached? Can you please explain how refresh_token should be being passed here?When your
access_token
has expired (because it's short-lived), we are sending aPOST
request to therefresh-token
route, which calls therefreshToken
method in the Controller. There we are checking if thehttponly
cookie is passed with the request, if it is, then we are getting a newaccess_token
and newrefresh_token
.Hi @stefan
I am also encountering this problem. I tested on Postman and I can see the
refresh_token
into the cookie so I can get it throughrequest()->cookie('cookie')
i.imgur.com/YxbCYde.png
But on my browser, the
refresh_token
cookie is not existing. I already addedAddQueuedCookiesToResponse
in Kernel.php and tried to except the cookie inEncryptCookies
but still,refresh_token
is not existing.i.imgur.com/WsGiaYi.png
Did I miss anything? THanks in advance.
As the
refresh_token
is set to beHttpOnly
cookie, you can't access it or see it in the browser cookies. Therefresh_token
is used only to renew theaccess_token
when it expires.Yeah, this is clear, but for some reason, the cookie is not being passed from nuxt in the first place in the
await this.$axios.$post('refresh-token');
. Can this be because my front-end and back-end are on different domains? And how to overcome this?dump(request()->cookie())
returns an empty array on Cors.php middleware on /api/refresh-token requestWill your guide work in case my laravel api is
site.test
and my nuxt is running onlocalhost:3000
for e.g.? Because I coming to the conclusion that top-level domains must be the same for this to work?No, your apps can be on different domains, and this would still work. I can't know for sure what went wrong in your case. Maybe the
httponly
cookie isn't set in the first place, or you're sending the request without the cookie. Until I see the errors or some code, I can't know what's wrong.Was there a solution to this issue? I'm currently having the exact error when refresh token is called.
Update:
I ran this in the login after grantPasswordToken function:
Log::notice(cookie('refresh_token'));
and here is the response:
refresh_token=deleted; expires=Mon, 28-Oct-2019 22:11:22 GMT; Max-Age=0; path=/; httponly
This is a very usefull tutorial. I have implemented this in our prototype project but one of my colleague is complaining when the page is refreshed the user is being signed out so he implemented saving the token in the local storage. Am I right that the implementation is SPA so page reload is not needed but how did you circumvent when users try to refresh the page?
Thanks for this tutorial!
Never save the token in the local storage, if you do, you are exposing your app to potential attacks. If you are using Nuxt.js, you should simply make plugin and put this
As stated in the Nuxt.js docs for the plugin:
If you are using some other JS library, check their doocumentation and see how can you run some function before instantiating the root app.
Hi, this is a really great tutorial, any chance you would go into this part in a bit more detail, with refreshing the token in window.onNuxtReady()? I did a version which checks if x-access-token is set similar to the middleware, and then does router push to '/', but it's quite choppy and not sure how secure. Would be a nice addition to the post. Thanks!!!
I'm not sure if that requires whole new post, but maybe I'll do part 2 in addition to this post. Basically what you need to do is this:
window.onNuxtReady()
check if user is set in the vuex AND there isn't x-access-token in the cookiesI'd love to see how you apply it on code - having the same issues right now more or less. I want the user to stay logged on refresh.
I am also got the similar error, get logout everytime i do a refresh, any option ?
Once a user has logged in, you should put
user_id
in the cookies. Then make a plugin that will check if the user exists andx-access-token
does not exist, if these conditions are true, then you should dispatch an action to refresh the token.This doesn't seem to work for me, does this work for anyone else? It STILL signs me out every time I refresh the page. very annoying
Hi! Thanks for the article! One thing to note though -- will refreshing part work in universal mode (SSR) after page reload?
Let's imagine that you're authenticated and reading some page with auth middleware for 5 minutes (for access token to expire). Then you click refresh button in browser and several things will happen:
refreshToken.js
middleware will not work (because it will be fired from node.js server which has no refresh_token cookie, this cookie only available in browser) -- so you'll get "unauthenticated"asyncData
orfetch
to retrieve some data against auth middleware in laravel - you actually will not be able to do so either (also because there isn't refresh_token cookie in node.js)Actually if user visits auth page after access_token expiration then he will be logged out too. (For example if user tries to visit auth page on the next day or event after one hour)
Any way to get around these things?
Yes, I haven't covered that in this post, but I have posted a solution for this in the comments, here's a link. I think I should write a short post on this subject.
Thanks for the response!
Yes, I saw this comment, but I don't understand how it will solve the problems (okay, it may solve the first problem I described, but not the second -- which is most important).
I think if you store refresh_token in cookie -- there is no way to use
asyncData
orfetch
on api routes protected by auth middleware, because we have to do requests from node.js server for asyncData and fetch to work and we will be unauthenticated because of expired access_token and having no way to refresh it from node.I never tested it like that, but I use SSR only for SEO optimization, so if some content needs authentication, then in my case it doesn't need to be server-side rendered. But I have an idea how to get it to work, I'll try it as soon as I can.
Hmm, you're right actually... It doesn't make much sense to use asyncData() on auth pages.
But it would be nice to hear your idea about this case anyway )
Hi, I'm exactly stuck in this scenario. In this post Laravel httpOnly cookie is useless. because the author saving a cookie in frontend instead of using that httpOnly cookie. Ofcause, the author can't! Because when calling client-side HTTP request, httpOnly cookie which server sent, does not persistently save in the browser. Nuxt also cannot create httpOnly cookie even if it running on NodeJs! I have search about this issue and Nuxt authors are not capable to do that. github.com/nuxt-community/auth-mod...
This is fantastic! Thanks so much for posting. Any thoughts on modifying this because of Laravel Airlock? I assume this approach works well for SSR Nuxt (Universal) too...
Thanks. Yes, it works well, you just need to check for the cookie in the
nuxtServerInit
function. As for airlock, I haven't tried it, but I assume that same flow would be applied.Trying to work this out with SSR (Universal) flow (everything worked great for SPA). When I make the original
login
call I get back thex-access-token
, but therefresh_token
is only listed in the Response/Request headers. I can set thex-access-token
into cookie storage, but I'm not sure where therefresh_token
ends up (can't seem to access it)Once the time on the
x-access-token
expires, a page refresh or change triggers therefreshToken
call, but therefresh_token
is not set as a cookie for that call back to the server, and then I get the 403.I suppose I'm supposed to store the
refresh_token
as a cookie - but not sure how to even get it when it comes in. It seemed like SPA just kept it around...You shouldn't store the
refresh_token
anywhere, it should behttponly
cookie. As the name suggests, therefresh_token
should be used for refreshing theaccess_token
once it's expired.OK - yeah, with SSR on the
/api/refresh_token
call, I'm getting a 500 - aUndefined property: stdClass::$refresh_token
error in the ProxyRequest controller. It gets all the way tomakePostRequest
but then fails here:$this->setHttpOnlyCookie($resp->refresh_token);
With dev tools, I can see the refresh_token listed under Request Cookies, but it doesn't seem to be going up with the request (axios log doesn't list it)
Hmm, if the refresh_token is in the Request Cookies, it should work fine. Do you
json_decode
the response?Almost got this working - still Request is malformed - getting these two errors: Laravel\Passport\Exceptions\OAuthServerException
The request is missing a required parameter, includes an invalid parameter value, includes a parameter more than once, or is otherwise malformed.
ErrorException
Undefined property: stdClass::$refresh_token
and yes - following your code above explicitly:
$proxy = \Request::create('oauth/token', 'post', $params);
$resp = json_decode(app()->handle($proxy)->getContent());
I can't help you unless I see your code :(
However, you can check the github links:
and make sure that your code matches.
Got it....Clear those old cookies people, lest you spend hours chasing your tail. (Refresh tokens are set for longer periods...)
I'm having exact same issues now. Driving me mad - cannot figure out how to resolve it - any help?
And yes, I followed the tutorial 100% same.
EDIT: FOUND THE ISSUE!
seems like the .env wasn't configured properly - make sure the following exists:
PASSWORD_CLIENT_ID=2
PASSWORD_CLIENT_SECRET={secret_created_by_passport_in_step_1}
Yes, I mention that in the post, I guess you missed that part :D
Why not using the
laravel.passport
strategy innuxt.config.js
, as documented below ?auth.nuxtjs.org/providers/laravel-...
I'm actually struggling with it : from Nuxt.js, I'm redirected to Laravel login page and then back to Nuxt.js homepage with a
code
andstate
, but I don't know how to use it to get token.I am encountering the same problem. Have you figured out the solution? I posted this on stackoverflow but no reply yet. Maybe
middleware:auth
in nuxtjs for laravel passport has a problem. Very frustrating. Sigh!stackoverflow.com/questions/634971...
It's not flexible enough for my needs...
Just a couple things I noticed while working through this:
refreshTo()
(should berefreshToken()
)nuxt.config.js
:credentials
should bewithCredentials: true
, correct?refreshTo
intorefreshToken
You is not change
refreshTo
intorefreshToken
in this tutorial ))It looks like the refresh_token part is not working, unless I missed something. I can login,
x-access-token
is there - but when it comes time to refresh - I get the403
error.I was totally wrong about the
withCredentials
key...everything kept failing till I put it back the way you had it withcredentials
instead...weird because it goes against everything else I see.THANK YOU!
Hi there, I'm running into a CORS issue that I can't seem to get around. I'm using Laravel 7.5.2. Basically anytime I try to use the register function I get: Access to XMLHttpRequest at 'myapi.test/api/register' from origin 'localhost:3000' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: The value of the 'Access-Control-Allow-Credentials' header in the response is '' which must be 'true' when the request's credentials mode is 'include'. The credentials mode of requests initiated by the XMLHttpRequest is controlled by the withCredentials attribute. If I change the 'credentials' to 'withCredentials', it passes the CORS preflight, but then the token part does not appear to be working.
***FOLLOW UP: I'm still using the 'withCredentials' parameter. The issue going in that direction was in the .env using CLIENT_ID as opposed to PASSWORD_CLIENT_ID. That was mentioned before in this thread. Thanks!
This is a very useful lesson. Thank you author. I am new to frontend. Sorry for the stupid question. I have an error with CORS :
Can someone please explain in more detail what is the reason? And how is this solved?
... I using idea Ken Hall and this work for me. But i don't understand reason this problem.
And my refresh token expired on re-try to navigate to the page /secret =))
And there’s one more thing I don’t understand. For some reason, my navigation bar is not showing. What could be the reason?
I would also be interested in knowing how to adapt this code to use the new PKCE.
HEEEEY, I love this article so much. I finally could have a little of sense what AUTH is.
After a little of time spending to overcome page reload issue, I customized bit of your code.
Key issue was that I have to make my client read cookie from SSR part.
1) To get cookie from SSR, install 'cookieparser'
npm i cookieparser -S
2) @ store/index.js
const cookieparser = process.server ? require('cookieparser') : undefined
and action part,
async nuxtServerInit ({ commit, dispatch }, {req}) {
const token = cookieparser.parse(req.headers.cookie)['x-access-token']
await commit('SET_TOKEN', token);
},
3) @ middleware/refreshToken.js
if (! store.state.token) {
store.dispatch('refreshToken')
.catch(errors => {
store.dispatch('logout');
});
}else{
}
Hope this helps some people who are struggling to overcome page reload issue.
Hi, Thanks for this post. Does
cookie()->queue
work in you? I tried this but it can't retrieve the cookie. I already added AddQueuedCookiesToResponse in Kernel.php and also added the cookies in EncryptCookies.php. I think, I can't get cookie values in Laravel API. Is there anything I missed? Thanks for the helpThanks for the great tutorial. Would it make sense to do another dispatch in the login() method in login.vue, to a '/me' Laravel endpoint, and store some user information in Vuex, to use throughout the app? Any thoughts / best practices on that? (Replicating the Nuxt auth module a bit)
I would just directly return the user from the login route in Laravel along wiith the token, that way I wouldn't need to send two requests, one for the token and another for the user.
My response would look something like this
Awesome, thanks for the advice. I'm a bit of a noob with Vue/Nuxt, maybe there's a cleaner way to do it, but something like this seems to work (setting user on login, clearing user on logout).
Authcontroller.php
return response([
'user' => $user->name,
'token' => $resp->access_token,
'expiresIn' => $resp->expires_in,
'message' => 'You have been logged in',
], 200);
Added the user in store/index.js
export const state = () => ({
token: null,
user: null,
});
Added Vuex mutations:
SET_USER(state, user) {
state.user = user;
}
REMOVE_USER(state, user) {
state.user = null;
},
Added Vuex actions:
setUser({commit}, user) {
commit('SET_USER', user);
},
removeUser({commit}) {
commit('REMOVE_USER');
}
Changed logout method
logout: function() {
this.$axios.post('/api/logout')
.then(resp => {
this.$store.dispatch('removeUser');
this.$store.dispatch('logout');
this.$router.push('/login');
})
.catch(errors => {
console.log(errors);
});
}
Login.vue, login() method:
login() {
this.$axios.$post('/api/login', this.form)
.then(({token, expiresIn, user}) => {
this.$store.dispatch('setToken', {token, expiresIn});
this.$store.dispatch('setUser', user);
this.$router.push('/');
})
.catch(errors => {
console.log(errors);
})
}
Hey, Small suggestion to update your tutorial:
I've been stumbled upon the following issue (pretty common if we judge by comments) - once you refresh your SPA, you're being kicked out to main page.
After short research online and experimenting myself, I think the most elegant solution keep the login persist upon refresh would be using the nuxt.js plugins option:
at nuxt.config.js:
add to plugins array the following:
plugins: [
{ ssr: false, src: '~plugins/app-bootstrap' },
...
]
at root/plugins folder, add the file "app-bootstrap.js" and put inside the following:
import cookies from 'js-cookie';
export default ({ store }) => {
const token = cookies.get('x-access-token');
}
this way, we ensure we are using the same functions and workflow as the rest of the application.
I don't think this is the best solution, but it might work in your case. I've already addressed how to handle this in the comments, here's link. I think I'll do part 2 and 3 of this post, where in one I will go through the issue for the token on page reload, and the other will be for authenticating with PKCE (this may be a separate post, I haven't decided yet).
Imho - if we can resolve this without extra plugins and libs, it would be the best - reduce the overall package size and understand better what's going on.
What would be the advantages of including this plugin? I'm curious if I'm missing something on my solution.
It's not a third-party plugin, it's just a custom nuxt plugin that we going to create. Nuxt plugin is just some function that will be called before the instantiation of the root app, nothing more.
I didn't quite understand your question. Can you explain it a bit more?! :/
sorry, i have solved the problem 🙏
I spent a lot of time following this tutorial, fixing all the errors, setting up both environments to finally find out that it's not persistent.
The user has to login every time when opening a page.
Who would use such app?
You're doing something wrong
Maybe. I ended up with a working middleware and working login function.
So when I access the site, it brings me to login page. I login and get redirected to the dashboard.
However if I F5 to refresh the dashboard, the api calls that were made, return 401 not authorized.
Anyway, while I researched further I realized that I'd be totally find with @nuxt/auth and jwt or token approach. In my case I'm working on migrating the existing Laravel+jquery application to Nuxt + Laravel backend. Thus I need something that is relatively simple to add without breaking the existing functionality.
Thank you for your tutorial. Even though I won't use it in the end. I really started to understand how the things work and will be able to implement the @nuxt/auth
I'm glad it helped you :)
Any chance you were able to do the write up on not needing to persist the tokens client side and just using server side session?
Sorry for newbs question. What is that proxy for?
In order for this to work we need to make a proxy that will make request to our own API. It might seems confusing at first but once we're done it will make perfect sense.
Still don't understand it.
Thank you
Because we don't want our Passport
client_secret
exposed, so we are sending it with a proxy that's made in our backend along with the credentials that came from our frontend.So far everything works except for the refresh_token, always fails and logout happens every 5 minutes. I'll keep trying to see if I can get it working, but as of right now it does not based on the above details. Great tutorial however, just wish we could find a way to get refresh to actually work. My guess is, its not passing in the token to be refreshed.
Congratulations for this super tutorial! Keep Rocking!
Just a Q: In the middleware folder it should not be a new auth.JS file?
Thank you, and you are right, it should be auth.js. I'll change it right away.
Such a great post for the stack that I love.
Great article. Would be nice to have an update with Passport's PKCE :-)
Here you go, a post for PKCE autheticaiton
request.headers.common.Authorization =
Bearer ${token}
I have miss the Bearer word to write, it tooks 4 hour to solve the problem.
Thanks for the comment. To be honest, I wasn't aware that the new version of Passport ships with PKCE, thank you for the info.
Thank you for this great Article, one question: Is it possible to integrate nuxt/auth with your way?
Yes, but I don't want to use it, because it's not flexible enough for my needs
Laravel Sanctum and Laravel JWT have now been integrated to Nuxt Auth module.
What about if I don't use Register or Login Users and is only the Frontend using the Client Credentials Grant Tokens from Laravel Passport?
The flow will be more or less the same
To be clear for those of us new to Passport, the PKCE "hack" -- is that the Proxy bit? In other words, what part is no longer needed because of v.8?
Hi, thanks for the great article, how can we use the last Proxy for multi-auth in laravel (user + admin ). I'm getting stuck in it for four months 😭
have any one try to upload any file data?
did any try to upload image file using form data. on passport base laravel app?
Having problem to upload file its not uploading when i have used:
This post is super incomplete, you gonna waste a lot of time trying to solve the problems, it has a lot of gotchas, I mean a lot. Don't waste your time on it, use nuxt-auth
How this will work with multi tenant. alway redirect to /login. it should be redirect on domain/tenant/login. I am using pathindentifiication tenant. please help me how to achieve this.
hi stefant, how to implement the get methods in your tutorial?
hi , i am getting error (Undefined property: stdClass::$refresh_token) while testing with postman, is there any solution for this ?