Spotify API Authorization for cron job - node.js

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

Related

Spotify API: How to get access token for only myself

I'm following this tutorial to get the track list from my Discover Weekly playlist. The tutorial mentions that I need to get an OAuth token for my own account before requesting the playlist info. This is done by going to a random Console page and click on 'Get token' at the end of the page (which requires me to log into my Spotify account and approves the Console to access my account data).
However, I want to acquire this token programmatically, instead of manually clicking on 'Get token' and logging into my account every time I need this token. What I have is:
My Spotify user ID (from my Account page)
The Spotify client ID for an application I just created under Spotify for Developers
The client secret for this application
Basic knowledge of how to send GET and POST requests (using Python's requests library)
How can I get an OAuth token, or at least generate a new token each time, using some of these above
information?
It depends on what you're trying to do. If all you want is a token to query the api to lookup songs/artists/etc., then you can use the Client Credentials auth flow that doesn't require any user input. All you need to do here is exchange your client ID and secret for an access_token that you'll use in subsequent requests.
If you want access or change certain user information, you'll have to use one of the two other flows on the same spotify authorization page. You'll need to pass a list of scopes with this request, directing the user to a spotify-url-based authorization page, and be able to give it a redirect url that will handle the receiving of the access_token object once the user logs in to the spotify page.
I don't think there's a way to implement one of these flows where you need to request user scopes without having some sort of web server running to accept the redirect passed into the spotify auth url and then save the given token.
After looking at the link you posted for spotify's console pages, it looks like you can use any of those API requests to generate a token including the scopes you want. All it's doing is performing the normal authorization flow in the background, skipping the step where it returns a secret to you that your server that you can then exchange for an access_token and refresh_token. Using the spotify console pages seems like an easy quick way to get scripts or prototypes running without having to deal with setting up your own webserver.

Google API Authentication Tasks API

I want to create a Lambda function that uses the Google Tasks API to add tasks every evening at a certain time.
I am unsure of how to authenticate with my account and be able to store access tokens / credentials securely in my lambda environment variables.
As I understand it since my lambda is making a request on behalf of a user (which will always be me in this case) it seems like everything in the docs points to needing to use OAuth2.0 to authenticate which makes sense since you'd want the user's permission to make changes in their account. However since I only want to do so on my account, I wanted to know if there was a way to simply authorize my account without doing a OAuth flow which I don't believe is possible from a lambda since I won't be responding to it every time it runs.
How would I authenticate my application so I can make calls to the tasks API and be authenticated against my account?
This is surprisingly more work than I'd imagined and unfortunately google doesn't generate developer tokens which would have solved a lot of this problem.
Authorization & Consent
There are no immediate ways of authorizing your account for the app that you've created without going through the consent flow. Some cloud service providers generate a developer token for testing your app with your credentials - but google doesn't seem to have this functionality. Not for the Tasks API anyways. AdWords API talks about a developer token but I'm not sure if it's the same concept.
You won't have to re-authorize once you've given consent. This general principal applies to other OAuth using parties, unless the level of consent changes (example: the app starts asking for write permissions in addition to previously consented read) you won't get re-prompted. If permission levels change, you'll get re-prompted.
Now - the second part - how do you make one?
Google explains it in detail here - but I'll further simplify because you don't need to setup a web-server for your case, you're only doing this for yourself.
Our goal is to only to get you the initial refresh token. Once you've retrieved the refresh token, you can use that from your Lambda to retrieve a new access + refresh token whenever you're accessing the tasks API. You just need to keep the refresh token stored somewhere, so you can continuously keep on accessing the tasks API. You're just looking to get the access + refresh token.
Head over to https://console.developers.google.com and create a new application.
After the creation, click 'Enable APIs and Services' and look for Tasks API.
Proceed with creating the credentials and make sure you select you'll be calling this API from a Web Server. Selecting Browser (JavaScript) would only give you an access token and not a refresh token, because they would trust you to store the refresh token on your server, but not on a browser. An access token is time-limited to (conventionally) 60 minutes.
You should also select the User Data / Information and not the App Data / Information for the types of data you want to access. The app one is generally used for GSuite.
Set your redirect uri to be http://localhost:8080 - This is where you normally would need a web-server but we'll just redirect back to your machine and get the parameter from here. It obviously won't find a web-server but the parameter we want is in the url, we'll just copy it.
Now here comes the authentication part. Google's auth url is: https://accounts.google.com/o/oauth2/v2/auth
We will add parameters to this url
access_type=offline // so your daemon app can access it offline
response_type=code // required if you have access_type=offline
scope=https://www.googleapis.com/auth/tasks // what do you want to access to
redirect_uri=http://localhost:8080 // where would google send the code
client_id=
so the whole thing should look like https://accounts.google.com/o/oauth2/v2/auth?access_type=offline&response_type=code&scope=https://www.googleapis.com/auth/tasks&redirect_uri=http://localhost:8080&client_id=
Go to this URL and you should get prompted for consent.
Consent to it and google should redirect you to http://localhost:8080/?code= We'll need that code. That needs to be sent to google to get an access + refresh token.
Code exchange: Make a post request to Google. You can use PostMan. Again normally all of this would be automatically handled by a webserver (detect code parameter, make post request etc..) - but we just need the refresh token here, so we can stick that into our Lambda app.
POST to:
https://www.googleapis.com/oauth2/v4/token
with parameters:
code=<the code you've retrieved>
client_id=<your_client_id>&
client_secret=<your_client_secret>&
redirect_uri=http://localhost:8080&
grant_type=authorization_code
Google should return you the access token and the refresh token. From this point on you need to save the refresh token into your Lambda app - and if it's running on a scheduled job on every bootup:
Read the refresh token
Call Google for a new refresh token + access token
Save the new refresh token.
Use the access token to access your Tasks API.

Spotify: Permanent auth with authorization code workflow

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.

how to secure azure mobile service / html - javascript

When I call an oauth provider like gmail and I get the token back, how can I make sure that all future calls I make are from that same client that did the authentication? that is, is there some kind of security token I should pass pack? Do I pass that token back everytime?
For example, if I have a simple data table used for a guest book with first,last,birthdate,id. How can I make sure that the user who "owns" that record is the only one who can update it. Also, how can I make sure that the only person who can see their own birthday is the person who auth'd in.
sorry for the confusing question, I'm having trouble understanding how azure mobile services (form an html client) is going to be secure in any way.
I recently tried to figure this out as well, and here's how I understand it (with maybe a little too much detail), using the canonical ToDoList application with server authentication enabled for Google:
When you outsource authentication to Google in this case, you're doing a standard OAuth 2.0 authorization code grant flow. You register your app with Google, get a client ID and secret, which you then register with AMS for your app. Fast forwarding to when you click "log in" on your HTML ToDoList app: AMS requests an authorization code on your app's behalf by providing info about it (client ID and secret), which ultimately results in a account chooser/login screen for Google. After you select the account and log in successfully, Google redirects to your AMS app's URL with the authorization code appended as a query string parameter. AMS then redeems this authorization code for an access token from Google on your application's behalf, creates a new user object (shown below), and returns this to your app:
"userId":"Google:11223344556677889900"
"authenticationToken":"eyJhbGciOiJb ... GjNzw"
These properties are returned after the Login function is called, wrapped in a User object. The authenticationToken can be used to make authenticated calls to AMS by appending it in the X-ZUMO-AUTH header of the request, at least until it expires.
In terms of security, all of the above happens under HTTPS, the token applies only to the currently signed-in user, and the token expires at a predetermined time (I don't know how long).
Addressing your theoretical example, if your table's permissions has been configured to only allow authenticated users, you can further lock things down by writing logic to store and check the userId property when displaying a birthday. See the reference docs for the User object for more info.

using facebook client flow to authnticate and login on app/site

Other then the fact that when using facebook's client-flow you get an access token right away, and when using the server-flow you first get an authorization code that you have to exchange for an access token, What is the difference between the two flows and when should I use each of them ?
more specifically can I use client-flow and still be able to securely log a user into my application/site?
At first glance I though that I could take the access_token and id I got on the client (via client-flow), send them to my server and then if a graph api call for that ID and token does not break I can assume I am dealing with this user and log him into my site based on his FB ID.
On second thought it looks to me that If I don't follow the server-flow there is no way to securely use the client id & access_token to log the user into my application/site.
The reason I say this is that another (hacker) app owner that "shares" a user with my app. might take the access_token and and ID he (illegitimately) got for user on his authorization flow, and fake a call to my site with this data causing me to log him in as if he was this user.
Am I missing something here?
Should this not be written in big red letters on the first paragraph of https://developers.facebook.com/docs/authentication/ ?
Oauth 2 (http://oauth.net/2/) is what Facebook uses. For the most part it is the most secure interface available. If there was a way for a user to take an access token for one app and then use it in another app, then oauth2 will need to be patched (or Facebook oauth2 will need to be patched).
If you think you found a way to hack it, then you should get your $500.00 prize from http://www.facebook.com/whitehat/bounty

Resources