spotify-api / spotify-api.js

A complete wrapper for spotify web api for deno, node.js and the browser.
https://spotify-api.js.org
MIT License
214 stars 19 forks source link

How to get user info from currently logged in user. #68

Closed tintin10q closed 3 years ago

tintin10q commented 3 years ago

Question and Help

I am using this library with vue in a client side application.

In version 8 I was able to get the user info with something like this:

const token = this.get_access_token_from_params(this.params) // after doing an implicit grant with a redirect
console.log("Token:", token)
await this.$spotify.login(token)
const user_info = await this.$spotify.user.info()

How would this work in version 9? From the welcome page it really seems like I need to give the client secret but this would be a bad idea as this code will be running on the client.

I got this now:

      const token = this.get_access_token_from_params(this.params)  // after doing an implicit grant with a redirect
      console.log("Token:", token)
      const userClient = await this.$spotify.create({"token": token}) // this.$spotify is new Client
      const me = userClient.user?.displayName
      console.log(me)   // This is undefined

this .user has undefined for displayName and images. It seemed really easy to get the user info in v8. What am I missing here?

scientific-dev commented 3 years ago

In v9, you can simply do it like this....

const token = this.get_access_token_from_params(this.params) // after doing an implicit grant with a redirect
const userClient = await Client.create({ token, userAuthorizedToken: true });

Set true to the userAuthorizedToken to cache user info. You can view the documentation for the ClientOptions.

You can simplify it further more to,

const client = await Client.create({
    token: {
        clientID: 'id', // Your spotify application client id.
        clientSecret: 'secret', // Your spotify application client secret.
        code: 'code', // The code search query from the web redirect. Do not use this field if your aim is to refresh the token.
        refreshToken: 'refreshToken', // Use this field only if your aim is to refresh your token instead of getting new one put your refresh token here.
        redirectURL: 'url' // The redirect url which you have used when redirected to the login page.
    }
});

If any suggestions or doubts, create a new issue and if your question is answered kindly close this issue.

tintin10q commented 3 years ago

Thanks for the swift reply I will try this out.

tintin10q commented 3 years ago

I have a question you mention that creating a client with a token like this would be simpler.

const client = await Client.create({
    token: {
        clientID: 'id', // Your spotify application client id.
        clientSecret: 'secret', // Your spotify application client secret.
        code: 'code', // The code search query from the web redirect. Do not use this field if your aim is to refresh the token.
        refreshToken: 'refreshToken', // Use this field only if your aim is to refresh your token instead of getting new one put your refresh token here.
        redirectURL: 'url' // The redirect url which you have used when redirected to the login page.
    }
});

But this would mean that I would have to store the client secret on the clients machine. Like if someone opens the vue app they could in theory get access to the client secret right?

scientific-dev commented 3 years ago

I have a question you mention that creating a client with a token like this would be simpler.

const client = await Client.create({
    token: {
        clientID: 'id', // Your spotify application client id.
        clientSecret: 'secret', // Your spotify application client secret.
        code: 'code', // The code search query from the web redirect. Do not use this field if your aim is to refresh the token.
        refreshToken: 'refreshToken', // Use this field only if your aim is to refresh your token instead of getting new one put your refresh token here.
        redirectURL: 'url' // The redirect url which you have used when redirected to the login page.
    }
});

But this would mean that I would have to store the client secret on the clients machine. Like if someone opens the vue app they could in theory get access to the client secret right?

No, the token is been generated with those options and then stored it in Client.token property. But the credentials are stored in Client.refreshMeta property. Which is a security vulnerability for browser clients so i have fixed it and published v9.0.1. So now i guess there should be no risk of exposing it if you have upgraded your module to v9.0.1. And if there is any bug with the new v9.0.1 kindly create a new issue.

tintin10q commented 3 years ago

Thanks for the update that is amazing!

I wonder though if this makes it safe. Because the client secret would still be send in the code that is send to the client to be executed by the browser. What are your thoughts about that?

scientific-dev commented 3 years ago

Thanks for the update that is amazing!

I wonder though if this makes it save. Because the client secret would still be send in the code that is send to the client to be executed by the browser. What are your thoughts about that?

No, the client secret is a temporary value in the Client constructor and only the token is saved in the Client.token property. If you want to save try to see ClientOptions.refreshToken type in the documentation.

tintin10q commented 3 years ago

Ok that sounds great. But my point is that for this to work my secret needs to be somehow hardcoded into the app. Lets say the app I make is running and I fetch the html/css/javascript but I just collect the JavaScript but don't actually run it. Then someone could go trough it to find the client secret in the code.

So even if the value is temporary then it would still be there before the code is executed in the first place.

Or am I missing something here?

scientific-dev commented 3 years ago

Ok that sounds great. But my point is that for this to work my secret needs to be somehow hardcoded into the app. Lets say the app I make is running and I fetch the html/css/javascript but I just collect the JavaScript but don't actually run it. Then someone could go trough it to find the client secret in the code.

So even if the value is temporary then it would still be there before the code is executed in the first place.

Or am I missing something here?

Well, there is no way they can access the token because i mean the token is basically a temporary memory value which is within a function (constructor).

tintin10q commented 3 years ago

Yeah but if they don't actually execute the javascript then they could get it.

Like if its in the code thats send but the client just decides to not execute it and just read trough it then they could find the secret.

scientific-dev commented 3 years ago

Yeah but if they don't actually execute the javascript then they could get it.

Like if its in the code thats send but the client just decides to not execute it and just read trough it then they could find the secret.

Do you mean the new generated token from the params provided?

tintin10q commented 3 years ago

No I don't mean that I mean the client secret.

It is also needed in the constructor.

clientSecret: 'secret', // Your spotify application client secret.

scientific-dev commented 3 years ago

No I don't mean that I mean the client secret.

That is one of the major cons of using frontend try using an api and get the clientSecret or do this thing in the backend and send the props to the frontend.

It is basically everyone do, they do this credential stuff in the backend not in the frontend.

tintin10q commented 3 years ago

Ok thanks.

Also thanks for replying so quickly every time!

scientific-dev commented 3 years ago

Ok thanks.

So i guess you could close this issue as your doubts has been cleared.