directus / directus

The flexible backend for all your projects šŸ° Turn your DB into a headless CMS, admin panels, or apps with a custom UI, instant APIs, auth & more.
https://directus.io
Other
27.24k stars 3.81k forks source link

Directus SDK, send back undefined refresh_token #12427

Closed halwesit closed 2 years ago

halwesit commented 2 years ago

Preflight Checklist

Describe the Bug

Hello Everyone, I have used Directus with NuxtJS, I have a problem with authentication.

To Reproduce

when I request for '/auth/login' using Postman, nothing goes wrong, I will get the object with three keys like this: " data": { "access_token": "eyJhbGc...", "expires": 3600, "refresh_token": "CMg..." } but when I request the same URL with the same and different credentials using Directus SDK and NuxtJS, I will get the object like this: " data": { "access_token": "eyJhbGc...", "expires": 3600, "refresh_token": undefined }, also I tried using Fetch and Axios, I will get an object like the Postman response, but also they have another problem that they cache my requests and didn't update when I request for new user login, they send back the same first user's login data.

Errors Shown

No response

What version of Directus are you using?

9.7.1

What version of Node.js are you using?

v16.14.2

What database are you using?

Postgres 13

What browser are you using?

Chrome,

What operating system are you using?

Windows (My PC), Linux (VPS)

How are you deploying Directus?

PaaS (Caprover)

azrikahar commented 2 years ago

but when I request the same URL with the same and different credentials using Directus SDK and NuxtJS

Can you share more details on this specific setup, as well as whether the request is happening on client side or server side (depends on your setup)?

Would you mind testing it on a fresh local Directus instance as well? Just so we can hopefully narrow down the root cause here.

halwesit commented 2 years ago

Hey, thanks for your replay, this is the Directus information View Image, I have used Caprover with Docker and PostgreSQL DB, I think the problem isn't with the Directus platform, but with the Directus SDK, because I have tried the same requests with Postman and Axios also, everything goes well, and nothing wrong happened.

For know I have solved my problem by using Axios and setting up my own Auth script, but I wanted to share this bug, to be solved for the feature.

rijkvanzanten commented 2 years ago

@halwesit Could you share the exact snippet of code you used with the SDK? That would help narrow this down for us šŸ™‚

halwesit commented 2 years ago

@rijkvanzanten as I mentioned at the first I have used Nuxt JS, I wrote a plugin for Directus to be available as a global variable as $directus, and this is my plugin code

import { Directus } from "@directus/sdk";

const directus = new Directus("directus-server");

export default (_, inject) => {
  inject("directus", directus);
};

and for the login request, I wrote this code:

async login(){
   try {
      await this.$directus.auth.login({
     email: this.emailModel,
     password: this.passwordModel,
      }).then((res) => {
         console.log(res)
      })
   } catch(err) {}
}

and got the result that I mentioned before.

rijkvanzanten commented 2 years ago

thanks!

azrikahar commented 2 years ago

I believe this circles back to the original question of "whether the request is happening on client side or server side"!

but also they have another problem that they cache my requests and didn't update when I request for new user login, they send back the same first user's login data.

Based on the plugin code you have shared, then it'll run once on the server side initially, which answers the above statement as the server side is using the "cached" access token and not the current user in the browser.


And to answer the question of why using Postman does return the refresh_token in the response body, this once again relates to the server side vs client side thing, as Postman for example is "server side" in this context.

When the this.$directus.auth.login is called, it passes the mode property which differs between server (json) and client (cookie):

https://github.com/directus/directus/blob/30253359183aa30411a2e32b7272ff4ee479fbec/packages/sdk/src/base/auth.ts#L100-L104

The API then only return the refresh_token if it's server side (json) as seen here:

https://github.com/directus/directus/blob/30253359183aa30411a2e32b7272ff4ee479fbec/api/src/auth/drivers/local.ts#L86-L88

because for clients, it is set as cookie instead.

Currently the SDK returns the object as the following:

https://github.com/directus/directus/blob/30253359183aa30411a2e32b7272ff4ee479fbec/packages/sdk/src/base/auth.ts#L110-L114

which is why refresh_token is undefined, whereas it may probably be best to only attach this property if it exists so that it doesn't show up at all when it's not.


To actually address the SDK in the context of Nuxt 2 plugin (since you're using inject), I believe the two possible solutions would be:

  1. Making the plugin to be client side only: https://nuxtjs.org/docs/directory-structure/plugins/#client-or-server-side-only, but this does depend on the nature of your Nuxt app.

  2. Using something like cookie-universal-nuxt to set the access/refresh tokens and make it work seamlessly for SSR.

With that said, I'm not sure would this still qualify as an issue with the SDK anymore as it's more of a Nuxt plugin setup thing. šŸ¤”

halwesit commented 2 years ago

Thank you @azrikahar, appreciate your response.