"invalid_grant" エラーの理解とトラブルシューティングについて探究する: OIDC の承認を探求する
OpenID Connect(OIDC)の承認の基本を学び、"invalid_grant" エラーのトラブルシューティング方法を理解します。
背景
私たちのコミュニティでは、ユーザーからの繰り返しの質問をよく耳にします: Logto の "invalid_grant" エラーって何? 例えば #503
これは一部のユーザーが Logto を自分たちのアプリケーションに統合する際の一般的な問題で、このエラーの背後にある理由は場合によります。そして、提供される文脈が限られているため、説明するのが難しいことがあります。そのため、正確な OIDC の概念を理解し、問題のトラブルシューティング方法を学ぶことがすべての人にとって必要不可欠です。
では OIDC の承認について基本的な知識を深めていきましょう。
OIDC 承認の解説
私たちが以前のブログ記事で紹介したように、OpenID Connect (OIDC)は OAuth 2.0の上に構築されたプロトコルです。
OIDC または OAuth2 の状況下では、承認はリソースオーナー(通常はユーザー)からクライアントアプリケーションに対して許可された一連の許可を指します。承認はクライアントアプリケーションがユーザーの身元情報やその他の保護されたリソースにアクセスするために必要不可欠です。OIDC には、アプリケーションがアクセストークンを取得する方法とそのシナリオごとに適したいくつかの承認タイプが定義されています。
以下に OIDC の承認をより理解しやすくするための一つの例えをご紹介します。
異なる国を旅行するとき、各国が入国のためのビザスタンプを要求することを想像してみてください。このシナリオでは、あなたのパスポートはあなたのユーザーアカウントとして機能し、個人情報を含んでいます。OIDC の承認は、あなたが国に入るためのビザを申請する方法のようなものです。ビザが発行されると、その国に入るための "トークン" を事実上取得することになります。
同様に、アプリケーションを使用する際、承認リクエストは、認証サーバーによるアクセスの許可を求める行為を指します。認証サーバーはあなたの身元を確認し、アプリケーションにサインインするための "ビザ"(アクセストークン)を発行します。
一般的に使用される OIDC 承認タイプ:
- 認証コード承認: これは OIDC で最も一般的に使用される承認タイプです。これには 、ユーザーを認証サーバーにリダイレクトし、認証コードを取得し、アプリケーションに戻ってコードをアクセストークンと交換するという一連のプロセスが含まれます。これは、外国に入国する前に大使館からビザを申請する標準的なプロセスと考えることができます。
- リフレッシュトークン承認: OIDC では、この承認タイプを使用してクライアントアプリケーションが以前に発行されたリフレッシュトークンを使用して新たなアクセストークンを取得することができます。これは一般的に、ユーザーに資格情報を再入力させることなくユーザーセッションを延長するために使用されます。あなたのビザがあなたがもう一度税関を通らずに外国での滞在を延長できる魔法のカードを持っているように想像してみてください。
- 含蔵承認: この承認形式は、レガシーなブラウザベースのアプリケーションを使用したり、認証コード承認よりもセキュリティが低いです。これはクライアントアプリケーションに直接アクセストークンを返します。これは "ビザオンアライバル" のように動作します。事前のビザ申請は必要ありません。
- クライアント認証承認: サーバー間通信に適しており、この承認タイプを使用すると、クライアントアプリケーションはその資格情報(クライアント ID とクライアント秘密)を使用して認証サーバーと直接認証することができます。これは特別なエージェントがビザ申請プロセスを経ずに特別な仕事バッジを提示して国に入ることに似ています。
承認オブジェクトモデル:
Logto では、承認はオブジェクトエンティティとしてデータベースに保持され、ユーザーアカウント ID、アプリケーション ID、関連する OIDC リソースとスコープ、有効期限などの情報を含んでいます。それぞれのリフレッシュトークンとアクセストークンは特定の承認オブジェクトに関連付けられています。
承認リクエスト:
認証サーバーに対する API を通じて行われる HTTP リクエスト。クライアントアプリケーションは、新しい承認(例えば、サインインしてリフレッシュトークンとアクセストークンを取得する)、承認の詳細を更新(例えば、リフレッシュトークンを新しいアクセストークンと交換する)、或いは承認を取り消す(例えば、ログインユーザーに発行された全てのトークンを取り消し、そのアクセスを終了する)といった様々な目的で OIDC トークンエンドポイントへの承認リクエストを送信することができます。
典型的な認証コード承認リクエストは以下のようになります:
"invalid_grant" エラーの理解
OIDC で invalid_grant
エラーが発生すると、一般的には承認タイプまたは承認リクエストと関連するデータが無効であるか、サポートされていないことを示しています。以下に、このエラーの背後にある一般的な理由をいくつか挙げてみます:
- 不正確な承認タイプ: アプリケーションで誤った承認タイプを使用すると、
invalid_grant
エラーが起こる可能性があります。Logto SDK を活用して、適切な承認タイプを使用していることを確認します。 - リダイレクト URI の不一致: トークンと認証コードを交換する際、リクエストで使用されるリダイレクト URI は、初めての認証リクエストで使用されたものと一致する必要があります。一致しないと
invalid_grant
エラーが発生してしまう可能性があります。 - 期限切れあるいは使用済みの認証コード: 認証コードのサインインフローでは、認証コードは有限の寿命を有し、トークンを取得するために一度使用すると "使用済み" とマークされます。期限切れあるいは使用済みのコードをアクセストークンと交換しようとすると、
invalid_grant
エラーが発生します。 - 期限切れあるいは手入れが行われたリフレッシュトークン: リフレッシュトークンをアクセストークンと交換する際、
invalid_grant
エラーはリフレッシュトークンがすでに期限切れである場合に発生します。さらに、 Logto ではデフォルトで リフレッシュトークンのローテーション を有効にしています。同じリフレッシュトークンで2回目のトークンエンドポイントへのリクエストは、使用済みの "ローテーション" リフレッシュトークンを使用するとみなされ、拒否されます。 - 必須データやリクエストヘッダーが欠落: 承認リクエストを作成する際は、指定された承認タイプのための必要なパラメーターとリクエストヘッダーが提供されている必要があります。例えば、すべての承認リクエストではクライアント ID が提供されている必要があり、クライアント ID とクライアント秘密がクライアント認証承認のために提供されている必要があります。このリスクも Logto SDK を活用することで軽減することができます。
- その他の理由: このエラーは、クライアント認証の不一致、承認が期限切れまたは見つからない、リフレッシュトークンが見つからない等、その他の理由により発生することもあります。
トラブルシューティング
"invalid_grant" エラーを効果的に解決するためのいくつかのヒント:
- 常に Logto のクライアント SDK を使用して、 Logto をアプリケーションに統合し、承認リクエストが適切なエンドポイントと正しいデータを使って作られるようにします。
- あなたのアプリの認証情報とリダイレクト URIs が Admin Console の設定と一致していることを確認します。
- 冗長なリクエストの送信を避ける、特に React や Vue のような SPA では、依存関係の変化によりページコンポーネントが再レンダリングされるこ とがあります。コードやリフレッシュトークンをアクセストークンと交換するために使用される関数が同じリクエストパラメーターで複数回起動されないようにします。 これは一部のユーザーがよく犯す間違いです。通常、あなたのデバッグコンソールで複数の "トークン" リクエストが見られ、最初の一つは成功していますがそれに続くものはすべて失敗している場合、それらのリクエストパラメーターをチェックして "コード" や "リフレッシュトークン" を同じものを使用しているかどうかを見ます。同じコードやリフレッシュトークンは承認リクエストで一度だけ使用することができることを覚えておいてください。
- 有効期限をチェックする。例えば、あなたのリフレッシュトークンが期限切れ(デフォルトでは14日間)で
invalid_grant
エラーを受け取った場合、再度ユーザーサインインフローを初期化することにより適切に処理します。もし Logto SDK を使用しているなら、signIn()
関数を再度呼び出してユーザーをサインインページにリダイレクトすることができます。 - 監査ログを監視する。Admin Console → 監査ログに移動し、インシデントと関連するエラーログを検索し、詳細なエラースタックトレースを確認します。通常、
invalid_grant
エラーの背後には、 "Grant not found" や "Refresh token expired" のような具体的な理由がスタックトレースにあります。
締めくくりとして
invalid_grant
エラーは初心者には難しく、混乱を招くことがありますが、 OIDC の承認についての明確な理解と注意深さを持っていれば、あなた自身で問題を特定し、解決することができます。 Discord や GitHub のディスカッションに参加し、このブログが混乱を解消し、対処している問題を特定するのに役立ったかどうかお知らせください。Logto の開発チームはいつでもあなたを支援するために準備しています。
一緒に、あなたの大切なアプリケーションのためのシームレスで安全な認証体験を構築しましょう。