私たちは、HTTP がステートレスであることを知っています。したがって、ユーザーがログインしているかどうかを確認する必要がある場合、ユーザーのログイン状態をチェックする必要があります。一般的に、ユーザーがログインに成功すると、サーバーはログイン証明書(トークンとも呼ばれる)を送信します。これは、あなたがある会社に訪問する際、受付で合法であると認証された後、その会社の受付があなたに訪問者カードを渡すのと似ています。その後、あなたはその会社内でどこに行くにもその訪問者カードを使ってドアを開け、あなたが誰であるかを再確認する必要はありません。コンピュータの世界では、このログイン証明書に関連するデータは 2 つの場所に保存されます。一つはユーザー側で、Cookie の形で保存されます(一般的にはブラウザのローカルストレージには保存されません。なぜなら、これでは XSS 攻撃によってログイン証明書が漏洩する可能性が高いからです)。もう一つはサーバー側で、セッションと呼ばれる方法で保存されます(SessionID は Cookie に保存されます)。
しかし、この世界はまだ比較的複雑です。ユーザーのアクセスに加えて、ユーザーが委託した第三者のアプリケーションや企業間の呼び出しもあります。ここで、業界で一般的に使用されるいくつかの API 認証技術を比較的体系的にまとめたいと思います。これにより、皆さんがこれらの技術をより包括的に理解できるようになります。
HTTP Basic#
HTTP Basic は非常に伝統的な API 認証技術であり、比較的シンプルな技術です。この技術は、ユーザー名とパスワードを使用してログインを行います。全体のプロセスはRFC 2617に定義されており、Wikipedia: Basic Access Authenticationの項目にも記載されています。また、MDN HTTP Authenticationも参照できます。
その技術原理は以下の通りです:
- ユーザー名とパスワードを「username」の形式にします(コロンで区切ります)。
- Base64 エンコードを行います。
Base64("username:password")
で文字列を取得します(例:haoelを base64 エンコードすると aGFvZW86Y29vbHNoZWxsCg が得られます)。 - aGFvZW86Y29vbHNoZWxsCg を HTTP ヘッダーの Authorization フィールドに入れ、
Authorization: Basic aGFvZW86Y29vbHNoZWxsCg
を形成し、サーバーに送信します。 - サーバーがヘッダー内に認証フィールドを見つけられない場合、401 エラーを返し、
WWW-Authenticate: Basic Realm='HelloWorld'
のようなヘッダーを返してクライアントに認証を要求します。その後、認証が通らない場合は 401 エラーを返します。サーバーが認証に成功した場合、200 を返します。
Base64 を使用する目的は、特定の文字を取り除くことに過ぎず、これにより HTTP プロトコル内で転送できるようになります。この方法の最大の問題は、ユーザー名とパスワードをネットワーク上に送信することです。したがって、一般的には TLS/SSL の安全な暗号化方式と組み合わせて使用する必要があります。JIRA Cloud の API 認証が HTTP Basic の方法をサポートしていることがわかります。
しかし、ユーザー名とパスワードを同時に公のネットワーク上で送信するこの方法はあまり良くありません。なぜなら、Base64 は暗号化プロトコルではなく、エンコーディングプロトコルだからです。したがって、HTTPS が安全な保護としてあっても、安心感は得られません。
Digest Access#
中国語では「HTTP 摘要認証」と呼ばれ、最初はRFC 2069文書で定義されました(その後、RFC 2617で一連のセキュリティ強化オプションが導入されました。「保護品質」(qop)、クライアントによって増加されるランダム数カウンター、クライアント生成のランダム数など)。
その基本的な考え方は、リクエスターがユーザー名、パスワード、ドメインを MD5 でハッシュ化し、MD5(username:realm:password)
をサーバーに送信することです。これにより、ユーザー名とパスワードをネットワーク上に送信することがなくなります。しかし、ユーザー名とパスワードは基本的に変わらないため、この MD5 文字列も比較的固定されます。したがって、この認証プロセスには 2 つの要素が追加されます。一つは nonce、もう一つは qop です。
- まず、呼び出し側が通常の HTTP リクエストを発行します。例えば:
GET /coolshell/admin/ HTTP/1.1
- サーバーは認証できないため、401 エラーを返し、HTTP ヘッダーの WWW-Authenticate には以下の情報が含まれます:
WWW-Authenticate: Digest realm="testrealm@host.com",
qop="auth,auth-int",
nonce="dcd98b7102dd2f0e8b11d0f600bfb0c093",
opaque="5ccc069c403ebaf9f0171e9517f40e41"
- ここでの nonce はサーバー側で生成されたランダム数です。その後、クライアントは
HASH1=MD5(MD5(username:realm:password):nonce:cnonce)
を計算します。ここでの cnonce はクライアントが生成したランダム数です。これにより、全体の MD5 の結果が異なるようになります。 - qop に auth が含まれている場合、
HASH2=MD5(method:digestURI)
を計算します。ここでの method は HTTP のリクエストメソッド(GET/POST など)、digestURI はリクエストの URL です。 - qop に auth-int が含まれている場合、
HASH2=MD5(method:digestURI:MD5(entityBody))
を計算します。ここでの entityBody は HTTP リクエストの全データです。 - 次に、
response = MD5(HASH1:nonce:nonceCount:cnonce:qop:HASH2)
を得ます。qop がない場合はresponse = MD5(HA1:nonce:HA2)
となります。 - 最後に、クライアントはサーバーに次のリクエストを発行します ——HTTP ヘッダーの
Authorization: Digest ...
に注意してください。
GET /dir/index.html HTTP/1.0
Host: localhost
Authorization: Digest username="Mufasa",
realm="testrealm@host.com",
nonce="dcd98b7102dd2f0e8b11d0f600bfb0c093",
uri="%2Fcoolshell%2Fadmin",
qop=auth,
nc=00000001,
cnonce="0a4f113b",
response="6629fae49393a05397450978507c4ef1",
opaque="5ccc069c403ebaf9f0171e9517f40e41"
ウィキペディアのWikipedia: Digest access authenticationの項目は、この詳細を非常に詳しく説明しています。
摘要認証のこの方法は、以前の方法よりも良いです。なぜなら、ユーザーのパスワードをネットワーク上に送信することはなく、パスワードの MD5 を送信するだけだからです。相対的に安全であり、TLS/SSL の安全なリンクが必要ありません。しかし、このアルゴリズムは非常に複雑に見えますが、最終的にはユーザーのパスワードが重要です。このパスワードが十分に複雑でない場合、実際にはブルートフォース攻撃に対して脆弱です。また、全体のプロセスは中間者攻撃を受けやすいです—— たとえば、中間者がクライアントに Basic 認証方式や古い署名認証方式(RFC2069)を要求する場合です。
App Secret Key + HMAC#
まず HMAC 技術について説明します。この技術は MAC(メッセージ認証コード)から来ており、メッセージに署名するための技術です。つまり、メッセージが送信中に変更されることを恐れているため、メッセージに MAC アルゴリズムを適用して要約文字列を得る必要があります。その後、受信者はメッセージを受け取った後、同じ計算を行い、この MAC 文字列を比較します。一致すれば、変更されていないことを示します(全体のプロセスは下の図を参照してください)。HMAC(ハッシュベースの認証コード)は、この作業をハッシュ技術を利用して行います。たとえば、SHA-256 アルゴリズムです。
次に App ID について説明します。これは認証とは関係なく、誰が API を呼び出すかを区別するためのもので、私たち全員の身分証明書のようなものです。異なる人を示すためだけに使用され、認証には使用されません。前述の違いは、ここで App ID を使用して暗号化キーをマッピングする必要があることです。これにより、サーバー側で関連する管理を行うことができます。私たちはいくつかのキーのペア(AppID、AppSecret)を生成し、より細かい操作権限管理を行うことができます。
AppID と HMAC を API 認証に使用する場合、現在最も優れた専門的なものは AWS です。私たちはS3 の API リクエスト署名文書を通じて AWS がどのように機能しているかを見ることができます。全体のプロセスは非常に複雑で、以下の画像プロセスで大まかな流れを確認できます。基本的には、以下のいくつかのステップに分かれます:
- HTTP リクエスト(メソッド、URI、クエリ文字列、ヘッダー、署名ヘッダー、ボディ)をパッケージ化して CanonicalRequest と呼び、SHA-256 の署名を作成し、次に base16 エンコードを行います。
- 上記の署名と署名アルゴリズム AWS4-HMAC-SHA256、タイムスタンプ、スコープをパッケージ化して StringToSign と呼びます。
- 署名を準備し、AWSSecretAccessKey を使用して日付に DataKey を署名し、DataKey を操作するリージョンに署名し、関連するサービスに DataRegionServiceKey を署名し、最終的に SigningKey を得ます。
- ステップ 3 の SigningKey を使用してステップ 2 の StringToSign に署名します。
最後に、HTTP リクエストを発行する際に、HTTP ヘッダーの Authorization フィールドに以下の情報を含めます:
Authorization: AWS4-HMAC-SHA256
Credential=AKIDEXAMPLE/20150830/us-east-1/iam/aws4_request,
SignedHeaders=content-type;host;x-amz-date,
Signature=5d672d79c15b13162d9279b0855cfba6789a8edb4c82c400e06b5924a6f2b5d7
ここでの AKIDEXAMPLE は AWS Access Key ID、いわゆる AppID です。サーバー側はこの AppID に基づいて関連する Secret Access Key を検索し、署名を検証します。このプロセスが少し理解できない場合は、この記事を読んでみてください ——《Amazon S3 Rest API with curl》にはいくつかのコードがあり、コードは最も詳細で正確です。
この認証方法の利点は、AppID と AppSecretKey がサーバーのシステムによって発行されるため、管理が可能であることです。AWS の IAM は関連する管理を行い、ユーザー、権限、およびそれに対応する AppID と AppSecretKey を管理します。しかし、欠点は、このものに標準がないため、各社の実装が非常に不一致であることです。たとえば、Acquia の HMAC、WeChat の署名アルゴリズム(ここで、WeChat の API は HTTP プロトコルの標準に従っておらず、認証情報を HTTP ヘッダーの Authorization に置くのではなく、ボディに置いています)。
JWT – JSON Web Tokens#
JWT は比較的標準的な認証ソリューションであり、この技術は Java の分野で非常に一般的に使用されています。JWT の署名も MAC の一種です。JWT の署名プロセスは一般的に以下のようになります:
- ユーザーはユーザー名とパスワードを使用して認証サーバーに認証を要求します。
- 認証サーバーはユーザー名とパスワードを検証した後、サーバー側で JWT トークンを生成します。このトークンの生成プロセスは以下の通りです:
- 認証サーバーは Secret Key(鍵)も生成します。
- JWT ヘッダーと JWT ペイロードをそれぞれ Base64 でエンコードします。ペイロードにはユーザーの抽象 ID や有効期限が含まれる場合があります。
- 秘密鍵を使用して JWT に署名します。
HMAC-SHA256(SecertKey, Base64UrlEncode(JWT-Header)+'.'+Base64UrlEncode(JWT-Payload));
- その後、
base64(header).base64(payload).signature
を JWT トークンとしてクライアントに返します。 - クライアントは JWT トークンを使用してアプリケーションサーバーに関連するリクエストを送信します。この JWT トークンは一時的なユーザー権限証明書のようなものです。
アプリケーションサーバーがリクエストを受け取ったとき:
- アプリケーションサービスは JWT トークンをチェックし、署名が正しいことを確認します。
- しかし、認証サーバーだけがこのユーザーの Secret Key(鍵)を持っているため、アプリケーションサーバーは JWT トークンを認証サーバーに送信する必要があります。
- 認証サーバーは JWT ペイロードからユーザーの抽象 ID を解読し、その抽象 ID を使用してログイン時に生成された Secret Key を取得し、署名を再確認します。
- 認証サーバーが確認を通過した後、アプリケーションサービスはこれが合法なリクエストであると見なすことができます。
上記のプロセスは、認証サーバーでユーザーのために動的に Secret Key を生成することを示しています。アプリケーションサービスが署名を検証する際には、認証サーバーに署名を求める必要があるため、このプロセスはネットワーク呼び出しを増加させます。したがって、JWT は HMAC-SHA256 アルゴリズムをサポートするだけでなく、RSA の非対称暗号アルゴリズムもサポートしています。
RSA の非対称アルゴリズムを使用する場合、認証サーバー側に秘密鍵を置き、アプリケーションサーバー側に公開鍵を置きます。認証サーバーは秘密鍵で暗号化し、アプリケーションサーバーは公開鍵で復号化します。これにより、アプリケーションサーバーが認証サーバーにリクエストを送信する必要がなくなりますが、RSA は非常に遅いアルゴリズムです。したがって、ネットワーク呼び出しを省略できても、CPU を消費します。特にヘッダーとペイロードが長い場合です。したがって、比較的良い方法は、ヘッダーとペイロードを単純に SHA256 で処理し、SHA256 から得られた文字列を RSA で暗号化することです。これにより、RSA アルゴリズムが比較的速くなり、RSA 署名の目的も達成できます。
最後に、認証サーバーとアプリケーションサーバー間で定期的に公開鍵と秘密鍵のペアを交換するメカニズムを使用するだけで済みます。
ここで、Angular 大学の《JSW:The Complete Guide to JSON Web Tokens》を全文読むことを強くお勧めします。
OAuth 1.0#
OAuth も API 認証のプロトコルであり、このプロトコルは最初に 2006 年に Twitter のエンジニアによって OpenID の実装を開発しているときに、ソーシャルブックマークサイト Ma.gnolia と共に発見されました。良い委任認可プロトコルが存在しなかったため、2007 年に OAuth グループが設立されました。このニュースを聞いた Google の社員も参加し、このプロトコルを改善しました。2007 年末に草案が発表され、1 年後の 2008 年に OAuth が IETF に持ち込まれ、さらなる標準化作業が行われました。最終的に 2010 年 4 月に OAuth 1.0 が正式に発表されました。すなわち、RFC 5849(この RFC は TCP のものに比べて読みやすいです)。ただし、その前身の草案を理解したい場合は、OAuth Core 1.0 Revision Aを読むことをお勧めします。以下に大まかな説明をします。
RFC 5849 によれば、OAuth の登場は、ユーザーが第三者のネットワーク印刷サービスを使用して、特定のウェブサイトにある写真を印刷したいが、ユーザーはその第三者のネットワーク印刷サービスに自分のユーザー名とパスワードを渡したくないが、同時にその第三者のネットワーク印刷サービスに自分の写真にアクセスさせたいという問題を解決するために生まれました。
- このプロトコルには 3 つの役割があります:
- ユーザー(写真所有者)
- 消費者(第三者の写真印刷サービス)
- サービスプロバイダー(写真ストレージサービス)
- このプロトコルには 3 つの段階があります:
- 消費者がリクエストトークンを取得する
- サービスプロバイダーがユーザーを認証し、消費者に権限を付与する
- 消費者がアクセストークンを取得し、API を呼び出してユーザーの写真にアクセスする
全体の認可プロセスは以下の通りです:
- 消費者(第三者の写真印刷サービス)は、まずサービスプロバイダーから開発用の消費者キーと消費者シークレットを取得する必要があります。
- ユーザーが消費者にアクセスすると、消費者はサービスプロバイダーにリクエストトークンを要求します(HTTP リクエストに署名する必要があります)。
- サービスプロバイダーは消費者が登録された第三者サービスであることを確認した後、リクエストトークン(oauth_token)とリクエストトークンシークレット(oauth_token_secret)を返します。
- 消費者はリクエストトークンを受け取った後、HTTP GET リクエストを使用してユーザーをサービスプロバイダーの認証ページにリダイレクトします(リクエストトークンを含む)。
- サービスプロバイダーはユーザーの認証に成功した後、消費者にリダイレクトし、リクエストトークン(oauth_token)と検証コード(oauth_verifier)を返します。
- 次に、リクエストトークンと検証コードを使用してアクセストークン(oauth_token)とアクセストークンシークレット(oauth_token_secret)を取得します。
- 最後に、アクセストークンを使用してユーザーが許可したリソースにアクセスします。
以下の図は Yahoo! のフローチャートで、全体のプロセスの関連詳細を示しています。
上記のプロセスには 3 つの当事者がいます:ユーザー、消費者、サービスプロバイダー。したがって、これを 3 脚フローと呼びます。OAuth 1.0 にはユーザーの参加が不要なものもあり、消費者とサービスプロバイダーのみの 2 脚フローもあります。この場合、ユーザー認証のプロセスが省略されます。全体のプロセスは以下の通りです:
- 消費者(第三者の写真印刷サービス)は、まずサービスプロバイダーから開発用の消費者キーと消費者シークレットを取得する必要があります。
- 消費者はサービスプロバイダーにリクエストトークンを要求します(HTTP リクエストに署名する必要があります)。
- サービスプロバイダーは消費者が登録された第三者サービスであることを確認した後、リクエストトークン(oauth_token)とリクエストトークンシークレット(oauth_token_secret)を返します。
- 消費者はリクエストトークンを受け取った後、直接アクセストークン(oauth_token)とアクセストークンシークレット(oauth_token_secret)を取得します。
- 最後に、アクセストークンを使用してユーザーが許可したリソースにアクセスします。
最後に、OAuth の署名について説明します。
- ここで、2 つの秘密鍵があります。一つは消費者がサービスプロバイダーに登録する際にプロバイダーから発行される消費者シークレット、もう一つはトークンシークレットです。
- 署名鍵はこれら 2 つの鍵を結合して作成され、& で接続されます。たとえば、消費者シークレットが j49sk3j29djd でトークンシークレットが dh893hdasih9 の場合、署名鍵は j49sk3j29djd&dh893hdasih9 となります。
- リクエストトークンまたはアクセストークンを要求する際には、全体の HTTP リクエストに署名する必要があります(HMAC-SHA1 および HMAC-RSA1 署名アルゴリズムを使用)。リクエストヘッダーには、OAuth に必要なフィールドを含める必要があります。例えば:
- 消費者キー:いわゆる AppID
- トークン:リクエストトークンまたはアクセストークン
- 署名メソッド:署名アルゴリズム(例:HMAC-SHA1)
- タイムスタンプ:有効期限
- ノンス:ランダム文字列
- コールバック:コールバック URL
以下の図は全体の署名の概念図です:
OAuth 2.0#
前述のように、Digest Access から AppID + HMAC、次に JWT、そして OAuth 1.0 まで、これらの API 認証はすべてクライアントに秘密鍵(またはパスワード)を送信し、その後 HASH または RSA を使用して HTTP リクエストに署名する必要があります。この主な理由は、以前の HTTP が平文で送信されていたため、送信中に改ざんされる可能性が高かったため、安全な署名メカニズムが必要でした。したがって、これらの認証方法は HTTP の平文プロトコルの下で機能することができます。
この署名方式は比較的複雑であるため、開発者にとってもあまり親切ではありません。署名を組織する際に、さまざまな URLEncode や Base64 を使用し、クエリのパラメータをソートし、さらに一部の方法では階層的に署名する必要があり、非常にエラーが発生しやすいです。また、この認証のセキュリティ粒度は比較的粗く、権限も単一であり、エンドユーザーが参加するモバイル端末にとっては不十分です。したがって、2012 年に OAuth 2.0 のRFC 6749が正式に発表されました。
OAuth 2.0 は TLS/SSL のリンク暗号化技術(HTTPS)に依存し、署名方式を完全に放棄しました。認証サーバーはもはやトークンシークレットの鍵を返さなくなったため、OAuth 2.0 は 1.0 とは完全に異なり、互換性がありません。現在、Facebook の Graph API は OAuth 2.0 プロトコルのみをサポートしており、Google や Microsoft Azure も OAuth 2.0 をサポートしています。国内の WeChat や Alipay も OAuth 2.0 の使用をサポートしています。
以下に、OAuth 2.0 の 2 つの主要なフローを重点的に見ていきます:
- 一つは Authorization Code Flow で、これは 3 脚のものです。
- もう一つは Client Credential Flow で、これは 2 脚のものです。
Authorization Code Flow#
Authorization Code は最も一般的に使用される OAuth 2.0 の認可タイプであり、ユーザーが第三者アプリケーションに自分の情報へのアクセスを許可するシナリオに適しています。このフローは OAuth 2.0 の 4 つのフローの中で、私が個人的に最も完全だと思うフローです。そのフローチャートは以下の通りです。
以下はこのプロセスの詳細な説明です:
- ユーザー(リソースオーナー)が第三者アプリケーション(クライアント)にアクセスすると、第三者アプリケーションはユーザーを認証サーバー(Authorization Server)に連れて行きます。主にリクエストするのは
/authorize
API で、リクエスト方式は以下の通りです。
https://login.authorization-server.com/authorize?
client_id=6731de76-14a6-49ae-97bc-6eba6914391e
&response_type=code
&redirect_uri=http%3A%2F%2Fexample-client.com%2Fcallback%2F
&scope=read
&state=xcoiv98CoolShell3kch
ここで:
- client_id は第三者アプリケーションの App ID です。
- response_type=code は認証サーバーに、Authorization Code Flow を使用することを伝えます。
- redirect_uri は第三者アプリケーションに戻る URL を意味します。
- scope は関連する権限を意味します。
- state は CSRF 攻撃を防ぐためのランダムな文字列です。
- 認証サーバーがこの URL リクエストを受け取ると、client_id を通じて redirect_uri と scope が合法かどうかを確認します。合法であれば、ポップアップページを表示してユーザーに許可を求めます(ユーザーがログインしていない場合は、まずログインを促し、ログインが完了した後に許可アクセスページを表示します)。
- ユーザーがアクセスを許可すると、認証サーバーはクライアントにリダイレクトし、その中に Authorization Code を追加します。以下のようになります:
https://example-client.com/callback?
code=Yzk5ZDczMzRlNDEwYlrEqdFSBzjqfTG
&state=xcoiv98CoolShell3kch
- 次に、クライアントは Authorization Code を使用してアクセストークンを取得できます。認証サーバーに以下のリクエストを発信する必要があります。
POST /oauth/token HTTP/1.1
Host: authorization-server.com
code=Yzk5ZDczMzRlNDEwYlrEqdFSBzjqfTG
&grant_type=code
&redirect_uri=https%3A%2F%2Fexample-client.com%2Fcallback%2F
&client_id=6731de76-14a6-49ae-97bc-6eba6914391e
&client_secret=JqQX2PNo9bpM0uEihUPzyrh
- 問題がなければ、認証サーバーは以下の情報を返します。
{
"access_token": "iJKV1QiLCJhbGciOiJSUzI1NiI",
"refresh_token": "1KaPlrEqdFSBzjqfTGAMxZGU",
"token_type": "bearer",
"expires": 3600,
"id_token": "eyJ0eXAiOiJKV1QiLCJhbGciO.eyJhdWQiOiIyZDRkM..."
}
ここで:
- access_token はアクセスリクエストトークンです。
- refresh_token は access_token を更新するために使用されます。
- id_token は JWT のトークンで、一般的にユーザーの OpenID が含まれます。
- 次に、アクセストークンを使用してユーザーのリソースをリクエストします。
GET /v1/user/pictures
Host: https://example.resource.com
Authorization: Bearer iJKV1QiLCJhbGciOiJSUzI1NiI
Client Credential Flow#
Client Credential は簡略化された API 認証で、主に認証サーバーからサーバーへの呼び出しに使用されます。つまり、ユーザーが参加しない認証プロセスです。以下は関連するフローチャートです。
このプロセスは非常にシンプルで、本質的にはクライアントが自分の client_id と client_secret を使用して認証サーバーにアクセストークンを要求し、その後アクセストークンを使用して関連するリソースにアクセスするというものです。
リクエストの例:
POST /token HTTP/1.1
Host: server.example.com
Content-Type: application/x-www-form-urlencoded
grant_type=client_credentials
&client_id=czZCaGRSa3F0Mzpn
&client_secret=7Fjfp0ZBr1KtDRbnfVdmIw
返却の例:
{
"access_token":"MTQ0NjJkZmQ5OTM2NDE1ZTZjNGZmZjI3",
"token_type":"bearer",
"expires_in":3600,
"refresh_token":"IwOGYzYTlmM2YxOTQ5MGE3YmNmMDFkNTVk",
"scope":"create"
}
小結#
2 つの用語と 3 つの概念を区別する#
- 2 つの用語を区別します:Authentication(認証)と Authorization(認可)。前者はリクエスターの身分を証明するもので、身分証明書のようなものです。後者は権限を得るためのものです。身分は他者と区別するための証明であり、権限は自分の特権を証明するものです。Authentication は、操作を行うこの人が本人であることを証明するために、パスワード、SMS 認証コード、さらには顔認識を提供する必要があります。Authorization は、すべてのリクエストで人を確認する必要がなく、Authorization を経てトークンを得ることです。これは Authorization です。まるでパスポートとビザのようです。
- 3 つの概念を区別します:エンコーディング Base64Encode、署名 HMAC、暗号化 RSA。Base64 エンコーディングは、より良い転送のため(奇妙な文字がなく、バイナリファイルを転送できる)であり、明文に相当します。HMAC 署名は情報が改ざんされないようにするためのもので、RSA 暗号化は他者に情報が見えないようにするためのものです。
一部の意図を理解する#
- 複雑な HMAC ハッシュ署名方式を使用する主な理由は、当時 TLS/SSL 暗号化リンクがなかったためです。
- JWT が uid をトークンに含める目的は、状態を排除するためですが、ユーザーが変更できないようにするために署名が必要です。
- OAuth 1.0 は、第三者のクライアントと実際のユーザーを区別し、最初にリクエストトークンを取得し、その後アクセストークンを交換する方法は、第三者アプリケーションとユーザーを区別するためです。
- ユーザーのパスワードはユーザー自身が設定したものであり、複雑さは制御できませんが、サーバーが発行する Secret は非常に複雑であり、主な目的は管理が容易であり、いつでも無効にできることです。
- OAuth プロトコルは、すべての認証プロトコルに比べてより柔軟で完全な構成を持っています。AppID/AppSecret 署名方式を使用し、異なる権限を持ち、いつでも無効にできるようにするには、AWS の IAM のようなアカウントとキーの管理システムを開発する必要があります。
関連する注意事項#
- どの方法を使用する場合でも、HTTP の規範に従い、認証情報を Authorization HTTP ヘッダーに置くべきです。
- GET 方式を使用して URL にシークレットのようなものを含めないでください。多くのプロキシやゲートウェイソフトウェアは、全 URL をアクセスログファイルに記録します。
- シークレットはパスワードに相当しますが、暗号化に使用されるため、ネットワーク上で送信しない方が良いです。送信する場合は、TLS/SSL の安全なリンクを使用するのが最善です。
- HMAC の MD5 でも SHA1/SHA2 でも、その計算は非常に速いですが、RSA の非対称暗号は CPU を消費します。特に暗号化する文字列が長い場合です。
- プログラム内にシークレットをハードコーディングしない方が良いです。なぜなら、GitHub 上には多くのハッカーがさまざまなシークレットを監視するソフトウェアがあるため、非常に注意が必要です!このようなものは、設定システムやデプロイシステムに置くべきで、プログラム起動時に設定ファイルや環境変数に設定します。
- AppID/AppSecret を使用するか、OAuth 1.0 を使用するか、OAuth 2.0 を使用するか、JWT を使用するか、個人的には TLS/SSL 下の OAuth 2.0 を使用することをお勧めします。
- シークレットは管理される必要があり、管理とは、新規追加、撤回、アカウントと関連する権限の設定が可能であることを意味します。シークレットは自動的に変更できるのが最善です。
- 認証認可サーバー(Authorization Server)とアプリケーションサーバー(App Server)はできるだけ分けるべきです。