これまでのところ、サーバーレンダリングアプリのみを扱いました。ユーザーがユーザー名/パスワードまたはOAuthプロバイダー(Facebookなど)を使用してログインした後、サーバーはセッションCookieを設定しますが、関連ページにリダイレクトします。
しかし、今は、よりモダンなアプローチを使用して、ReactをフロントエンドとJSON APIバックエンドで使用して、アプリを構築しようとしています。これの標準的な選択は、JSON Webを使用することです。認証用のトークンですが、セッション/ローカルストレージまたはどこにでも保存できるように、JWTをクライアントに提供する方法を理解するのに苦労しています。
よりよく説明する例:
ユーザーはリンク(_/auth/facebook
_)をクリックしてFacebook経由でログインします
ユーザーがリダイレクトされ、Facebookログインフォームまたは許可ダイアログ、あるいはその両方が表示されます(必要な場合)。
Facebookはユーザーを_/auth/facebook/callback
_にリダイレクトし、認証コードを牽引します。サーバーはこれをアクセストークンとユーザーに関するいくつかの情報と交換します
サーバーは情報を使用してDBでユーザーを検索または作成し、次にユーザーデータの関連サブセット(IDなど)を含むJWTを作成します
???
この時点で、私はユーザーがReactアプリ(たとえば_/app
_)と呼ばれる)のメインページにリダイレクトされるようにして、フロントエンドが引き継ぐことができるようにします。しかし、リダイレクトのためのクエリ文字列にそれを置く以外に、途中でJWTを失うことなくそれを行う(エレガントな)方法は考えられません(_/app?authtoken=...
_)-それはアドレスに表示されますreplaceState()
などを使用して手動で削除するまでは、少し奇妙に思えます。
実際、これが通常どのように行われるのか疑問に思っているだけで、ここで何か不足していると確信しています。サーバーは、Node(Koa with Passport))です。
編集:明確にするために、クライアントにトークンを提供するための最良の方法(保存できるように)を尋ねていますOAuthリダイレクトフローの後 Passportを使用する。
私は最近、この同じ問題に遭遇し、ここでも他の場所でも解決策を見つけられなかったため、 このブログ投稿 を私の詳細な考えとともに書きました。
TL; DR:OAuthログイン/リダイレクト:
<script>
タグ付け:localStorage
に保存します(JWTを使用したログインは基本的に「JWTをlocalStorage
に保存する」と同等であるため、私のお気に入りのオプションは#3でしたが、考慮していない欠点がある可能性があります。他の人の考えを聞いて興味がありますここに。)
お役に立てば幸いです。
クライアント:トークンを解析してローカルストレージに保存し、ページの再読み込み後に使用できるようにします。
ログアウト
これはサーバー側からのログイン要求です。ヘッダーにトークンを格納しています:
router.post('/api/users/login', function (req, res) {
var body = _.pick(req.body, 'username', 'password');
var userInfo;
models.User.authenticate(body).then(function (user) {
var token = user.generateToken('authentication');
userInfo = user;
return models.Token.create({
token: token
});
}).then(function (tokenInstance) {
res.header('Auth', tokenInstance.get('token')).json(userInfo.toPublicJSON());
}).catch(function () {
res.status(401).send();
});
});
これは、反応側のログインリクエストです。ユーザー名とパスワードが認証に合格すると、ヘッダーからトークンを取得し、ローカルストレージにトークンを設定します。
handleNewData (creds) {
const { authenticated } = this.state;
const loginUser = {
username: creds.username,
password: creds.password
}
fetch('/api/users/login', {
method: 'post',
body: JSON.stringify(loginUser),
headers: {
'Authorization': 'Basic'+btoa('username:password'),
'content-type': 'application/json',
'accept': 'application/json'
},
credentials: 'include'
}).then((response) => {
if (response.statusText === "OK"){
localStorage.setItem('token', response.headers.get('Auth'));
browserHistory.Push('route');
response.json();
} else {
alert ('Incorrect Login Credentials');
}
})
}