モバイルアプリケーション用のAPIの作成-認証と承認


189

概観

アプリケーション用の(REST)APIを作成しようとしています。最初の/主な目的は、モバイルアプリ(iPhone、Android、Symbianなど)による使用です。私は(他の実装を研究することにより)WebベースのAPIの認証と承認のさまざまなメカニズムを調べてきました。基本的な概念のほとんどに頭を抱えていますが、まだいくつかの領域でガイダンスを探しています。私がやりたい最後のことは、ホイールを再発明することですが、自分の基準に合う標準的な解決策を見つけることができません(ただし、自分の基準を誤解しているので、遠慮なく批評してください)。さらに、私はそれを消費するすべてのプラットフォーム/アプリケーションでAPIが同じであることを望みます。

oAuth

それが提供される最初のソリューションである可能性が高いことを知っているので、私は先に進んでoAuthへの反対を捨てます。モバイルアプリケーション(または、より具体的には非Webアプリケーション)の場合、認証のためにアプリケーションを(Webブラウザに移動するために)残すのは間違っているように見えます。さらに、ブラウザーがコールバックをアプリケーション(特にクロスプラットフォーム)に返す方法はありません(私は承知しています)。私はそれを行ういくつかのアプリを知っていますが、それは単に間違っていると感じて、アプリケーションUXを中断させます。

必要条件

  1. ユーザーはユーザー名/パスワードをアプリケーションに入力します。
  2. すべてのAPI呼び出しは、呼び出し元のアプリケーションによって識別されます。
  3. オーバーヘッドは最小限に抑えられ、認証の側面は開発者にとって直感的です。
  4. このメカニズムは、エンドユーザー(ログイン資格情報が公開されない)と開発者(アプリケーション資格情報が公開されない)の両方に対して安全です。
  5. 可能であれば、httpsは必要ありません(決してハード要件ではありません)。

実装に関する私の現在の考え

外部の開発者がAPIアカウントをリクエストします。彼らはapikeyとapisecretを受け取ります。すべてのリクエストには、少なくとも3つのパラメータが必要です。

  • apikey-登録時に開発者に与えられる
  • タイムスタンプ-特定のapikeyの各メッセージの一意の識別子としても機能します
  • hash-タイムスタンプのハッシュ+ apisecret

apikeyは、リクエストを発行するアプリケーションを識別するために必要です。タイムスタンプはoauth_nonceと同様に機能し、リプレイ攻撃を回避/軽減します。ハッシュは、リクエストが実際に特定のAPIキーの所有者から発行されたことを確認します。

認証済みのリクエスト(ユーザーに代わって実行されるリクエスト)の場合、私はまだ、access_tokenルートを使用するか、ユーザー名とパスワードのハッシュコンボを使用するかを決めていません。いずれにしても、ある時点でユーザー名とパスワードの組み合わせが必要になります。そのため、複数の情報(apikey、apisecret、timestamp)+パスワードのハッシュが使用されます。 この点についてフィードバックをいただければ幸いです。 ちなみに、私はパスワードをハッシュせずにシステムに保存しないので、最初にパスワードをハッシュする必要があります。

結論

ちなみに、これは、一般にAPIを構築/構造化する方法の要求ではなく、アプリケーション内からのみ認証と承認を処理する方法だけです。

ランダムな考え/ボーナスの質問

リクエストの一部としてAPIキーのみを必要とするAPIの場合、APIキーの所有者以外の誰かがAPIキーを(平文で送信されるため)表示し、過度のリクエストを行って使用制限を超えてしまうことを防ぐにはどうすればよいですか?多分私はこれを考えすぎているかもしれませんが、リクエストがapikey所有者に対して検証されたことを認証するための何かがあるべきではありませんか?私の場合、それはapisecretの目的でした。ハッシュ化されない限り、表示/送信されることはありません。

ハッシュといえば、md5対hmac-sha1はどうですか?すべての値が十分に長いデータ(つまりapisecret)でハッシュされる場合、それは本当に重要ですか?

私は以前、ユーザーごとのソルトをユーザーのパスワードハッシュに追加することを検討していました。それを行うとしたら、アプリケーションは、使用されるソルトを知らなくても、一致するハッシュを作成できるでしょうか?


1
さらにいくつかのコメント/提案を得ることを望んでいました。質問は曖昧で曖昧すぎますか?
jsuggs

6
質問は完璧ですが、ほぼ2年後でも、oauthの実装は難解なようです...上記で説明したことを正確に達成するのに最も苦労しています。追加のディメンションがあります:loginName / passwordのペアを使用したくない-android / iosでgoogle ID検証を使用したい(symbianはWWFによって「ほぼ絶滅した種」と宣言された)ため、開発を拒否するWindowsモバイル(最近では何と呼んでも)。
トニーギル2012

