あいつの日誌β

働きながら旅しています。

React + Redux + JWT tutorial(1)

あらすじ

SPA で認証機能を使いたいので練習します。

対象読者

  • redux の middleware について大体わかる
  • JWT について大体わかる

大体わからない場合は以下をご一読下さい

Server を用意する

サーバーに以下の機能を実装します。

  • login に成功したら token を生成して返す
  • token を使った API を call する事ができるようになる
  • logout すると token を使った API を call しても失敗する
  • 再度 login すると新しい token を生成して返す
% mkdir practice-react-redux-jwt && cd $_
% npm install --save express express-jwt errorhandler morgan body-parser jsonwebtoken
% npm init -y

create server.js:

const SECRET_KEY = 'SECRET_KEY';

const logger       = require('morgan'),
      http         = require('http'),
      express      = require('express'),
      errorhandler = require('errorhandler'),
      bodyParser   = require('body-parser'),
      jwt          = require('jsonwebtoken'),
      jwtCheck     = require('express-jwt')({secret: SECRET_KEY});

const app = express();
const port = process.env.PORT || 3000;

app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());

if (process.env.NODE_ENV === 'development') {
  app.use(logger('dev'));
  app.use(errorhandler())
}

app.get("/", function(req, res) {
  res.sendfile(__dirname + '/www/index.html');
})

app.get('/api/hello', function(req, res) {
  res.status(200).send('hello, public');
});

app.use('/api/private', jwtCheck);
app.get('/api/private/hello', function(req, res) {
  res.status(200).send('hello, private');
});

app.post('/api/sessions', function(req, res) {
  const token = jwt.sign({name: 'username'}, SECRET_KEY, { expiresIn: 60*60*5 });
  res.status(201).send({
    id_token: token
  });
});

http.createServer(app).listen(port, function (err) {
  console.log('listening in http://localhost:' + port);
});

今回は Frontend の解説がメインなので Backend は最小限の機能にしています。 JWT の実装としては気が狂っている感じがしますが練習用のサーバープログラムなのでご了承下さい。

http://qiita.com/kaiinui/items/21ec7cc8a1130a1a103a

動作確認

/api/hello はいつでも call 可能

% curl http://localhost:3000/api/hello                                                                                          
hello, public

/api/private/hello へのアクセスには Token が必要

% curl http://localhost:3000/api/private/hello
UnauthorizedError: No authorization token was found

token を取得する

% curl -X "POST" http://localhost:3000/api/sessions
{"id_token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoidXNlcm5hbWUiLCJpYXQiOjE0NzYzNDAyNTUsImV4cCI6MTQ3NjM1ODI1NX0.8CDpnsFZGYHy47xHzodckY1DKUG6j1cpyKRbbzpx9oQ"}

token を使用して /api/private/hello へのアクセスができる事を確認する

% TOKEN=`curl -X "POST" http://localhost:3000/api/sessions | jq .id_token -r` 
% curl -H "Authorization: Bearer ${TOKEN}" http://localhost:3000/api/private/hello
hello, private

今回はサーバー側の実装を紹介しました。 次回はフロント側の実装を紹介します。