React/NodeJS/Passportでtwitterログインを実装してみた
こちらの記事をベースにしてReactJS/NodeJSのシステムにtwitterログインを組み込んでみた。 qiita.com
主に異なるのは型指定が緩めななんちゃって
typescriptを使っているところか。
蓋々交換機能
技術的なこと
passport-config.ts
export default function passportConfig() { var TWITTER_CONSUMER_KEY = "*****"; var TWITTER_CONSUMER_SECRET = "*******"; var passport = require("passport"), TwitterStrategy = require("passport-twitter").Strategy; // Sessionの設定 passport.serializeUser(function (user, done) { done(null, user); }); passport.deserializeUser(function (obj, done) { done(null, obj); }); passport.use( new TwitterStrategy( { consumerKey: TWITTER_CONSUMER_KEY, consumerSecret: TWITTER_CONSUMER_SECRET, callbackURL: "https://********/auth/twitter/callback", }, function (token, tokenSecret, profile, done) { passport.session.user = profile; // tokenとtoken_secretをセット profile.twitter_token = token; profile.twitter_token_secret = tokenSecret; process.nextTick(function () { return done(null, profile); }); } ) ); }
auth.ts
NodeJSでtwitter認証からのコールバックなどを担当するコントローラ。
import * as express from "express"; import * as session from 'express-session'; import { Request } from "./interface/express.Request"; const passport = require("passport"); export class Auth{ public router: express.Router; constructor() { this.router = express.Router(); this.router.get("/twitter", passport.authenticate('twitter')); this.router.get("/twitter/success", this.success); this.router.get("/twitter/callback", passport.authenticate('twitter', { successRedirect: 'https://******/api/v2/auth/twitter/success', failureRedirect: 'https://******/' }) )} private success(req:Request,res:express.Response):void{ if(req.session.passport !== undefined){ res.json(req.session.passport.user.username); }else{ res.sendStatus(401); } } }
express.Requestインターフェースの拡張
import * as Express from 'express'; export interface Request extends Express.Request { session:any; }
app.ts
import { Auth } from './auth'; import * as session from 'express-session'; import passportConfig from './passport-config'; passportConfig(); const passport = require("passport"); app.use(passport.initialize()); app.use(passport.session()); app.use( session({ secret: '********', resave: false, saveUninitialized: false, cookie:{ httpOnly: true, secure: true, maxage: 1000 * 60 * 30 } }) );
ReactでNodeJS/Passportから認証情報を受け取る
credentialsオプションが必要。
const response = await fetch('/auth/twitter/success', { method:'GET', credentials: "include", headers: { Accept: "application/json", "Content-Type": "application/json", "Access-Control-Allow-Credentials": true } });
認証が終わったタイミングで認証情報を受け取る
認証のためのウインドウを開き、 そのウインドウが閉じられたタイミングで親の画面をリロードする。 リロードの際に認証情報を受け取っている。
onClick={()=>{ const authWindow = window.open('/auth/twitter','newTab'); var timer = setInterval(function() { if(authWindow.closed) { clearInterval(timer); window.location.reload(); } }, 1000); }}