DEV Community

Cover image for Secure authentication in Nuxt SPA with Laravel as back-end

Secure authentication in Nuxt SPA with Laravel as back-end

StefanT123 on January 15, 2020

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...
Collapse
 
mkantautas profile image
Mantas Kantautas

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?

Collapse
 
stefant123 profile image
StefanT123

When your access_token has expired (because it's short-lived), we are sending a POST request to the refresh-token route, which calls the refreshToken method in the Controller. There we are checking if the httponly cookie is passed with the request, if it is, then we are getting a new access_token and new refresh_token.

Collapse
 
mkantautas profile image
Mantas Kantautas

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?

Thread Thread
 
mkantautas profile image
Mantas Kantautas • Edited

dump(request()->cookie()) returns an empty array on Cors.php middleware on /api/refresh-token request

Thread Thread
 
mkantautas profile image
Mantas Kantautas

Will your guide work in case my laravel api is site.test and my nuxt is running on localhost:3000 for e.g.? Because I coming to the conclusion that top-level domains must be the same for this to work?

Thread Thread
 
stefant123 profile image
StefanT123

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.

Thread Thread
 
brainuso profile image
brainuso • Edited

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

Collapse
 
smzapp profile image
smzapp • Edited

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 through request()->cookie('cookie')

i.imgur.com/YxbCYde.png

But on my browser, the refresh_token cookie is not existing. I already added AddQueuedCookiesToResponse in Kernel.php and tried to except the cookie in EncryptCookies but still, refresh_token is not existing.

i.imgur.com/WsGiaYi.png

Did I miss anything? THanks in advance.

Thread Thread
 
stefant123 profile image
StefanT123

As the refresh_token is set to be HttpOnly cookie, you can't access it or see it in the browser cookies. The refresh_token is used only to renew the access_token when it expires.

Collapse
 
thond1st profile image
thond1st

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!

Collapse
 
stefant123 profile image
StefanT123

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

export default function ({store}) {
  window.onNuxtReady(() => {
    // refresh the token
  });
}

As stated in the Nuxt.js docs for the plugin:

Nuxt.js allows you to define JavaScript plugins to be run before instantiating the root Vue.js Application.

If you are using some other JS library, check their doocumentation and see how can you run some function before instantiating the root app.

Collapse
 
abronson07013635 profile image
ABronson

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!!!

Thread Thread
 
stefant123 profile image
StefanT123

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:

  1. when the user log in, persist the user in the cookies (maybe use vuex-persisted state library)
  2. get the user from the store if it exists, if not, check in the cookies
  3. in the window.onNuxtReady() check if user is set in the vuex AND there isn't x-access-token in the cookies
  4. dispatch the action for refreshing the token
Thread Thread
 
orenlande profile image
orenlande

I'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.

Thread Thread
 
binumathew profile image
Binu Mathew

I am also got the similar error, get logout everytime i do a refresh, any option ?

Thread Thread
 
stefant123 profile image
StefanT123

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 and x-access-token does not exist, if these conditions are true, then you should dispatch an action to refresh the token.

export default function ({store}) {
  window.onNuxtReady(() => {
    let token = clientCookies.get('x-access-token');
    let user = clientCookies.get('user_id');

    if (user && ! token) {
      store.dispatch('auth/refreshToken')
        .catch(errors => {
          store.dispatch('auth/signUserOut');
        });
    }
  });
}
Thread Thread
 
alexwu66922308 profile image
Alex Wu

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

Collapse
 
jes490 profile image
Aleksey Sesyolkin • Edited

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:

  1. You 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"
  2. If you use asyncData or fetch 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?

Collapse
 
stefant123 profile image
StefanT123

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.

Collapse
 
jes490 profile image
Aleksey Sesyolkin • Edited

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 or fetch 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.

Thread Thread
 
stefant123 profile image
StefanT123

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.

Thread Thread
 
jes490 profile image
Aleksey Sesyolkin

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 )

Thread Thread
 
harsha935 profile image
Harsha Sampath • Edited

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...

Collapse
 
jameshull profile image
James R. Hull 🎬

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...

Collapse
 
stefant123 profile image
StefanT123

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.

