Skip to content

Instantly share code, notes, and snippets.

@hughrawlinson
Last active September 21, 2023 20:53
Show Gist options
  • Save hughrawlinson/358afa57a04c8c0f1ce4f1fd86604a73 to your computer and use it in GitHub Desktop.
Save hughrawlinson/358afa57a04c8c0f1ce4f1fd86604a73 to your computer and use it in GitHub Desktop.

Spotify OAuth Scripts

Requirements

  • jq
  • Your own Spotify Client ID and Client Secret

Creds Storage

Store your Client ID in ~/.config/spotify_client_creds.json. It should look like:

{
  "id": "",
  "secret": ""
}

Installation

Add client_creds and authorization_code to your path, however you like. I like storing them in ~/.local/bin and adding that directory to my path. Store your credentials on your filesystem as shown above. You have full disk encryption turned on, right? If you want to do user authentication, you should make sure that your app has whitelisted http://localhost:8082/ as a redirect URI.

Usage

client_creds for client-only credentials authorization_code for user login credentials

Contributing

Found a bug? Well volunteered! I look forward to reviewing your patch.

#!/bin/bash
# spotify_platform_oauth.sh
#
# A script to quickly and easily generate Spotify oauth tokens given a client
# id, secret, and scope. Will authenticate a user via the browser.
# The app must have "http://localhost:8082/' as a redirect_uri
# spotify_client_creds.json should contain a spotify client id and secret pair
# encoded as a json object with properties `id` and `secret`
# TODO grab client id and secret first from args, if not, then this file, if not, exit with an error
client_id=$(jq -r '.id' ~/.config/spotify_client_creds.json)
client_secret=$(jq -r '.secret' ~/.config/spotify_client_creds.json)
port=8082
redirect_uri=http%3A%2F%2Flocalhost%3A$port%2F
auth_endpoint=https://accounts.spotify.com/authorize/?response_type=code\&client_id=$client_id\&redirect_uri=$redirect_uri
# TODO return cached access token if scopes match and it hasn't expired
# TODO get scopes from args
scopes="playlist-read-private"
if [[ ! -z $scopes ]]
then
encoded_scopes=$(echo $scopes| tr ' ' '%' | sed s/%/%20/g)
# If scopes exists, then append them to auth_endpoint
auth_endpoint=$auth_endpoint\&scope=$encoded_scopes
fi
# TODO if refresh_token exists and is valid for scopes, use refresh flow
open $auth_endpoint
# User is now authenticating on accounts.spotify.com...
# Now the user gets redirected to our endpoint
# Grab token and close browser window
response=$(echo "HTTP/1.1 200 OK\nAccess-Control-Allow-Origin:*\nContent-Length:65\n\n<html><script>open(location, '_self').close();</script></html>\n" | nc -l -c $port)
code=$(echo "$response" | grep GET | cut -d' ' -f 2 | cut -d'=' -f 2)
response=$(curl -s https://accounts.spotify.com/api/token \
-H "Content-Type:application/x-www-form-urlencoded" \
-H "Authorization: Basic $(echo -n $client_id:$client_secret | base64)" \
-d "grant_type=authorization_code&code=$code&redirect_uri=http%3A%2F%2Flocalhost%3A$port%2F")
# Useful values are
# jq -r '.expires_in'
# may not exist
# jq -r '.scope'
# I'm not actually using this yet, best not store it
# echo $response | jq -r '.refresh_token' > /var/tmp/spotify_refresh_token
# TODO cache access token
echo $response | jq -r '.access_token'
#!/bin/bash
client_id=$(jq -r '.id' ~/.config/spotify_client_creds.json)
client_secret=$(jq -r '.secret' ~/.config/spotify_client_creds.json)
encoded_creds="$(echo -n "$client_id:$client_secret" | base64 -w 0)"
curl -s "https://accounts.spotify.com/api/token" -d "grant_type=client_credentials" -H "Authorization: Basic $encoded_creds" \
| jq -r .access_token
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment