SpotifyWebAPIの認可フローをまとめてみた

以前、
SpotifyAPIでクイックプレイリスト作成ツールを作ってみた

で簡単にSpotifyWebAPIの使い方を紹介しましたが、今回リニューアルに向けてSpotifyWebAPIの認可フローをまとめてみました!!!
(ちょい長めなので、飽きないように絵文字多めでうざいかもしれませんw)

公式ドキュメント:https://developer.spotify.com/documentation/general/guides/authorization-guide/
のほとんど和訳みたいな感じですが…😅

Spotify APIを使うフローは3つあります。

  • Authorization Code
    リフレッシュ可能なユーザ認可。エンドユーザ情報にアクセスするAPIエンドポイント(プレイリスト作成も可能)もアクセスできる。
  • Implicit Grant Flow
    一時的なユーザ認可。JavaScriptを使いエンドユーザブラウザで実行される。サーバ側のコードを使用しないアプリ向け、refresh_tokenの提供なし。
  • Client Credentials Flow
    リフレッシュ可能なアプリ認可。サーバ間認証で、エンドユーザ情報にアクセスにしないAPIエンドポイントのみにアクセスできる。

今回はPHPを使う想定で、
Authorization Codeについての詳細を紹介します!!!

Spotify Web APIでつかうURLは2つあります。

  • https://accounts.spotify.com
    Spotifyアカウント(ユーザ認可)へのAPI用👦
  • https://api.spotify.com/
    それ以外(アーティスト・プレイリスト・トラックなど)のSpotifyサービスへのAPI用🎧

ざっくりとした流れは、以下stepになります。

1.認可リクエスト🙇‍♂️

GET https://accounts.spotify.com/authorize

<クエリパラメータ>

クエリパラメータ
client_id SpotifyのDeveloperにあるやつ(必須)
response_type "code"をセットする。(必須)
redirect_uri SpotifyのDeveloperより設定したRedirect URIsと同じものにする(必須)
status ランダム文字列をセットをすると、リクエストとレスポンスが妥当かの確認できて、クロスサイトリクエストフォージェリなどの攻撃に対する保護ができる。[RFC-6749](推奨)
scope デフォルトはSpotifyデスクトップやweb、モバイルプレーヤで通常表示される情報のみアクセスを許可する設定になる。
詳細は、Authorization Scopes
show_dialog [default:false] falseの場合、一度承認すると自動でredirect_uriにリダイレクトする。trueの場合、既に承認していてもredirect_uriにリダイレクトされず、再度認証を

具体例

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

をすると、

  1. クエリパラメータ指定のscopeについて、エンドユーザに認可していいか尋ねる
    • エンドユーザがログインしていない場合:ログインを求める
    • エンドユーザがログイン済の場合:スコープについてのデータアクセスへの許可/拒否かを聞く
  2. エンドユーザはredirect_uriにリダイレクトされる
    • エンドユーザが認可を許可した場合🙆‍♂️:
      codeとstate(リクエストで指定してた時のみ)がクエリパラメータとして返ってくる。
    • code:access_tokenと交換できる認証コード
      例)https://example.com/callback?code=NApCCg..BkWtQ&state=profile%2Factivity

    • エンドユーザが認可を拒否した場合🙅‍♂️:
      errorとstate(リクエストで指定してた時のみ)
    • error:認可失敗の理由
      例)https://example.com/callback?error=access_denied&state=STATE

2.refresh_tokenとaccess_tokenをリクエストする🔑

認可コード(code=xxxx)を受け取った後、認可コードとaccess_tokenを交換するためにリクエストする

POST https://accounts.spotify.com/api/token

<リクエストボディパラメータ>
OAuth 2.0で定義されたapplication/x-www-form-urlencodedでエンコードされたパラメータを含ませる必要がある。

リクエストボディパラメータ
grant_type "authorization_code"をセットする(必須)
code 1で取得したcodeをセットする(必須)
redirect_uri 妥当性の検証に使用されるだけで、リダイレクトはしない。1でリクエストしたredirect_uriと一致する必要がある(必須)
client_idとclient_secret もしくはヘッダーパラメータにAuthorization: Basic <?php base64_encode(client_id:client_secret)>を含める(必須)

<レスポンスデータ>

レスポンスデータ
access_token 今後のSpotifyWebAPIサービスを利用するためのaccess_token
token_type "Bearer"
scope access_tokenに付与されたscope、スペース区切りのリスト文字列
expires_in access_tokenの有効な期間(秒単位)
refresh_token access_tokenが期限切れになった時、新しいaccess_tokenを得るために必要となるっぽい

3. access_tokenを使って、SpotifyWebAPIへアクセスする🎧

2で受け取ったaccess_tokenを使用(ヘッダーにセット)し、リファレンスに沿ってリクエストをするとで、ユーザに代わってSpotifyWebAPIにリクエスト/レスポンス(JSON)を受け取ることができる。

例)
curl -H "Authorization: Bearer {access_token}" https://api.spotify.com/v1/me

Web API Reference
https://developer.spotify.com/documentation/web-api/reference-beta/#endpoint-check-current-user-follows

4.access_tokenをリフレッシュする方法✨

access_tokenは、しばらくすると意図的に期限切れになります。
その後、認可コードとの交換で最初に取得したrefresh_tokenを使用して新しいaccess_tokenをもらう。

POST https://accounts.spotify.com/api/token

<リクエストボディパラメータ>
OAuth 2.0で定義されたapplication/x-www-form-urlencodedでエンコードされた、リクエストボディパラメータを含ませる。

  • grant_type:refresh_tokenをセットする(必須)
  • refresh_token:認可コード交換の時に返されたrefresh_tokenをセットする

<へッダーパラメータ>

  • Authorization:Authorization: Basic <?php base64_encode(client_id:client_secret)>(必須)

まとめ

改めて日本語でまとめてみると、ユーザ情報にもアクセスするのでセキュリティ面で考えることもできました。

  • statusをセットした方が、安全そう
  • client_secretなどの他人にバレてはやばそうな情報を使ったリクエストを送る時はOAuth 2.0で定義されたapplication/x-www-form-urlencodedでエンコードしてる
  •