OAuth2の認証フローを知りたかったので、ソーシャルログイン後、メールアドレスを取得するところまでを実装してみました。
抽象化を防ぐため、可能な限りサードパーティのライブラリは使ってません。
事前準備
Google, Facebookそれぞれのdeveloperページでアプリを作成し、クライアントID
、クライアントシークレット
を取得しておく。
またリダイレクトURL
(今回はhttp://localhost:3000/oauth2callback
)も忘れずに登録しておく。
Google: https://console.cloud.google.com/apis/
Facebook: https://developers.facebook.com/apps/
ググったら親切なページがいっぱい出てくるので、具体的なやり方については割愛します。
また、プロジェクトディレクトリで必要なライブラリをインストールしておきます。
$ npm i -S express node-fetch
const express = require('express')
const fetch = require('node-fetch')
const qs = require('querystring')
const client_id = '{クライアントID}'
const client_secret = '{クライアントシークレット}'
const redirect_uri = 'http://localhost:3000/oauth2callback'
const response_type = 'code'
const scope = 'email'
const auth_uri = 'https://accounts.google.com/o/oauth2/v2/auth'
const token_uri = 'https://www.googleapis.com/oauth2/v4/token'
const email_uri = 'https://www.googleapis.com/oauth2/v3/userinfo'
const app = express()
app.get('/', (req, res) => {
const params = qs.stringify({
client_id,
redirect_uri,
response_type,
scope,
})
res.redirect(302, `${auth_uri}?${params}`)
})
app.get('/oauth2callback', (req, res) => {
fetch(token_uri, {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: qs.stringify({
client_id,
client_secret,
code: req.query.code,
grant_type: 'authorization_code',
redirect_uri,
})
}).then(res => res.json()).then(json => {
return fetch(email_uri, {
headers: {
Authorization: `Bearer ${json.access_token}`,
}
})
}).then(res => res.json()).then(json => {
res.end(json.email)
})
})
app.listen(3000, () => console.log('listening on port 3000'))
$ node google.js
ブラウザから http://localhost:3000 にアクセス
const express = require('express')
const fetch = require('node-fetch')
const qs = require('querystring')
const client_id = '{クライアントID}'
const client_secret = '{クライアントシークレット}'
const redirect_uri = 'http://localhost:3000/oauth2callback'
const response_type = 'code'
const auth_uri = 'https://www.facebook.com/v2.12/dialog/oauth'
const token_uri = 'https://graph.facebook.com/v2.12/oauth/access_token'
const email_uri = 'https://graph.facebook.com/me'
const app = express()
app.get('/', (req, res) => {
const params = qs.stringify({
client_id,
redirect_uri,
response_type,
})
res.redirect(302, `${auth_uri}?${params}`)
})
app.get('/oauth2callback', (req, res) => {
let params = qs.stringify({
client_id,
client_secret,
code: req.query.code,
redirect_uri,
})
fetch(`${token_uri}?${params}`)
.then(res => res.json())
.then(json => {
const access_token = json.access_token
params = qs.stringify({
access_token,
fields: 'email',
})
return fetch(`${email_uri}?${params}`)
})
.then(res => res.json())
.then(json => {
res.end(json.email);
})
})
app.listen(3000, () => console.log('listening on port 3000'))
$ node facebook.js
ブラウザから http://localhost:3000 にアクセス
まとめ
passportやnode-oauthを使った事例はよく見かけるのですが、内部が抽象化されていてフローを理解できなかったので、fetchのみで実装してみました。
リクエストメソッドやパラメータの渡し方に違いはありますが、規格は同じなのでやはり実装は似通っていますね。
何かの参考になれば幸いです。ありがとうございました。