お仕事でLINEログインをチームで実装する機会があったので、自分でもできるように小さなサービスを作ってみようと思います。
まずは、LINEログインボタンを表示し、それを押すとLINEログインの実行を行い、ログインしたアカウント情報を表示するところまで実装します。
サーバサイドはNode.jsを利用し、インフラとしてはHerokuを利用します。
(LINEからのcallback URLを指定する必要があるので、Herokuが便利です。)
事前準備
Node: v12.13.1
Heroku CLI: 7.35.0
Nodeアプリ環境の構築
https://github.com/noboru-i/line-note/commit/d0d935c6075b5f3f007b306d7aeaf14b2134355e
https://github.com/noboru-i/line-note/commit/94518c502c16b300e63bc8d4bdf73eb95d9b3d9d
まずは、サンプルを持ってきて、フォルダ名などをリネーム。
git clone https://github.com/heroku/node-js-getting-started.git
mv node-js-getting-started line-note
cd line-note
npm install
その後、READMEやpackage.jsonのアプリ名部分などを整理。
Heroku環境の作成・仮デプロイ
heroku create line-note
git push heroku master
heroku open
これで、とりあえずサンプルのNode.jsアプリが動作していることを確認できた。
LINE Developersにて、LINEログインチャンネルを作成
https://developers.line.biz/console/ より、個人のLINEアカウントでログイン。
適当な名前を入れてProviderを作成。
いろいろ適当に入力し、LINEログインチャンネルを作成。
"LINE Login"タブの"Callback URL"に、 https://line-note.herokuapp.com/callback を指定。
Herokuアプリの環境変数として、チャンネルID / チャンネルシークレットを保存しておく。
heroku config:set LINECORP_PLATFORM_CHANNEL_CHANNELID=(コンソールで確認できる"Channel ID")
heroku config:set LINECORP_PLATFORM_CHANNEL_CHANNELSECRET=(コンソールで確認できる"Channel secret")
ローカルでの確認用に、 .env
にも同様に設定しておく。
(とはいえ、callbackが本番ドメインの方に来るので、ローカル環境は使いませんでした。)
LINECORP_PLATFORM_CHANNEL_CHANNELID=(コンソールで確認できる"Channel ID")
LINECORP_PLATFORM_CHANNEL_CHANNELSECRET=(コンソールで確認できる"Channel secret")
コードの修正し、LINEログインを実装
とりあえずログインボタンを作れればいいので、 views/pages/index.ejs
を開いて、上の方にあるボタンを以下のように書き換える。
<a type="button" class="btn btn-lg btn-default" href="/login">LINEログイン</a>
次に、 /login
にアクセスされたときに、LINEログインのページにリダイレクトする仕組みを作っておく。
同様に、 /callback
にアクセスが来たとき、リクエストパラメータの code を出力することにしておく。
index.js
を、以下のように変更。
const express = require('express')
const path = require('path')
const PORT = process.env.PORT || 5000
const querystring = require('querystring');
express()
.use(express.static(path.join(__dirname, 'public')))
.disable('etag')
.set('views', path.join(__dirname, 'views'))
.set('view engine', 'ejs')
.get('/', (req, res) => res.render('pages/index'))
.get('/login', (req, res) => {
const query = querystring.stringify({
response_type: 'code',
client_id: process.env.LINECORP_PLATFORM_CHANNEL_CHANNELID,
redirect_uri: 'https://line-note.herokuapp.com/callback',
state: 'hoge', // TODO: must generate random string
scope: 'profile',
})
res.redirect(301, 'https://access.line.me/oauth2/v2.1/authorize?' + query)
})
.get('/callback', (req, res) => {
res.send('code: ' + req.query.code)
})
.listen(PORT, () => console.log(`Listening on ${ PORT }`))
これを git push heroku master
にてデプロイすると、ログインのフローが確認できる。
まだ、codeが見えるだけ。
LINEの情報を取得する
https://github.com/noboru-i/line-note/commit/85ba05cae417ea5b004ff60fac1dc159c97f13b6
https://github.com/noboru-i/line-note/commit/d6e3f23e4a533147132c4ee613e57de746085d39
codeからaccess tokenを取得、それを利用してユーザ情報を取得する。
まずは、サーバからAPIを実行するために、requestモジュールを導入。
npm install request --save
そして、以下のように実装する。
const request = require('request')
express()
// ...
.get('/callback', (req, res) => {
request
.post({
url: `https://api.line.me/oauth2/v2.1/token`,
form: {
grant_type: "authorization_code",
code: req.query.code,
redirect_uri: 'https://line-note.herokuapp.com/callback',
client_id: process.env.LINECORP_PLATFORM_CHANNEL_CHANNELID,
client_secret: process.env.LINECORP_PLATFORM_CHANNEL_CHANNELSECRET,
}
}, (error, response, body) => {
if (response.statusCode != 200) {
res.send(error)
return
}
request
.get({
url: 'https://api.line.me/v2/profile',
headers: {
'Authorization': 'Bearer ' + JSON.parse(body).access_token
}
}, (error, response, body) => {
if (response.statusCode != 200) {
res.send(error)
return
}
res.send(body)
})
})
})
.listen(PORT, () => console.log(`Listening on ${ PORT }`))
これによって、以下のようなレスポンスが画面に表示される。
{
userId: "XXX",
displayName: "XXX",
pictureUrl: "https://profile.line-scdn.net/ch/v2/p/XXX"
}
今回やらなかったこと
access_token / refresh_token
access_token
は30日で有効期限切れとなります。
access_token
が失効したあと、10日以内に refresh_token
を利用すると、再度 access_token
と refresh_token
を取得できます。
stateのチェック
CSRF対策のため、 /authorize
にアクセスする際のstateパラメータにランダムな文字列を生成して、 /callback
で返却されたstateとチェックする必要があります。
セッションなどに一時的に保存して、チェックする必要があります。
参考
https://developers.line.biz/ja/docs/line-login/web/try-line-login/
line-login-starterというサンプルアプリの使い方が書いてある。
https://github.com/nkjm/line-login
LINEログインのunofficial SDK。今回は参考として。