28
22

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

nodeでシンプルにOAuth2認証(google, facebook)

Last updated at Posted at 2018-03-10

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

Google

google.js
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 にアクセス

Facebook

facebook.js
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のみで実装してみました。
リクエストメソッドやパラメータの渡し方に違いはありますが、規格は同じなのでやはり実装は似通っていますね。

何かの参考になれば幸いです。ありがとうございました。

28
22
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
28
22

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?