3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Node.js(Express)とRenderでLINEログイン機能を実装する

Posted at

はじめに

前回はLINEが用意してくれているデモアプリをつかって、LINEログイン機能を試しました。
今回は、Node.jでの実装を通して、内部でどのような処理をしているのかを確かめます。

前提

本記事は以下のことは完了している想定で進めます。

  • Node.jsをインストール済であること
  • GitHubアカウントをもっていること
  • Renderアカウントをもっていること
  • LINE関連の設定が終わっていること(設定詳細はこちら
  • LINEログインチャネルの作成方法がわかっていること(作成方法はこちら

LINEログインの仕組み

LINEログインは以下のフローに沿って実施されます。
(出典:ログインのフロー

英語で書いてありますが、大きく分けて3つの処理があります。

1. ログインの要求

ユーザーがWebアプリ上でLINEログインをしようとすると、WebアプリはLINEのプラットフォームのログイン認証用のURLへリダイレクトします。
ここは開発者の実装が必要な部分です。

2. ログイン認証、認可

LINEプラットフォームは、ユーザーに対してログイン認証画面を表示させ、ユーザーはLINEの情報を入力して認証を行います。
ユーザーがアプリへのアクセスを許可すると、認可が完了します。
ここは開発者の実装が不要です。

認証、認可の処理はLINE側で実行してくれます。

3. ログイン情報の検証、情報の取得

認証、認可が完了すると、LINEプラットフォームはWebアプリへ再度リダイレクトします。
Webアプリ側ではリクエストの正当性の検証や、アクセストークン、プロファイル情報の取得などを行い、問題なければユーザーにログイン後の結果を表示させます。
ここは開発者の実装が必要です。

以上のように、ログイン認証についてはLINE側で実施してくれるため、開発者としては

  • ログイン要求の処理
  • 認証完了後の処理

の2つを実装すればよいことになります。

Node.jsでログイン処理を実装する

なにもないところから処理を作っていきます。
なお、本処理ではOSにはMac、開発ツールとしてはVS Codeを使っています。

初期設定

package.jsonの生成

適当なフォルダを作成します。(ここでは「login-demo」)
ターミナルでフォルダに移動して

npm init

を実行します。

以下のようにpackage nameversisonなどを聞かれます。
すべてデフォルトでよいのでenterキーを押して次々進みます。
最終的に問題ないか聞かれるので、「yes」を入力して処理を完了させます。
image.png

完了すると、package.jsonファイルが生成されます。
image.png

package.jsonの編集

生成したpackage.jsonに以下の2項目を追加します。

package.json
{
  "name": "login-demo",
  "version": "1.0.0",
  "description": "",
+  "type": "module",
  "main": "index.js",
  "scripts": {
+    "start": "node index.js",
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "express": "^4.19.2"
  }
}

expressのインストール

expressというサーバーサイドの処理を書くのに便利なNode.jsのフレームワークをインストールします。

npm install express

実行が完了すると、以下のようなフォルダとファイルが生成されます。
image.png

以上で初期設定は完了です。

ログイン処理の実装

index.jsというファイルを作成します。
ここに具体的な処理を追加していきます。
image.png

リクエストを受け取る

ログインフローで確認したログイン要求と認証完了後の処理の他、アプリのルートパスへのリクエストを受け取る処理を書いていきます。

index.js
import express from "express";
import path from "path";
import { fileURLToPath } from "url";

const app = express();
const __dirname = path.dirname(fileURLToPath(import.meta.url));

// ルートパスへのリクエスト
app.get("/", (req, res) => {
  res.sendFile(path.join(__dirname, "login.html"));
});

// ログイン要求のリクエスト
app.get("/login", (req, res) => {

});

// 認証完了後のリクエスト
app.get("/success", (req, res) => {
  res.status(200).send("success");
});

ルートパスへのリクエスト

アプリにアクセスされたらhtmlファイルを表示させます。
本来フロント側は別でサーバーを立ててやりますが、今回は簡易化のためにサーバー側で直接htmlを返します。
このファイルは後ほど作成します。

ログイン要求へのリクエスト

Webアプリでログインボタンを押したときに、LINEプラットフォームのログイン認証URLにリダイレクトさせる処理です。こちらは後ほど処理を作成するので一旦処理はなしにしています。

認証完了後のリクエスト

本来はLINEプラットフォームからのリクエストを検証して、情報を取得する処理をしてから、ログイン成功画面を表示させますが、今回は単純にサーバーから「success」を返すだけにします。

LINEプラットフォームへのリダイレクト

ログインを要求されたときのリダイレクト処理を記載します。

index.js(一部抜粋)
import crypto from "crypto";

/* 一部処理の記載を省略 */

// リダイレクトURL生成処理
const createRedirectUrl = () => {
  const bytes = crypto.randomBytes(32);
  const state = bytes.toString("base64url");

  const redirectUrl =
    "https://access.line.me/oauth2/v2.1/authorize?" +
    "response_type=code" +
    `&client_id=${process.env.CHANNEL_ID}` +
    `&redirect_uri=${process.env.CALLBACK_URL}` +
    `&state=${state}` +
    "&scope=profile%20openid";
  return redirectUrl;
};

/* 一部処理の記載を省略 */

// ログイン要求のリクエスト
app.get("/login", (req, res) => {
  const redirect = createRedirectUrl();
  res.redirect(redirect);
});

リダイレクトURL生成処理を作成し、それをログイン要求時の処理として追加しています。
リダイレクトのパラメータについて1つずつ確認します。

response_type

固定でcodeとなります。OAuth2.0認証で使われるパラメータのようです。

client_id

LINEログインチャネルのチャネルIDです。
後ほど設定する環境変数から取得するようにしています。

redirect_uri

ログインフローで確認した、ログイン認証成功後にリダイレクトされるURLです。
これも環境変数から取得するようにします。

state

CSRF(クロスサイトリクエストフォージェリ)を防止するために使用されるパラメータです。
ログイン認証が成功すると、リクエストに同じstateが設定されて返却されます。
生成したstateと返却されたstateが一致するかを確かめることで、正当なリクエストかどうかを確認します。

ランダムに生成する必要があるので、今回はNode.jsのcryptoモジュールを使用しています。
Node.jsに含まれているのでnpm installは不要です。

scope

Webアプリ側で使用したいユーザープロファイルの情報です。
ここに含めたパラメータについて、許可してもいいかユーザーに確認します。
5通りの指定方法がありますが、詳細は以下から確認してください。
ウェブアプリにLINEログインを組み込む - スコープ

リッスンするポートの設定

index.js
/* 一部処理の記載を省略 */

const PORT = 3000;

/* 一部処理の記載を省略 */

// リッスンするポートの設定
app.listen(PORT, () => {
  console.log(`Server is running on http://localhost:${PORT}`);
});

最後にサーバーがリッスンするポート番号を指定します。

サーバーの処理はこれで完了です。

全体のソースを表示
index.js
import express from "express";
import path from "path";
import { fileURLToPath } from "url";

import crypto from "crypto";

const PORT = 3000;
const app = express();
const __dirname = path.dirname(fileURLToPath(import.meta.url));

// リダイレクトURL生成処理
const createRedirectUrl = () => {
  const bytes = crypto.randomBytes(32);
  const state = bytes.toString("base64url");

  const redirectUrl =
    "https://access.line.me/oauth2/v2.1/authorize?" +
    "response_type=code" +
    `&client_id=${process.env.CHANNEL_ID}` +
    `&redirect_uri=${process.env.CALLBACK_URL}` +
    `&state=${state}` +
    "&scope=profile%20openid";
  return redirectUrl;
};

// ルートパスへのリクエスト
app.get("/", (req, res) => {
  res.sendFile(path.join(__dirname, "login.html"));
});

// ログイン要求のリクエスト
app.get("/login", (req, res) => {
  const redirect = createRedirectUrl();
  res.redirect(redirect);
});

// 認証完了後のリクエスト
app.get("/success", (req, res) => {
  res.status(200).send("success");
});

// リッスンするポートの設定
app.listen(PORT, () => {
  console.log(`Server is running on http://localhost:${PORT}`);
});

画面表示用htmlの作成

ルートパスへアクセスされた際に表示させる「login.html」を作成します。
image.png

login.html
<!DOCTYPE html>
<html lang="jp">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Line Login Demo</title>
</head>
<body>
    <h3>LINE Login</h3>
    <a href="/login" id="login">Login</a>
</body>
</html>

複雑な見た目にする必要はないので、リンク押下でログイン要求の処理へ飛ばすようにしています。

以上でログイン処理の実装は完了です。

Webアプリの公開

アプリができたので公開していきます。
大まかな流れを紹介します。

Githubリポジトリに配置する

Githubに任意のリモートリポジトリを作成し、そこに作成したリソースを配置します。
これをベースとしてアプリをデプロイします。

RenderでWebアプリを作る

Webアプリのデプロイ

Renderは無料でWebアプリなどを手軽に作れるサービスです。
Githubに公開しているリポジトリを元にWebアプリを作ることができます。

RenderのサイトからWeb Serviceの新規作成を行います。
作成元に先ほどのリポジトリを選択し、以下のように設定を行います。

「Instance Type」は「Free」にしておきます。

「Environment Variables」には、リダイレクト生成処理の際に指定したCHANNEL_IDCALLBACK_URLを設定します。
CHANNEL_IDはLINE DevelopersのLINEログインチャネル-チャネル基本設定から確認できます。
CALLBACK_URLは現時点ではわからない(WebアプリのURLはこれから発行される)ので、適当な値を入れておきます。後ほど修正します。

設定し終えたらWeb Serviceを作成します。

デプロイが完了するとURLが発行されます。
そのURLにアクセスすると、以下のような画面が表示されます。

これでWebアプリの作成は一旦成功です。

設定変更

リダイレクトURLを設定するため、先ほどの環境変数CALLBACK_URLを修正しましょう。
実装部分で作成した、ログイン成功後の処理にリダイレクトしたいので、生成されたWebアプリのURLの末尾に/successを追加したものを、CALLBACK_URLに設定してください。

設定を保存すると、再度デプロイが走ります。

LINE ログインチャネルの設定

リダイレクト先のURLはLINE側にも設定する必要があります。
以下のようにコールバックURLに、環境変数に設定したものと同じURLを設定します。

これでアプリの公開設定は完了です。

ログイン処理を試す

早速作成したログイン処理を試してみましょう

WebアプリのURLにアクセスします。

質素なリンクを押下すると、LINEの認証画面に移ります。

QRコードでのログインもできるので、お好きな方でログインしてみてください。

ログインが成功すると、以下の画面が表示されます。

全く何の意味もないログイン認証ですが、これで自作のアプリを通してログイン機能を試すことができました。

まとめ

自分で一からログイン機能を作成することに挑戦してみました。
ログイン要求を受け取る処理、認証完了後の処理さえ書いてしまえば、簡単にログイン機能を実装できることがわかりました。
実際にはもっとたくさんの処理やチェックを盛り込む必要があるかもしれませんが、基本的にはあまり難しくなくログイン機能を実装できるので、とても便利ですね。

また、何度かRenderを使ってアプリのデプロイをしてきましたが、こちらも無料とは考えられないくらいの手軽さ、便利さです。

これからもいろいろな機能を試すのに使っていきたいと思いました。

3
1
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
3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?