ユーザーアクセストークンが取得できない[400]
ネイティブアプリ(Swift)上でスマレジのAPIにアクセスしていますが、ユーザーアクセストークンの取得に失敗します。
環境
・プライベートアプリとして登録
・ネイティブアプリ(iOS, Swift)
・開発環境を想定
実行内容
(1)アプリ上でログイン画面にリダイレクトし、ログイン情報を入力
リダイレクト先:https://id.smaregi.dev/authorize?response_type=code&client_id={クライアントID}&scope=openid
ログイン情報:自身のスマレジディベロッパーズアカウントでログイン
※{クライアントID}には、スマレジディベロッパーズサイトの当該アプリ>環境設定>開発環境にあるクライアントIDを使用しています。
※スマレジアカウント(通常の契約ID)とスマレジディベロッパーズアカウント(sb_から始まる契約ID)は、同じメールアドレス、同じパスワードでそれぞれ存在しています。この時どちらのアカウントでログインされているのかは確認できませんでした。ちなみに、スマレジアカウント(通常の契約ID)は当該アプリにおいてアクティベート済みです。
結果:code=クエリに格納された認可コードを取得した。
(2)ユーザーアクセストークンの取得APIにアクセス
アクセス先:https://id.smaregi.dev/authorize/token
リクエストヘッダ:
・Authorization → Basic {Base64文字列}
・Content-Type → application/x-www-form-urlencoded
リクエストボディ:grant_type=authorization_code&code={取得した認可コード}
※クライアントシークレットがないため、{Base64文字列}には「クライアントID:」とコロンで終わる文字列をBase64エンコードしたものを使用しています。
結果:レスポンス400を受信し、トークンを取得できなかった。
以上について、トークンの取得に失敗する理由として考えられる候補をご教示いただけないでしょうか。
ベストアンサー
-
認可コード取得時のstateは推奨項目のため必須ではないのですが、可能であれば入力のうえ取得をお試しください。
また、過去に「code_challenge」の処理方法によりエラーが発生している事例がありました。
SHA256ハッシュを16進数表記に変換せずにbase64エンコードする必要があるのですが、上記はそれを処理するためのツールです。
こちらはOAuthという規格に準拠したツールであり、スマレジの認可基盤もその規格に沿ったものになりますので、
こちらのツールを使って「code_challenge」の値を生成いただくことで、エラーが解消するかどうかご確認ください。
※過去のスレッド
上記ご確認いただいても解決に至らない場合、400エラーになったときのレスポンス内容をご教示ください。
答え
@s_mtd
ネイティブアプリにてユーザーアクセストークンが取得できないご状況ですね。
ネイティブアプリの場合、認可コード取得の際の「code_challenge」と「code_challenge_method」が必須になりますが、こちらが指定されていない可能性が考えられます。
「code_challenge」と「code_challenge_method」を指定して、認可コードの取得から改めて行っていただけますでしょうか。
また、認可コードの取得の際に「code_challenge」を指定すると、
ユーザーアクセストークンの取得の際のリクエストボディに「code_verifier」も必須になります。
◎基本仕様書のログイン部分をご確認ください。
https://developers.smaregi.dev/apidoc/common/#/paths/~1dummy/get
ご回答ありがとうございます。
「code_challenge」と「code_challenge_method」を設定しましたが、結果は変わらず400でした。
・code_verifierには、ランダムな文字列を動的に生成して設定しています。(64文字、[A-Z],[0-9]のみで構成)
・code_challengeには、以下の手順で取得した文字列を設定しています。
1 code_verifierのSHA256ハッシュ値(=ダイジェスト値)を取得
2 上記のハッシュ値をBase64でエンコード
3 上記のエンコードした値をURLセーフに変換(「+」→「-」、「/」→「_」、「=」を削除)
・code_challenge_methodには直接「S256」を指定
実行内容
(1)アプリ上でログイン画面にリダイレクトし、ログイン情報を入力
リダイレクト先:https://id.smaregi.dev/authorize?response_type=code&client_id={クライアントID}&scope=openid&code_challenge={Base64URL文字列}&code_challenge_method=S256
(2)ユーザーアクセストークンの取得APIにアクセス
リクエストボディ:grant_type=authorization_code&code={取得した認可コード}&code_verifier={ランダムな文字列}
結果:レスポンス400を受信し、トークンを取得できなかった。
この他、認可コード取得時にstateを指定していませんが、これは必須でしょうか?
色々試してみていますが、400から抜け出せないので他にも可能性があればご教示願います。
お忙しいところ恐縮ですが、よろしくお願いいたします。
ご回答ありがとうございました。本件解決いたしました。
①ご教示いただいたツールでcode_challengeを生成し、②stateも設定しました。
両方に問題があったようで、どちらも対応することで無事POSデータの取得ができました。
①ツールで生成したcode_challengeと、もともとコードで生成していたcode_challengeが異なっていましたので、ご共有いただいた事例と同様の事象が発生していたと思われます。
②クエリにcodeが含まれていた時点でそれを認可コードと断定して取得していましたが、今まで取得していたcodeは正式に発行された認可コードではなかったようです。おそらくリダイレクト中の過程で使用されていたクエリを誤認識(早とちり)して取得していました。stateの一致を確認することで、対象のクエリが正式に発行された認可コードであると確認できます。結果、今回は構造的にstateが必要ということでした。
この度はありがとうございました。今後ともよろしくお願いいたします。