8
誰もがoauth 2.0を提案しているのと同じくらい馬鹿げているが、一般的な英語を使用して、手順、要件、
注意

2
OAuth2.0のこの特定のフロー(リソース所有者のパスワードフロー)を読んでください。ウェブサイトにリダイレクトしません。 techblog.hybris.com/2012/06/11/…–
フランクリン

1
私も同じ答えを探しています。最近書いた良い記事を見つけました。これがお役に立てば幸いです。 stormpath.com/blog/the-ultimate-guide-to-mobile-api-security
New to Rails

回答:


44

私のプロジェクトでこれのログイン部分を行うことについて私が考えている方法は次のとおりです。

  1. ログインする前に、ユーザーlogin_tokenはサーバーにを要求します。これらはリクエストに応じてサーバーに生成および保存され、おそらく有効期間が限られています。

  2. アプリケーションにログインするには、ユーザーのパスワードのハッシュを計算し、パスワードをでハッシュしlogin_tokenて値を取得します。その後、ユーザーはlogin_tokenと結合されたハッシュの両方を返します。

  3. サーバーlogin_tokenはが生成したものをチェックし、有効なlogin_tokenのリストから削除します。次に、サーバーはユーザーのパスワードの保存されたハッシュをlogin_tokenと組み合わせ、送信された組み合わせトークンと確実に一致するようにします。一致する場合は、ユーザーを認証しています。

これの利点は、ユーザーのパスワードをサーバーに保存しないこと、パスワードを平文で渡すことはなく、パスワードハッシュはアカウント作成時に平文でのみ渡されることです(これにはいくつかの方法があります)。login_token使用時にDBから削除されるため、リプレイ攻撃から安全です。


おかげで、アプリケーション側でパスワードをハッシュする部分を追加するのを忘れていました。ユーザーのパスワードを平文で保存しません(保存する前にハッシュします)。
jsuggs 2010年

2
この方法にはマイナス面があります。ソルトされたパスワードをDBに保存することはできません。攻撃者がDBに手を置いた場合、復号化を行う必要はありません。この方式ではパスワードハッシュが実際のパスワードなので、
sigod 2015年

2
@sigodあなたは正しいです。私そこに根本的な二分があると思いますが-あなたはあなたの輸送を信頼する必要があるか、あなたはあなたのストレージを信頼する必要があります。ソルトパスワードを使用するログインシステムはトランスポート層を信頼するため、ユーザーからパスワードを平文で認証システムに渡します。このケースは、トランスポート層を信頼していません(これは、対象としているプラ​​ットフォームがSHTTPを適切にサポートしていなかったためだと思います)。トランスポート層を信頼する場合、他のトレードオフを行うことができる場合があります。
マイケルアンダーソン

3つの問題があります。1)ユーザーのパスワードがサーバーに保存されないのはなぜですか。手順2で、ハッシュされたユーザーのパスワードを保存すると述べました。2)ユーザーパスワードが平文で渡されることはありません。しかし、それは実際にはクライアントでハッシュされ、サーバーでハッシュされたパスワードと比較されます。これは、パスワードを渡し、クリアテキストで格納することとほぼ同じです。それを行う意味は何ですか?3)この方法は、login_token +パスワードがどのようにハッシュされるかを攻撃者が知らないことを前提としています。これは、ケルクホフスの原則に違反しており、本当に安全ではありません。
Tamer Shlash、2016

14

それはたくさんの質問を1つにまとめたものです。かなりの数の人が最後まで読んでいられなかったと思います:)

私のWebサービス認証の経験では、人々は通常それを過剰設計し、問題はWebページで発生するのと同じです。考えられる非常に単純なオプションには、ログインステップのhttpsが含まれ、トークンが返され、将来のリクエストに含める必要があります。また、http基本認証を使用して、ヘッダーにデータを渡すこともできます。セキュリティを強化するには、トークンを頻繁にローテーション/期限切れにし、リクエストが同じIPブロックから送信されていることを確認します(これはモバイルユーザーがセル間を移動するときに厄介になる可能性があります)、APIキーなどと組み合わせます。または、ユーザーを認証する前に、oauthの「キーのリクエスト」ステップを実行し(誰かが前の回答でこれをすでに提案していて、それは良い考えです)、それを必要なキーとして使用してアクセストークンを生成します。

まだ使用していませんが、oAuthのデバイスフレンドリーな代替としてxAuthについてよく耳にします。それを見て、あなたがそれを使うなら、私はあなたの印象が何であるか聞いて本当に興味があります。

ハッシュに関しては、sha1は少し優れていますが、それにこだわる必要はありません。デバイスが簡単に(そしてパフォーマンスの意味ですばやく)実装できれば、おそらく問題はありません。