Collapse
 
jameshull profile image
James R. Hull 🎬 • Edited

Trying to work this out with SSR (Universal) flow (everything worked great for SPA). When I make the original login call I get back the x-access-token, but the refresh_token is only listed in the Response/Request headers. I can set the x-access-token into cookie storage, but I'm not sure where the refresh_token ends up (can't seem to access it)

Once the time on the x-access-token expires, a page refresh or change triggers the refreshToken call, but the refresh_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...

Thread Thread
 
stefant123 profile image
StefanT123

You shouldn't store the refresh_token anywhere, it should be httponly cookie. As the name suggests, the refresh_token should be used for refreshing the access_token once it's expired.

Thread Thread
 
jameshull profile image
James R. Hull 🎬

OK - yeah, with SSR on the /api/refresh_token call, I'm getting a 500 - a Undefined property: stdClass::$refresh_token error in the ProxyRequest controller. It gets all the way to makePostRequest 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)

Thread Thread
 
stefant123 profile image
StefanT123

Hmm, if the refresh_token is in the Request Cookies, it should work fine. Do you json_decode the response?

Thread Thread
 
jameshull profile image
James R. Hull 🎬 • Edited

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());

Thread Thread
 
stefant123 profile image
StefanT123 • Edited

I can't help you unless I see your code :(
However, you can check the github links:

and make sure that your code matches.

Thread Thread
 
jameshull profile image
James R. Hull 🎬

Got it....Clear those old cookies people, lest you spend hours chasing your tail. (Refresh tokens are set for longer periods...)

Thread Thread
 
orenlande profile image
orenlande • Edited

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}

Thread Thread
 
stefant123 profile image
StefanT123

Yes, I mention that in the post, I guess you missed that part :D

Collapse
 
jameshull profile image
James R. Hull 🎬 • Edited

Just a couple things I noticed while working through this:

  • initial code of AuthController lists refreshTo() (should be refreshToken())
  • nuxt.config.js: credentials should be withCredentials: true, correct?
  • in the refreshToken milddleware, I assume when the cookie IS there, there should be a commit to the store to reset it (page refresh, direct access through URL). Like this?
  } else {
    store.commit('SET_TOKEN', token);
  }
Enter fullscreen mode Exit fullscreen mode
Collapse
 
stefant123 profile image
StefanT123
  1. Changed the refreshTo into refreshToken
  2. I saw that you've figured out yourself :D
  3. Well you can do that, but it will send a request on every route change and I don't like that. I'll only send a request when there the token is not there. That way, only one request will be sent every 5 minutes, and I think that's better approach.
Collapse
 
rzhevsky87 profile image
Rzhevsky87

You is not change refreshTo into refreshToken in this tutorial ))

Collapse
 
jameshull profile image
James R. Hull 🎬

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 the 403 error.

Collapse
 
jameshull profile image
James R. Hull 🎬

I was totally wrong about the withCredentials key...everything kept failing till I put it back the way you had it with credentials instead...weird because it goes against everything else I see.

THANK YOU!

Thread Thread
 
kenegade profile image
Ken Hall • Edited

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!

Collapse
 
devondahon profile image
gvi • Edited

Why not using the laravel.passport strategy in nuxt.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 and state, but I don't know how to use it to get token.

Collapse
 
samkoto profile image
Sam

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...

Collapse
 
stefant123 profile image
StefanT123

It's not flexible enough for my needs...

Collapse
 
smzapp profile image
smzapp

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 help

Collapse
 
abronson07013635 profile image
ABronson • Edited

Thanks 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)

Collapse
 
stefant123 profile image
StefanT123

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

return response([
    'user' => $user, // or even better wrap it in resource
    'token' => $token,
    'expiresIn' => $expiresIn,
    'message' => 'You have been logged in'
], 200);
Collapse
 
abronson07013635 profile image
ABronson

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);
})
}

  • A computed value for the current user in my NavBar.vue component, to display logged in users name currentUser() { return this.$store.state.user; },
Collapse
 
klukiyan profile image
Kiril Lukiyan

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?

Collapse
 
stefant123 profile image
StefanT123

You're doing something wrong

Collapse
 
