お仕事で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ログインを実装
https://github.com/noboru-i/line-note/commit/11af00edf4399acbc0452ba316d3a094031fd989
とりあえずログインボタンを作れればいいので、 views/pages/index.ejs
を開いて、上の方にあるボタンを以下のように書き換える。
<atype="button"class="btn btn-lg btn-default"href="/login">LINEログイン</a>
次に、 /login
にアクセスされたときに、LINEログインのページにリダイレクトする仕組みを作っておく。
同様に、 /callback
にアクセスが来たとき、リクエストパラメータの code を出力することにしておく。index.js
を、以下のように変更。
constexpress=require('express')constpath=require('path')constPORT=process.env.PORT||5000constquerystring=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)=>{constquery=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 stringscope:'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
そして、以下のように実装する。
constrequest=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。今回は参考として。