幸運を祈ります:)


ご返信ありがとうございます。私はxAuthを調査してきましたが、それが最終的にoAuthのインストールにつながるルートになる可能性があり、APIと対話するためのより標準化されたプロセスになります。
jsuggs 2010年

9

では、モバイルアプリケーションの認証と承認の側面を処理するサーバー側の認証メカニズムは何ですか?

これが事実であると仮定すると、次のようにアプローチします(ただし、 'cosだけがJava開発者なので、C#の人は別の方法で行います):

RESTful認証および許可サービス

  1. これは、盗聴を防ぐためにHTTPSでのみ機能します。
  2. RESTEasySpring SecurityCASの組み合わせに基づいています。(複数のアプリケーションにわたるシングルサインオン用)のます。
  3. ブラウザとWeb対応クライアントアプリケーションの両方で動作します
  4. ユーザーが詳細を編集できるWebベースのアカウント管理インターフェイスがあり、管理者(特定のアプリケーションの場合)が承認レベルを変更できるようになります

クライアント側のセキュリティライブラリ/アプリケーション

  1. サポートされているプラ​​ットフォーム(Symbian、Android、iOSなど)ごとに、プラットフォームのネイティブ言語(Java、ObjectiveC、Cなど)でセキュリティライブラリの適切な実装を作成します。
  2. ライブラリは、所定のプラットフォームで利用可能なAPIを使用してHTTPSリクエストの形成を管理する必要があります(JavaはURLConnectionなどを使用します)
  3. 一般的な認証および承認ライブラリ( 'cos'だけで十分です)の利用者は、特定のインターフェイスにコードを記述し、それが変更されても満足できないので、非常に柔軟であることを確認してください。Spring Securityなどの既存の設計選択に従います。

30,000ftからのビューが完成したので、どうやってそれを実行しますか?さて、ブラウザークライアントを使用してサーバー側でリストされたテクノロジーに基づく認証および承認システムを作成することはそれほど難しくありません。フレームワークはHTTPSと組み合わせて、認証プロセスによって生成され、ユーザーが何かをしたいときにいつでも使用される共有トークン(通常はCookieとして提示される)に基づいた安全なプロセスを提供します。このトークンは、要求が発生するたびにクライアントからサーバーに提示されます。

ローカルモバイルアプリケーションの場合、次のことを行うソリューションを求めているようです。

  1. クライアントアプリケーションには、メソッド呼び出しへのランタイムアクセスを制御する定義済みのアクセス制御リスト(ACL)があります。たとえば、特定のユーザーはメソッドからコレクションを読み取ることができますが、ACLは名前にQが含まれるオブジェクトへのアクセスのみを許可するため、コレクション内の一部のデータはセキュリティインターセプターによって静かに取得されます。Javaではこれは簡単です。呼び出し元のコードでSpring Securityアノテーションを使用し、適切なACL応答プロセスを実装するだけです。他の言語では、あなたは独力で、おそらくセキュリティライブラリを呼び出す定型のセキュリティコードを提供する必要があります。言語がAOP(アスペクト指向プログラミング)をサポートしている場合は、この状況で最大限に使用してください。
  2. セキュリティライブラリは、承認の完全なリストを現在のアプリケーションのプライベートメモリにキャッシュするため、接続を維持する必要がありません。ログインセッションの長さによっては、これが繰り返されることのない1回限りの操作になる場合があります。

何をするにせよ、独自のセキュリティプロトコルを発明しようとしないでください。、あいまいなセキュリティを使用したり。現在利用可能で無料のアルゴリズムよりも優れたアルゴリズムを作成することはできません。また、人々はよく知られたアルゴリズムを信頼しています。したがって、セキュリティライブラリが、SSL、HTTPS、SpringSecurity、およびAES暗号化トークンの組み合わせを使用してローカルモバイルアプリケーションの承認と認証を提供すると言った場合、市場ですぐに信用を得ることができます。

これがお役に立てば幸いです。さらに詳しい情報が必要な場合はお知らせください-Spring SecurityやACLなどに基づいて多数のWebアプリケーションを作成しました。


ありがとう、良い情報。いくつかの質問。最初に、盗聴が許容できる場合(許可されているかどうかがわからない場合、私のアプリケーションには実際の個人情報や貴重な情報はありませんが、理論的根拠が変わった場合)、HTTPSは実際に必要ですか?
jsuggs 2010年

必要に応じて、システム全体をHTTPSの外部で操作できます。HTTPSは秘密情報を保護するためだけのものなので、ユーザー名/パスワード/秘密が秘密に保たれることを保証するために、認証フェーズ中にHTTPSを介してそれを行うと思います。トークンが応答で渡された後、ストリームに含まれている情報(取得するために認証が必要)が盗聴者からの保護を必要としない場合は、平文でさらに要求を行うことができます。
Gary Rowe、

また、このCAS認証プロトコルの説明は役立つかもしれません:jasig.org/cas/protocol
Gary Rowe

9

Twitterは、xAuthを呼び出すバリアントをサポートすることで、oAuthの外部アプリケーションの問題に対処しました。残念ながら、この名前のスキーマは他にもたくさんありますので、整理するのが難しいかもしれません。

プロトコル oAuth です、リクエストトークンフェーズをスキップし、ユーザー名とパスワードを受信するとすぐにアクセストークンペアを発行するだけです。(ここではステップEから開始します。)この初期要求と応答は保護する必要があります-ユーザー名とパスワードをプレーンテキストで送信し、アクセストークンとシークレットトークンを受け取ります。アクセストークンペアが構成されたら、最初のトークン交換がoAuthモデルを介して行われたか、xAuthモデルを介して行われたかは、残りのセッションのクライアントとサーバーの両方には関係ありません。これには、既存のoAuthインフラストラクチャを活用でき、モバイル/ウェブ/デスクトップアプリケーションの実装とほぼ同じであるという利点があります。主な欠点は、アプリケーションにクライアントのユーザー名とパスワードへのアクセスが許可されることですが、要件によってこのアプローチが義務付けられているように見えます。

いずれにせよ、私はあなたの直感と他のいくつかの回答者の直感に同意したいと思います。ゼロから新しいものを構築しようとしないでください。セキュリティプロトコルは簡単に開始できますが、常にうまくいくことは難しく、複雑になるほど、サードパーティの開発者がそれらに対して実装できる可能性が低くなります。あなたの架空のプロトコルはo(x)Auth-api_key / api_secret、nonce、sha1 hashing-に非常に似ていますが、開発者が独自に開発する必要がある多くの既存のライブラリの1つを使用することができません。


2
「スキップリクエストトークン」エンドポイントがoAuth 2に含まれるように見えることも指摘する必要があります。これは、現在のドラフトに「パスワード」アクセス許可タイプとしてリストされています。セクション4.1.2を参照:tools.ietf.org/html/draft-ietf-oauth-v2-10#section-4.1.2
lantius

私がLonraに述べたように、私はxAuthについて詳しく調べています。具体的には最後に述べた理由で...開発者は、既成のoAuthツール/ライブラリを使用してAPIと対話できます。これは「良いこと」です。 。
jsuggs 2010年

6

パーティーには遅刻しましたが、この問題に関心のある人のために考慮すべきいくつかの追加ポイントを投入したいと思いました。私はモバイルAPIセキュリティソリューション(approov)をので、この分野全体が私の興味に間違いなく関連しています。

まず、モバイルAPIを保護しようとする際に考慮すべき最も重要なことは、モバイルAPIの価値です。銀行にとって適切なソリューションは、楽しみのためだけにやっている人にとって適切なソリューションとは異なります。

提案されたソリューションでは、少なくとも3つのパラメーターが必要になると述べています。

  • apikey-登録時に開発者に与えられる
  • タイムスタンプ-特定のapikeyの各メッセージの一意の識別子としても機能します
  • hash-タイムスタンプのハッシュ+ apisecret

これは、一部のAPI呼び出しではユーザー名/パスワードが不要であることを意味します。これは、ログインを強制したくないアプリケーション(オンラインショップでの閲覧など)に役立ちます。

これは、ユーザー認証の問題とは少し異なる問題であり、ソフトウェアの認証または証明に似ています。ユーザーはいないが、それでもAPIへの悪意のあるアクセスがないことを確認したい。したがって、APIシークレットを使用してトラフィックに署名し、APIにアクセスするコードを正規のものとして識別します。このソリューションの潜在的な問題は、アプリのすべてのバージョンの秘密を明かさなければならないことです。誰かがシークレットを抽出できれば、APIを使用できるようになり、ソフトウェアを偽装して好きなように実行できます。

その脅威に対抗するために、データの価値に応じてできることはたくさんあります。難読化は、秘密の抽出を困難にする簡単な方法です。あなたのために、Androidのためにそれを行うツールがありますが、ハッシュを生成するコードが必要であり、十分に熟練した個人は常に直接ハッシュを行う関数を呼び出すことができます。

ログインを必要としないAPIの過度の使用を軽減する別の方法は、トラフィックを抑制し、疑わしいIPアドレスを識別してブロックすることです。あなたが行きたい努力の量は、あなたのデータがどれほど貴重であるかに大きく依存します。

それを超えて、あなたは簡単に私の日常業務の領域に入り始めることができます。とにかく、APIを保護するもう1つの側面は、重要であり、フラグを立てたいと考えていることです。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.