開発中のアプリケーションにOAuth 2ベースの認証モデルを実装しています。エンドユーザーにFacebookでログインする機能、またはでメール/パスワードアカウントを設定する機能を提供しています。私のAPI。メール/パスワード認証はパスワード付与を使用して簡単です。Facebookのログインフローに関するヘルプを探しています。
私のアプリケーションは、JSON API(私の「リソースサーバー」)を使用するシングルページアプリケーションです。 Facebook JavaScript SDKを使用して、Webアプリがエンドユーザーの電子メールアドレスにアクセスすることを承認しています。
ユーザーがFacebookでログインしようとすると、プロセス全体がFacebookとWebアプリケーションの間で行われます。その結果、私のAPIは、FacebookのOAuthサーバーでトークンを検証するまで、Facebook認証トークンを信頼できません。
今のところ、Facebook accessToken
をAPIに渡しています。APIは、「me」グラフAPIのサーバー間呼び出しを介して、Facebookでのユーザーの承認を確認します。これが私の現在の設定の図です:
したがって、この時点で、Facebookアクセストークンと電子メールアドレスを持っています。 APIサーバーとWebアプリケーションの間でセッションを永続化する必要があります。この時点でセッションを永続化する標準的な方法は何ですか?
OAuthのドキュメントを読むと、これは私のAPIサーバーとWebアプリケーションの間で「暗黙の許可」を必要とするタイプの状況のようですが、その許可タイプは 私が使用しているOAuthパッケージ 。パッケージの作成者も 暗黙の付与は「非常に安全ではない」と言っています 。
私の他の考えは、ランダムなクライアントIDとクライアントシークレットを作成し、それらをWebアプリに返して、資格情報の付与を介してアクセストークンを要求できるようにすることです。これは私には非論理的に思えます。アクセストークンを作成してクライアントに送り返して直接使用しないのはなぜですか?
Facebookからの最初の承認後、WebアプリとAPIサーバー間で直接認証を維持する必要がありますが、それは正しいですか?
ランダムなパスワードを生成してユーザーにHTTPBasicトークンを送信するだけでよいことに気付きましたが、メリットがない限り、OAuthを使用したいと思います。
DynamicApis.comであなたが話していることを正確に実行しています。
これが私たちがしていることです:
1)ユーザーにログインを促します。この場合、oAuth2アクセストークンを自分で作成しますOR Facebook、githubなどにプロキシできます...しかし、結局のところ、 DynamicApisのセッションを駆動するoAuth2トークンは私たちが所有していますが、GitHubなどのサードパーティによって完全に作成された場合、残りのワークフローはまったく同じになります。
2)ユーザーは電子メール/パスワードでログインします。
3)ユーザーは認証コードを使用してDynamicApis.comにリダイレクトされます
4)DynamicApis.comは、アクセストークン(サーバー間呼び出し)の認証コードを交換します。 この時点で、oAuth2フローについて説明しました
5)この時点で、(たとえば暗号化)そのユーザーに代わって返され、発行されたアクセストークンを、セッションプロバイダー(SQL Serverベースとしましょう)。このセッションプロバイダーはDynamicApis.comが所有しています。
6)これで、セッションプロバイダーは通常どおりに機能します。ログインしたユーザーを表すキー(ハッシュ/暗号化されたアクセストークン)と、そのキーに関連付けられた複数のキー/値があります。
セッションプロバイダーは、ユーザーに代わってデータベースまたは使用するものに保存するデータのセッション状態(キーと値のペア)を保持します
セッションプロバイダーの有効期限は、アクセストークンの有効期限と同じ(またはアクセストークンよりも短い)必要があります。
ユーザーがログアウトすると、セッションは破棄されます。
セッションキーは、Cookie、URLに暗号化された形式で存在するか、ページに非表示になっている必要があります(セッションキーが今日保持されているのと同じように)
7)プーフ。ログインしたユーザーのセッションがあります。
必要に応じて、組み込みのASP.NETセッションプロバイダーロジックの多くを実際に再利用できます。または、DynamicApis.comにあるように、独自の自家製システムを構築することもできます。
可能であれば、oauth実装で、独自のカスタム付与クラスと認証プロバイダーをコーディングできます。
この種の認証用に新しいクライアントIDを定義します。
ユーザーはFacebookを使用して認証します。
Facebookはクライアントのトークンを生成します。
クライアントは、このアクセストークン、メールアドレス、認証タイプ/クライアントIDを使用してバックエンドアプリケーションにリクエストを送信します(「facebook」としましょう)
カスタム付与がトークンタイプを決定します(Springsecurity-oauth実装)
String clientId = tokenRequest.getClientId();
ClientDetails client = clientDetailsService.loadClientByClientId(clientId);
Map<String, String> parameters = tokenRequest.getRequestParameters();
String username = parameters.get("username"); //username is email
String password = parameters.get("password"); //password is fb access token
Authentication authentication = null;
if ("facebook".equals(clientId)) {
authentication = new FacebookAuthenticationToken(username, password);
} else {
authentication = new UserAuthenticationToken(username, password);
}
authentication = authenticationManager.authenticate(authentication);
認証プロバイダーはFacebookトークンをチェックして検証します。
public class FacebookAuthenticationProvider implements AuthenticationProvider {
@Autowired
private FacebookApi facebookApi;
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
String username = authentication.getName();
String password = (String) authentication.getCredentials();
// you can check your facebook session store
boolean valid = facebookApi.isValidToken(username, password);
if (!valid) {
throw new BadCredentialsException("Username not found.");
}
Collection<? extends GrantedAuthority> authorities = user.getAuthorities();
return new FacebookAuthenticationToken(user, password, authorities);
}
@Override
public boolean supports(Class<?> authentication) {
return FacebookAuthenticationToken.class.isAssignableFrom(authentication);
}
}
サンプルとしてコードを入れました。
私は通常、最初のFacebookログイン(メールの取得)後に、ユーザーに内部アプリのパスワードを設定するように強制します。その後、すべてがはるかに簡単になります。あなたは私が何を意味するのか理解することができます。