web-dev-qa-db-ja.com

セキュアなREST APIおよびシングルページアプリを使用して、外部OAuth 2認証コードを使用する

単一ページのJSアプリとOAuth APIの両方がある場合にREST 2 Authorization Codeフローを実装する方法を理解しようとしています。目的は、 RESTプロバイダーに認証をオフロードすることによるOAuth APIへのアクセス。

現在、私のフローは次のようになります。

1)

+--------------------+               +----------------+
| JS Single Page App | - redirect -> | OAuth Provider | - user enters credentials
+--------------------+               +----------------+

2)

+----------------+                                   +----------+
| OAuth Provider | - redirect with temporary code -> | REST API |
+----------------+                                   +----------+

3)

+----------+                                      +----------------+
| REST API | - request access token using code -> | OAuth Provider |
+----------+ <- return access token ------------- +----------------+

私は今どうすればいい?私の現在の理解では、JSシングルページアプリを再度ロードするページへのアクセストークンを受け取ったら、ユーザーをリダイレクトする必要があります。しかし、アクセストークンをシングルページアプリと共有し、その存在を使用して、私のREST APIにヒットするすべてのリクエストを認証する必要があります。または、別の識別子を作成してサーバー側を維持する方が良いでしょう。 new-identifier->access_token間のマッピングどちらの方法でクライアントに識別子を転送する最良の方法は何ですか?セッションを維持せず、リダイレクトされたページのURLバーに識別子が表示されないようにします。私は現在、単一ページアプリが読み取ってから消去する一時的なCookieを作成することを考えることができますが、どういうわけか少し不格好な感じがします。

12
Anvar Karimson

まず、非常に明確にするために、 OAuth 2は認証プロトコルではありません。 のIDを知りたい場合ユーザー、この問題を解決するために設計された他のプロトコルがあります OpenID Connect など。保護されたリソースへのアクセスをauthorizingする目的でOAuth 2を使用する場合は、読み続けてください。

直接的な質問に答えるには、 Authorization Code Grant フローを使用しているようです:

 +----------+
 | Resource |
 |   Owner  |
 |          |
 +----------+
      ^
      |
     (B)
 +----|-----+          Client Identifier      +---------------+
 |         -+----(A)-- & Redirection URI ---->|               |
 |  User-   |                                 | Authorization |
 |  Agent  -+----(B)-- User authenticates --->|     Server    |
 |          |                                 |               |
 |         -+----(C)-- Authorization Code ---<|               |
 +-|----|---+                                 +---------------+
   |    |                                         ^      v
  (A)  (C)                                        |      |
   |    |                                         |      |
   ^    v                                         |      |
 +---------+                                      |      |
 |         |>---(D)-- Authorization Code ---------'      |
 |  Client |          & Redirection URI                  |
 |         |                                             |
 |         |<---(E)----- Access Token -------------------'
 +---------+       (w/ Optional Refresh Token)

このフローは機密クライアント向けに最適化されています:エンドユーザーや、アクセスを試みている可能性のあるサードパーティからの秘密を保持できるクライアント保護されたリソース。クライアントのブラウザーで実行されているjavascriptアプリケーションの場合、秘密を保持することはできません。すべてのコードがそこにあり、ブラウザーのデバッガーで単純にそれに侵入してすべての秘密を明らかにします。

代わりに、 Implicit Grantフロー があり、特にあなたのようなクライアント向けに最適化されています。 RFCは、このフローを使用することを目的としたクライアントの例として、ブラウザーで実行されているJavaScriptを使用しています。

 +----------+
 | Resource |
 |  Owner   |
 |          |
 +----------+
      ^
      |
     (B)
 +----|-----+          Client Identifier     +---------------+
 |         -+----(A)-- & Redirection URI --->|               |
 |  User-   |                                | Authorization |
 |  Agent  -|----(B)-- User authenticates -->|     Server    |
 |          |                                |               |
 |          |<---(C)--- Redirection URI ----<|               |
 |          |          with Access Token     +---------------+
 |          |            in Fragment
 |          |                                +---------------+
 |          |----(D)--- Redirection URI ---->|   Web-Hosted  |
 |          |          without Fragment      |     Client    |
 |          |                                |    Resource   |
 |     (F)  |<---(E)------- Script ---------<|               |
 |          |                                +---------------+
 +-|--------+
   |    |
  (A)  (G) Access Token
   |    |
   ^    v
 +---------+
 |         |
 |  Client |
 |         |
 +---------+

このフローがどのように機能するかの詳細については、RFCを読む必要がありますが、フローの一般的な概念は、認証コードの使用を不要にすることです。代わりに、クライアントには直接アクセスコードが与えられます。

これには、コードが有効でなくなったときにクライアントがリソースを再度要求する必要があるという欠点があります。秘密を保持できないクライアントの承認付与を「記憶」する方法はありません。これは、OAuth作成者がこの種のクライアントのセキュリティを向上させるために意図的に行った決定です。

12
Paul Turner

私はあなたのシナリオを正しく理解しているかどうかわかりません。 OAuthを使用してJavaScriptクライアントからのRESTful API呼び出しを保護するだけの場合、暗黙の付与タイプに関するTragedianの回答は完全に正しいです。これは、UIとデータの明確な分離があることを意味します。

  • UI(つまり、JSシングルページアプリケーション)は、認証/承認のフォームなしでロードできます。
  • データ(RESTful API呼び出し)は、認証サーバーによって認証された後のアクセストークンで保護されます。

別のシナリオがある場合は、より正確に説明してください。 OAuthにも依存し、機密データを保存できるアプリケーションのバックエンド部分の一部について言及します。これは、JSシングルページアプリの他に、異なるクライアントがあることを意味します。 (OAuth言語で)...

1
pfust75