klukiyan profile image
Kiril Lukiyan

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

Thread Thread
 
stefant123 profile image
StefanT123

I'm glad it helped you :)

Collapse
 
rzhevsky87 profile image
Rzhevsky87 • Edited

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 :

Access to XMLHttpRequest at 'http://localhost:8080/api/register' from origin 'http://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-Origin' header in the response must not be the wildcard '*' when the request's credentials mode is 'include'. The credentials mode of requests initiated by the XMLHttpRequest is controlled by the withCredentials attribute.
Enter fullscreen mode Exit fullscreen mode

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?

 
devondahon profile image
gvi

I would also be interested in knowing how to adapt this code to use the new PKCE.

Collapse
 
Sloan, the sloth mascot
Comment deleted
Collapse
 
stefant123 profile image
StefanT123

I didn't quite understand your question. Can you explain it a bit more?! :/

Collapse
 
dhanibaharzah profile image
dhanibaharzah

sorry, i have solved the problem 🙏

Collapse
 
orenlande profile image
orenlande

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:

  1. at nuxt.config.js:
    add to plugins array the following:
    plugins: [
    { ssr: false, src: '~plugins/app-bootstrap' },
    ...
    ]

  2. 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');

if(token) {
    store.dispatch('setToken', {token});
}

}

this way, we ensure we are using the same functions and workflow as the rest of the application.

Collapse
 
stefant123 profile image
StefanT123

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).

Collapse
 
orenlande profile image
orenlande

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.

Thread Thread
 
stefant123 profile image
StefanT123

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.

Collapse
 
soonseek profile image
soonseek

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.

Collapse
 
timothymarois profile image
Timothy Marois

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.

 
efillman profile image
Evan Fillman

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?

Collapse
 
klukiyan profile image
Kiril Lukiyan

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

Collapse
 
stefant123 profile image
StefanT123

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.

    [code]

    $params = array_merge([
        'client_id' => config('services.passport.password_client_id'),
        'client_secret' => config('services.passport.password_client_secret'),
        'scope' => '*',
    ], $params);

    [code]
Collapse
 
feliped97511974 profile image
Felipe Damasceno

Congratulations for this super tutorial! Keep Rocking!

Just a Q: In the middleware folder it should not be a new auth.JS file?

Collapse
 
stefant123 profile image
StefanT123

Thank you, and you are right, it should be auth.js. I'll change it right away.

Collapse
 
alamriku profile image
alamriku

request.headers.common.Authorization = Bearer ${token}

I have miss the Bearer word to write, it tooks 4 hour to solve the problem.

Collapse
 
javierpomachagua profile image
Javier Pomachagua

Such a great post for the stack that I love.

Collapse
 
devondahon profile image
gvi

Great article. Would be nice to have an update with Passport's PKCE :-)

Collapse
 
stefant123 profile image
StefanT123

Here you go, a post for PKCE autheticaiton

 
jameshull profile image
James R. Hull 🎬

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?

Collapse
 
alamriku profile image
alamriku • Edited

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:

Collapse
 
alamriku profile image
alamriku

have any one try to upload any file data?

Collapse
 
devondahon profile image
gvi • Edited

Laravel Sanctum and Laravel JWT have now been integrated to Nuxt Auth module.

Collapse
 
stefant123 profile image
StefanT123

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.

Collapse
 
ayatamine profile image
ayatamine

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 😭

Collapse
 
kazemmdev profile image
Kazem

Thank you for this great Article, one question: Is it possible to integrate nuxt/auth with your way?

Collapse
 
stefant123 profile image
StefanT123

Yes, but I don't want to use it, because it's not flexible enough for my needs

Collapse
 
bawa_geek profile image
Lakh Bawa

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

Collapse
 
jespinosaonline profile image
Jonathan Espinosa

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?

Collapse
 
stefant123 profile image
StefanT123

The flow will be more or less the same

Collapse
 
dhanibaharzah profile image
dhanibaharzah

hi stefant, how to implement the get methods in your tutorial?

Collapse
 
zohaibwahab profile image
zohaibwahab

hi , i am getting error (Undefined property: stdClass::$refresh_token) while testing with postman, is there any solution for this ?