i am building a prototype to prove deriving user playlist etc. from Spotify.
As this is user information, i've to use Spotify's authorization code workflow (refer https://developer.spotify.com/web-api/authorization-guide/#authorization_code_flow)
In this workflow, an application requests user to grant scoped privileges so relevant information can be pulled out.
In the series of calls that follow:
call to /authorize
calls back a redirect_uri sent in request and sends in a code
e.g.
redirect_uri=../abc receives ../abc/callback?code=xyz
as is exemplified in docs.
xyz is then sent over to /api/token to get access_token and refresh_token
Is there any way one can avoid to repeatedly invoke /authorize after once the grant has been given by user?
In-effect, can i not treat the code (from /authorize) like an oauth token and preserve it (say in database) to get a new access_token every time i need one? (as a direct comparison check facebook's oauth token that can be saved and reused to authenticate every next time)
How can i remember a user has already granted me access to his/her Spotify profile and data?
Please indicate if i am missing something obvious from documentation. please point me right if this has been specified elsewhere.
many thanks!
For this use case you can use the Authorization Code flow. What you should persist is the refresh_token it returns, which can be used to obtain access tokens. You can also optionally persist the access token, that you can use during one hour, so you don't need to obtain a new access token every time.
There is a FAQ in the Authorization Guide that talks about a similar scenario, where a user would want to manage her playlists without having to go through the login process every time:
You basically need an access token and a refresh token issued for your user account. For obtaining a pair of access token / refresh token you need to follow the Authorization Code Flow (if you need a certain scope to be approved) or Client Credentials (if you just need to sign your request, like when fetching a certain playlist). Once you obtain them, you can use your access token and refresh it when it expires without having to show any login form.
Related
I'm using authentication code mechanism through Docusign's API for integration and works as expected.
Have a question regarding the documentation about implementation best practises, described in this page
Questions are related to the diagram at the end:
Question1
In Get the user's account ID, base URL and name (1st square) how do you recommend fetching the user/account information as before consent we don't know who is giving consent?
If it is related to users that may have given consent before, is it even necessary? If tokens already exist for the user, what is the purpose of verifying this scenario?
In the documentation it seems this is reinforced further with what is stated next:
How will we know what is the account/user information before the user gives consent?
Question2 (Similar to above)
In Collect the account ID (GUID) and name of the user, when no access token is found, I'm assuming we should redirect the user immediately so that the use gives consent again. Similar to the question above, in the diagram it indicates we should do this action "Collect account/user info" somehow before redirect for consent? We only know it afterwards as well, so is it needed?
It would be great if it would be possible to clarify the above!
As Inbar commented, that diagram needs some work. I'm sorry for the confusion.
Here's my recommendations for user present (Authorization Code and Implicit grant flows) and user absent (JWT grant flow).
All authorization flows
Determine if your users will typically use your application with a particular eSignature account or with any of their accounts. (It is common for customers to have access to more than one DocuSign eSignature account.)
If a particular account will be used, then provide an installation screen for your app where the admin can enter the account ID (use the guid format).
Your installation screen should also enable the installer to set
the DocuSign OAuth service provider, either production account.docusign.com or demo account-d.docusign.com
User present: Authorization Code and Implicit grant flows
Your app may or may not have its own login sequence for users. Your app needs a DocuSign access token for making API calls to DocuSign APIs.
When your user wants to authenticate with DocuSign:
Start the Authorization Code or Implicit grant flow.
When the flow is done, your app has an access token.
If the Authorization Code grant flow was used then you also have a refresh token.
Use the oauth/userinfo API call to obtain information about the user:
Their name and email
The eSignature accounts they have access too, and which of those accounts is the user's default account
For each account, the name of the account and the baseUrl for making API calls to the account.
If your app's users use a preferred account, then check that the user has access to the preferred account. Else, note the account id of the user's default account. (Also be prepared to handle the cases where there is either no userinfo response, no account or no default account for the user. These are infrequent DocuSign errors and can be fixed by contacting DocuSign Customer Support and referencing this article.
Use the expires_in OAuth response attribute to calculate your expires datetime. Then subtract 10 minutes so you have a buffer between the time you'll last use the access token and when it actually expires. You now have the last_use time.
Store the user's information, including the account id, base url for the account, access token, and last_use datetime.
If you have a refresh token, store it (and the user's information) in non-volatile storage.
When your application wants to make an API call
If you have a current access token for the user (last_use datetime is after the current datetime) then use it.
If the last_use time has passed, then use the refresh token if you have it. When refreshing the toke, you'll receive a new refresh token. Store it in non-volatile storage, overwriting the prior refresh token.
If no refresh token, then your app will need to ask the user to authenticate again.
Do not use oauth/userinfo again after either the token was refreshed or the user authenticated again. Keep and use the userinfo obtained after the person first logged in.
When your user wants to use a different account
Provide a "Switch accounts" feature to enable users to choose which of their accounts should be used. (Only applies if any account can be used with the application.)
User not-present: JWT grant
Your app's configuration screen will also need the user id in guid form. You can either store these values or look them up from DocuSign.
Decide whether a specific account is needed or not (see above).
Decide how the user will grant consent. See this video for more info.
First time your app needs an access token after a reboot
Use the JWT user grant to obtain an access token
As above, calculate the last_use datetime including a 10 minute buffer.
Use oauth/userinfo as above to determine if the user has access
the account or what the user's default account is. Also obtain the account's base_url.
Store the information.
Use the access token to make the API call.
Subsequent API calls
Check the last_use datetime. If it hasn't yet occurred then use the stored access token. If it has occured, then redo the JWT user grant flow but do not make another oauth/userinfo call--use the prior information.
Question 1 - You do not need to remember which user gave consent. That is not something you should do anyway, because users can revoke consent and then your information will be inaccurate. The system will ask for consent if needed (and if you ask for additional scopes it may be needed even if consent was given for example).
Question 2 - You should redirect immediately, whether consent is needed or not is unclear, but the user will either have to login, or just redirected if they have a cookie and consent is also based on their circumstances.
I'll consent (no pun intended) that we can improve this diagram and make it easier to understand. I would suggest implementing a simple scenario first and seeing how it work before moving on to the more advanced scenario (by simple I mean every time a user need to log in as if it was their first time).
One of the steps to authorize our application to access our DocuSign account requires a human to navigate to the oauth service (https://account-d.docusign.com/oauth/auth?response_type=code&scope=signature%20impersonation&client_id=...) then login to the account, and grant it access.
I've seen some references throughout the developer portal about this being something that will need done multiple times, and I've also seen it written on the same site that it only needs to be done once (the site is actually fraught with contradicting information).
Does anyone know if this step will need to be done more than once? It makes sense to me that it should NOT.
Much appreciated!
Chris
You are referring to https://docs.docusign.com/esign/guide/authentication/oa2_auth_code.html and it is a correct place for documentation for DocuSign. Now with above flow, you get two types of tokens i.e AccessToken and Refresh Token. If Access Token expires then you can use refresh token to get new set of access and refresh token and it does not need any consent from the user or a human action, it can be done using DocuSign OAUTH API from backend. But if the response to the refresh operation is an error, or if the new access token’s expires_in value is less than your threshold, you will need to repeat the initial authentication flow. So you need to do proper exception/error handling before taking user back to the consent/OAuth login page.
I am using passport-facebook to obtain an access token. According to here
https://developers.facebook.com/docs/marketing-apis#access-token
under "Get Access Token", I should be getting a 60 day long-lived token. This is the case if the scope is only ads_read. However, when I add additional scopes of manage_pages and read_insights, there is no expiration when I check via the Graph API.
This seems to be a bit contradictory to me. My theory is based on the getting an API key with ads_read permission manually from the below tool.
https://developers.facebook.com/apps//marketing-api/tools/
Using this tool and debugging it via the Graph API, I see one difference in that it the manually generated access token has the "Page" row under it, indicating that it is a page access token (to my own pages). Since it is a PAT, it will never expire, as expected.
My passport-facebook generated access token has the ads_read, manage_pages, read_insights permission as well and the expiration says "Never Expires". However, it does not have the Page row on it. Does that mean I can still use it forever to query the ads insights API?
This is my attempt at obtaining a non-expiring Marketing API access token.
Yes, if the expiration row says Never expires, you can continue to use the token for querying ads insights.
On a side note, is you generate system user access tokens, they also never expire. You can read more about it here - https://developers.facebook.com/docs/marketing-api/businessmanager/systemuser/v2.8
I'm creating a node.js application that will update playlists (owned by an account in which I have credentials) daily. According to the Spotify documentation, to add tracks to a playlist (https://developer.spotify.com/web-api/add-tracks-to-playlist/), authorization must be supplied using oauth2.
I'm struggling to find a way to do this completely server side with no redirects/etc. It seems like if I can get a refresh token, I can just use that?
I've been looking at the spotify web api node module (https://github.com/thelinmichael/spotify-web-api-node), oauth.io, and the spotify api.
Any ideas would be appreciated! There is only one account that will have to be authenticated, so it could be hard-coded at least for now.
You've picked the correct authorization flow - Authorization Code, since you need an access token that's connected to the user who owns the playlists you're updating. This of course also gives you the ability to refresh the token whenever you need to. (The expiration time is one hour, but you don't need to refresh the access token until your application actually needs to use it.)
As a sidenote, the Client Credentials flow is meant for server to server communication that doesn't require a user's permission, e.g. to search, read a playlist, or retrieve new releases. The Implicit Grant flow is meant to be used in frontends, and doesn't allow you to refresh the token.
I'm struggling to find a way to do this completely server side with no redirects/etc. It seems like if I can get a refresh token, I can just use that?
Once you have the refresh token you can continue to use it to retrieve new access tokens, which can be done without any user interaction. You need to do some preparation work to retrieve the refresh token though.
Following the steps describing the Authorization Code flow, you first need to direct the playlist's owner to a URL on Spotify's account server.
The documentation contains the following example URL:
GET https://accounts.spotify.com/authorize/?client_id=5fe01282e44241328a84e7c5cc169165&response_type=code&redirect_uri=https%3A%2F%2Fexample.com%2Fcallback&scope=user-read-private%20user-read-email&state=34fFs29kd09
Simply replace the client_id and redirect_uri with your application's information. Also modify the scope parameter to match the scopes you need, which from my understanding of your use case is playlist-read-private,playlist-modify-private,playlist-read-collaborative since you want to be able to read and modify all of the user's playlists. Supplying state is not required.
Using spotify-web-api-node you can generate this URL using the createAuthorizeURL method, but since you're only doing this once it's unnecessary to write code for it.
Instead, simply open the URL in your browser.
If done successfully, you'll be taken through a little login dance where your application asks for your permission to read and modify your playlists. When this is completed, Spotify's account service will redirect the browser to your redirect_uri URL with a code query parameter included as described in step 3 in the Authorization Guide.
However, since you're only doing this once, it would be enough to start a webserver on your own machine, set your application's redirect_uri to your localhost, and complete the login flow. Have a look at web-api-auth-examples for a ready-made node.js application that fires up an express server and reads the authorization code.
Once you've got the code, you can trade it for an access token using cURL as it's done in step #4 in the Authorization Guide, or use the code in the web-api-auth-examples repository.
Finally, with the tokens retrieved (step #5), you can start to use the Web API with the access token, and get a new one when it expires using the request in step #7.
spotify-web-api-node has a helper method to refresh the token. Search the main documentation for the refreshAccessToken method.
This use case is slightly mentioned in the FAQ section of the Authorization Guide.
As you said, you need to obtain a refresh token using the authorization code flow. For that you will need to carry out the OAuth process using your user account, the client_id of the app you have registered, and the scopes you need (it will vary depending on whether the playlist is private or public). Then, take the refresh token you have obtained and the client secret key of your app, and you can obtain access tokens without the need of the login form.
This related StackOverflow question might help too Spotify automated playlist management with PHP back-end and rate limits
I'm currently using my own Instagram account (not that of my users) to get an access_token, and thus I don't need to create an explicit server-side authentication flow for myself to get the code. I can then use the code programmatically to get an access_token without any human interaction.
My question is, for the purposes of an app that only requires the owner's code to get an access_token, does Instagram let you reuse the same code so that you don't have to keep manually entering a new one?
Thanks :)
If you are only using a single account, there is currently no need to request new access tokens repeatedly. You should be authenticating one time, and storing that access token to use with calls to the API endpoints.
Instagram access tokens currently have no set expiration, however may expire at any time in the future. So you may reuse the token indefinitely (for now), but build the system to be prepared to request a new token in the event that the stored token expires.
Per http://instagram.com/developer/authentication/:
Note that we do not include an expiry time. Our access_tokens have no
explicit expiry, though your app should handle the case that either
the user revokes access or we expire the token after some period of
time. In this case, your response’s meta will contain an
“error_type=OAuthAccessTokenError”. In other words: do do not assume
your access_token is valid forever.