[解決済み] REST API トークンによる認証
質問
認証を必要とするREST APIを開発しています。認証自体はHTTP上の外部Webサービスを介して行われるため、認証サービスを繰り返し呼び出すのを避けるために、トークンを配布することを推論しました。これは、私の最初の質問にきちんと私をもたらします。
これは、各リクエストで HTTP Basic Auth を使用するようクライアントに要求し、サーバー側の認証サービスの呼び出しをキャッシュするよりも本当に良いのでしょうか?
Basic Auth ソリューションには、コンテンツへのリクエストを開始する前にサーバーへの完全なラウンドトリップを必要としないという利点があります。トークンは、潜在的により柔軟な範囲 (つまり、特定のリソースまたはアクションへの権利のみを付与) を持つことができますが、それは私の単純な使用例よりも OAuth コンテキストに適しているようです。
現在、トークンはこのように取得されます。
curl -X POST localhost/token --data "api_key=81169d80...
&verifier=2f5ae51a...
×tamp=1234567
&user=foo
&pass=bar"
は
api_key
,
timestamp
と
verifier
はすべてのリクエストで必要です。"verifier"が返されます。
sha1(timestamp + api_key + shared_secret)
私の意図は、既知の相手からの通話のみを許可し、通話がそのまま再利用されるのを防ぐことです。
これでよいのでしょうか? アンダーキルですか? オーバーキル?
トークンを手にしたクライアントは、リソースを獲得することができます。
curl localhost/posts?api_key=81169d80...
&verifier=81169d80...
&token=9fUyas64...
×tamp=1234567
可能な限りシンプルな呼び出しのために、これはちょっと恐ろしく冗長なようです。というのは
shared_secret
が (最低でも) iOS アプリケーションに埋め込まれ、そこから抽出されることを考えると、これは間違ったセキュリティの感覚を超えて何かを提供することになるのでしょうか?
どのように解決するのですか?
すべての問題を分離して、それぞれの問題にアプローチして解決しましょう。
認証
認証のために、baseauthはプロトコルレベルで成熟したソリューションであるという利点があります。これは多くの "might crop up later" の問題がすでに解決されていることを意味します。たとえば、BaseAuth を使用すると、ユーザーエージェントはパスワードがパスワードであることを知っているので、キャッシュされません。
Authサーバの負荷
認証情報をサーバーにキャッシュする代わりに、トークンをユーザーに配布しても、認証情報のキャッシュという点では同じです。唯一の違いは、キャッシュの責任をユーザーに転嫁していることです。これは、ユーザーにとって不必要な労力であり、何の利益もないように思えます。
送信のセキュリティ
SSL接続を使用できれば、それだけで、接続は安全です*。誤って複数回実行されることを防ぐために、複数のURLをフィルタリングしたり、URLにランダムな要素("nonce")を含めるようユーザーに依頼したりすることができます。
url = username:[email protected]/api/call/nonce
それが不可能で、送信される情報が秘密でない場合、トークンのアプローチで提案したように、ハッシュでリクエストを保護することをお勧めします。ハッシュはセキュリティを提供するので、ユーザーにbaseauthパスワードとしてハッシュを提供するように指示することができます。堅牢性を高めるために、タイムスタンプの代わりにランダムな文字列を"nonce"として使用し、リプレイ攻撃(同じ秒数の間に2つの正当なリクエストが行われる可能性がある)を防ぐことを推奨します。共有シークレットフィールドとAPIキーフィールドを別々に提供する代わりに、単純にAPIキーを共有シークレットとして使用し、レインボーテーブル攻撃を防ぐために変更されないソルトを使用することができます。usernameフィールドは認証の一部なので、nonceを置くのに良い場所と思われます。これで、次のようなきれいな呼び出しができるようになりました。
nonce = generate_secure_password(length: 16);
one_time_key = nonce + '-' + sha1(nonce+salt+shared_key);
url = username:[email protected]/api/call
これが少し手間がかかるのは事実です。これは、(SSLのような)プロトコルレベルのソリューションを使用していないためです。ですから、少なくともユーザー自身がそれを経験する必要がないように、何らかの SDK をユーザーに提供するのは良いアイデアかもしれません。この方法でやる必要があるのなら、セキュリティレベルは適切(ジャスト・ライト・キル)だと思います。
安全な秘密保持
誰を阻止しようとしているかによります。ユーザーの携帯電話にアクセスできる人が、ユーザー名で REST サービスを使用するのを防ぐのであれば、ターゲット OS で何らかのキーリング API を見つけ、SDK (または実装者) がそこにキーを保存するようにするのがよいアイデアでしょう。それが不可能な場合、少なくとも暗号化し、暗号化されたデータと暗号化キーを別々の場所に保存することで、秘密を入手するのを少し難しくすることができます。
代替クライアントの開発を防ぐために、他のソフトウェア ベンダーに API キーを取得させないようにする場合は、暗号化して保存する方法のみが有効です。 ほとんど
が有効です。これはホワイトボックス暗号であり、今日まで、このクラスの問題に対する真に安全な解決策は誰も思いつきませんでした。少なくともできることは、悪用されたキーを禁止できるように、各ユーザーに 1 つのキーを発行することです。(*) 編集中です。 SSL 接続 は安全であるとみなされなくなりました。 がなければ を検証するための追加の手順を踏まずに を行う必要があります。
関連
-
[解決済み] GitHub アカウントのユーザー名を変更する
-
[解決済み] JWTにおける時間切れの問題
-
[解決済み] SOAPとRESTの比較(相違点)
-
[解決済み] Gitのプッシュで "Authentication Failed "と表示される
-
[解決済み] RESTを理解する。動詞、エラーコード、認証
-
[解決済み] JAX-RSとJerseyでRESTトークンベースの認証を実装する方法
-
[解決済み】REST APIでのPUTメソッドとPATCHメソッドの使い分け 実生活でのシナリオ
-
[解決済み】RESTful 認証
-
[解決済み】node.jsのユーザー認証ライブラリは?
-
[解決済み] マイクロサービス認証戦略
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] smbclient NT_STATUS_ACCESS_DENIED
-
[解決済み] LDAPサーバをベースDNとする。
-
[解決済み] GitHub アカウントのユーザー名を変更する
-
[解決済み] ユーザー名とパスワードでMongoDBを保護する方法
-
[解決済み】OAuth2の「暗黙の」フローはとてもうまく機能しているのに、なぜ「認証コード」フローがあるのですか?
-
[解決済み】Goの認証はどのように管理されているのでしょうか?[クローズド]
-
[解決済み] トークン認証とCookieの比較
-
[解決済み] Refresh Token "の目的は何ですか?
-
[解決済み] クロスオリジンリクエストにCookieを設定する
-
[解決済み] ステートレス(=セッションレス)認証の場合、CSRFトークンは必要ですか?