OAuth は認証のためのオープン ネットワーク標準であり、現在のバージョンはバージョン 2.0 です。
この記事は、OAuth 2.0 の設計思想と運用プロセスについて簡潔で一般的な説明を提供します。主な参考資料は RFC 6749 です。
OAuth がどこに適用されるかを理解するために、仮説的な例を示します。
ユーザーがGoogleに保存した写真を印刷できる「クラウド印刷」Webサイトがあります。このサービスを利用するには、Google に保存されている写真を「クラウド プリント」に読み込ませる必要があります。
問題は、Google がユーザーの承認を得た場合にのみ、「クラウド プリント」にこれらの写真の読み取りを許可することです。では、「クラウドプリント」はどのようにしてユーザーの承認を得ているのでしょうか?
従来の方法では、ユーザーは自分の Google ユーザー名とパスワードを「クラウド プリント」に伝え、後者はユーザーの写真を読み取ることができます。このアプローチにはいくつかの重大な欠点があります。
リーリーOAuth は上記の問題を解決するために生まれました。
OAuth 2.0 について詳しく説明する前に、いくつかの特別な用語を理解する必要があります。これらは、以下の説明、特にいくつかの図を理解するために非常に重要です。
リーリー上記の用語を理解すると、OAuth の機能は、「クライアント」が安全かつ制御可能な方法で「ユーザー」の承認を取得し、「サービス プロバイダー」と対話できるようにすることであることを理解するのは難しくありません。
OAuth は、「クライアント」と「サービスプロバイダー」の間に認可レイヤーを設定します。 「クライアント」は「サービスプロバイダー」に直接ログインすることはできませんが、ユーザーとクライアントを区別するために認可層にのみログインできます。 「クライアント」が認可レイヤーにログインするために使用するトークンは、ユーザーのパスワードとは異なります。ユーザーはログイン時に認可レイヤートークンの権限範囲と有効期間を指定できます。
「クライアント」が認可レイヤーにログインすると、「サービスプロバイダー」は、トークンの権限範囲と有効期間に基づいて、ユーザーの保存情報を「クライアント」に公開します。
OAuth 2.0の実行プロセスは以下のとおりです(RFC 6749から抜粋)。
リーリー上記の 6 つのステップのうち、B が鍵であること、つまり、ユーザーがクライアントをどのように承認できるかが重要であることを理解するのは難しくありません。この認可により、クライアントはトークンを取得し、そのトークンに基づいてリソースを取得できます。
以下では、クライアントが認可を取得するための 4 つのモードを 1 つずつ説明します。
クライアントはアクセストークンを取得するためにユーザーから認可グラントを取得する必要があります。 OAuth 2.0 では 4 つの認証方法が定義されています。
認証コードモードは、最も完全な機能と最も厳格なプロセスを備えた認証モードです。その特徴は、クライアントのバックエンドサーバーを介して「サービスプロバイダー」の認証サーバーと対話することです。
手順は次のとおりです:
リーリー上記の手順に必要なパラメータは次のとおりです。
ステップ A では、クライアントが認証を申請するために使用する URI には次のパラメータが含まれます:
これが例です。
リーリーステップ C では、サーバーは次のパラメータを含むクライアントの URI に応答します。
これが例です。
リーリーステップ D では、クライアントは、次のパラメータを含むトークンの HTTP リクエストを認証サーバーに申請します。
これが例です。
<pre class=" language-http"><code class=" language-http"> POST /token HTTP/1.1 <span class="token keyword">Host: server.example.com <span class="token keyword">Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW <span class="token keyword">Content-Type: application/x-www-form-urlencoded grant_type=authorization_code&code=SplxlOBeZQQYbYS6WxSbIA &redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Fcb </span></span></span></code>
E步骤中,认证服务器发送的HTTP回复,包含以下参数:
下面是一个例子。
<pre class=" language-http"><code class=" language-http"> HTTP/1.1 200 OK Content-Type: application/json;charset=UTF-8 Cache-Control: no-store Pragma: no-cache<span class="token application/json"> <span class="token punctuation">{ <span class="token string">"access_token"<span class="token punctuation">:<span class="token string">"2YotnFZFEjr1zCsicMWpAA"<span class="token punctuation">, <span class="token string">"token_type"<span class="token punctuation">:<span class="token string">"example"<span class="token punctuation">, <span class="token string">"expires_in"<span class="token punctuation">:<span class="token number">3600<span class="token punctuation">, <span class="token string">"refresh_token"<span class="token punctuation">:<span class="token string">"tGzv3JOkF0XG5Qx2TlKWIA"<span class="token punctuation">, <span class="token string">"example_parameter"<span class="token punctuation">:<span class="token string">"example_value" <span class="token punctuation">} </span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></code>
从上面代码可以看到,相关参数使用JSON格式发送(Content-Type: application/json)。此外,HTTP头信息中明确指定不得缓存。
OAuth 2.0 を理解する、oauth2.0_PHP チュートリアルを理解する(implicit grant type)不通过第三方应用程序的服务器,直接在浏览器中向认证服务器申请令牌,跳过了"授权码"这个步骤,因此得名。所有步骤在浏览器中完成,令牌对访问者是可见的,且客户端不需要认证。
它的步骤如下:
<p>(A)客户端将用户导向认证服务器。</p> <p>(B)用户决定是否给于客户端授权。</p> <p>(C)假设用户给予授权,认证服务器将用户导向客户端指定的"重定向URI",并在URI的Hash部分包含了访问令牌。</p> <p>(D)浏览器向资源服务器发出请求,其中不包括上一步收到的Hash值。</p> <p>(E)资源服务器返回一个网页,其中包含的代码可以获取Hash值中的令牌。</p> <p>(F)浏览器执行上一步获得的脚本,提取出令牌。</p> <p>(G)浏览器将令牌发给客户端。</p>
下面是上面这些步骤所需要的参数。
A步骤中,客户端发出的HTTP请求,包含以下参数:
下面是一个例子。
<pre class=" language-http"><code class=" language-http"> GET /authorize?response_type=token&client_id=s6BhdRkqt3&state=xyz &redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Fcb HTTP/1.1 Host: server.example.com </code>
C步骤中,认证服务器回应客户端的URI,包含以下参数:
下面是一个例子。
<pre class=" language-http"><code class=" language-http"> HTTP/1.1 302 Found Location: http://example.com/cb#access_token=2YotnFZFEjr1zCsicMWpAA &state=xyz&token_type=example&expires_in=3600 </code>
在上面的例子中,认证服务器用HTTP头信息的Location栏,指定浏览器重定向的网址。注意,在这个网址的Hash部分包含了令牌。
根据上面的D步骤,下一步浏览器会访问Location指定的网址,但是Hash部分不会发送。接下来的E步骤,服务提供商的资源服务器发送过来的代码,会提取出Hash中的令牌。
OAuth 2.0 を理解する、oauth2.0_PHP チュートリアルを理解する(Resource Owner Password Credentials Grant)中,用户向客户端提供自己的用户名和密码。客户端使用这些信息,向"服务商提供商"索要授权。
在这种模式中,用户必须把自己的密码给客户端,但是客户端不得储存密码。这通常用在用户对客户端高度信任的情况下,比如客户端是操作系统的一部分,或者由一个著名公司出品。而认证服务器只有在其他授权模式无法执行的情况下,才能考虑使用这种模式。
它的步骤如下:
<p>(A)用户向客户端提供用户名和密码。</p> <p>(B)客户端将用户名和密码发给认证服务器,向后者请求令牌。</p> <p>(C)认证服务器确认无误后,向客户端提供访问令牌。</p>
B步骤中,客户端发出的HTTP请求,包含以下参数:
下面是一个例子。
<pre class=" language-http"><code class=" language-http"> POST /token HTTP/1.1 Host: server.example.com Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW Content-Type: application/x-www-form-urlencoded grant_type=password&username=johndoe&password=A3ddj3w </code>
C步骤中,认证服务器向客户端发送访问令牌,下面是一个例子。
<pre class=" language-http"><code class=" language-http"> HTTP/1.1 200 OK Content-Type: application/json;charset=UTF-8 Cache-Control: no-store Pragma: no-cache<span class="token application/json"> <span class="token punctuation">{ <span class="token string">"access_token"<span class="token punctuation">:<span class="token string">"2YotnFZFEjr1zCsicMWpAA"<span class="token punctuation">, <span class="token string">"token_type"<span class="token punctuation">:<span class="token string">"example"<span class="token punctuation">, <span class="token string">"expires_in"<span class="token punctuation">:<span class="token number">3600<span class="token punctuation">, <span class="token string">"refresh_token"<span class="token punctuation">:<span class="token string">"tGzv3JOkF0XG5Qx2TlKWIA"<span class="token punctuation">, <span class="token string">"example_parameter"<span class="token punctuation">:<span class="token string">"example_value" <span class="token punctuation">} </span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></code>
上面代码中,各个参数的含义参见《OAuth 2.0 を理解する、oauth2.0_PHP チュートリアルを理解する》一节。
整个过程中,客户端不得保存用户的密码。
OAuth 2.0 を理解する、oauth2.0_PHP チュートリアルを理解する(Client Credentials Grant)指客户端以自己的名义,而不是以用户的名义,向"服务提供商"进行认证。严格地说,OAuth 2.0 を理解する、oauth2.0_PHP チュートリアルを理解する并不属于OAuth框架所要解决的问题。在这种 模式中,用户直接向客户端注册,客户端以自己的名义要求"服务提供商"提供服务,其实不存在授权问题。
它的步骤如下:
<p>(A)客户端向认证服务器进行身份认证,并要求一个访问令牌。</p> <p>(B)认证服务器确认无误后,向客户端提供访问令牌。</p>
A步骤中,客户端发出的HTTP请求,包含以下参数:
<pre class=" language-http"><code class=" language-http"> POST /token HTTP/1.1 Host: server.example.com Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW Content-Type: application/x-www-form-urlencoded grant_type=client_credentials </code>
认证服务器必须以某种方式,验证客户端身份。
B步骤中,认证服务器向客户端发送访问令牌,下面是一个例子。
<pre class=" language-http"><code class=" language-http"> HTTP/1.1 200 OK Content-Type: application/json;charset=UTF-8 Cache-Control: no-store Pragma: no-cache<span class="token application/json"> <span class="token punctuation">{ <span class="token string">"access_token"<span class="token punctuation">:<span class="token string">"2YotnFZFEjr1zCsicMWpAA"<span class="token punctuation">, <span class="token string">"token_type"<span class="token punctuation">:<span class="token string">"example"<span class="token punctuation">, <span class="token string">"expires_in"<span class="token punctuation">:<span class="token number">3600<span class="token punctuation">, <span class="token string">"example_parameter"<span class="token punctuation">:<span class="token string">"example_value" <span class="token punctuation">} </span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></code>
上面代码中,各个参数的含义参见《OAuth 2.0 を理解する、oauth2.0_PHP チュートリアルを理解する》一节。
如果用户访问的时候,客户端的"访问令牌"已经过期,则需要使用"更新令牌"申请一个新的访问令牌。
客户端发出更新令牌的HTTP请求,包含以下参数:
下面是一个例子。
<pre class=" language-http"><code class=" language-http"> POST /token HTTP/1.1 Host: server.example.com Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW Content-Type: application/x-www-form-urlencoded grant_type=refresh_token&refresh_token=tGzv3JOkF0XG5Qx2TlKWIA </code>