---
title: "LINEログイン APIの実装手順：PKCE・IDトークン検証と既存会員IDの連携"
url: "https://www.issoh.co.jp/tech/details/19337/"
published: 2026-11-05
updated: 2026-11-05
categories: ["業務システム"]
publisher: "株式会社一創"
---

# LINEログイン APIの実装手順：PKCE・IDトークン検証と既存会員IDの連携

LINEログイン APIは、自社のWebサイトやアプリにLINEアカウントでのログインを組み込むための、OAuth 2.0とOpenID Connectに準拠したAPIです。この記事では、v2.1の認可エンドポイントへstate・nonce・PKCEを付けてリダイレクトするところから、tokenエンドポイントでの認可コードの交換、IDトークンの検証、既存の会員IDとLINEユーザーIDの紐づけまでを、FlaskとPyJWTのコードで順に実装します。ウェブログインとLIFFで署名方式が変わる落とし穴、退会時に呼ぶ権限取消のAPIも扱います。LINEミニアプリとして作るかWebアプリとして作るかの判断は、[LINEミニアプリとLIFFの使い分けを整理した記事](https://www.issoh.co.jp/column/details/15161/)を先に読むと迷いません。

## まとめ：LINEログインAPIは認可コード＋PKCEで受け、IDトークンをサーバーで検証する

LINEログインが対応するレスポンスタイプは `code` だけです。実装は、認可URLへリダイレクトし、コールバックで受けた認可コードを `/oauth2/v2.1/token` でアクセストークンとIDトークンに換える、という標準の認可コードフローになります。stateとnonceは毎回ランダムに作り、PKCEの `code_challenge` も付けてください。

ログインした人を識別する値は、IDトークンの `sub`（LINEユーザーID）です。ウェブログインのIDトークンはHS256でチャネルシークレットを鍵に署名されているため、公開鍵で検証しようとすると失敗します。自前で検証するのが不安なら、verifyエンドポイントにIDトークンとチャネルIDを送るだけで検証できます。

会員テーブルの主キーは自社の会員IDに置き、LINEユーザーIDは別テーブルで紐づけます。退会時には `/user/v1/deauthorize` で連動アプリの権限を取り消すことが開発ガイドラインで必須とされています。

## LINEログインチャネルを作る前に決めるプロバイダーとスコープの設定

### プロバイダー単位で変わるユーザーIDとMessaging APIチャネルとの同居

LINE Developersコンソールでは、プロバイダーの下にLINEログインチャネルを作ります。ここで最初に決めるべきは、どのプロバイダーに置くかです。[ユーザーIDの説明](https://developers.line.biz/ja/docs/messaging-api/getting-user-ids/)によると、ユーザーIDは同じ人でもプロバイダーごとに別の値が発行され、形式は `U[0-9a-f]{32}`（Uと16進数32桁）です。LINEの[OpenID設定](https://access.line.me/.well-known/openid-configuration)でも `subject_types_supported` は `pairwise` になっています。

逆に、同じプロバイダーであれば、LINEログインチャネルとMessaging APIチャネルで同じユーザーIDが割り当てられます。ログインした会員へ後から公式アカウントで通知を送る計画があるなら、両方のチャネルを同じプロバイダーに置いてください。別プロバイダーに作ってしまうと、ログインで保存したIDがpushの宛先に使えません。送信側の実装は[Messaging APIのプッシュメッセージ送信を実装した記事](https://www.issoh.co.jp/tech/details/19335/)で扱っています。

### コールバックURLの登録とprofile・openid・emailスコープの申請手順

コールバックURLは、チャネルの［LINEログイン設定］タブで改行区切りに複数登録できます。認可リクエストの `redirect_uri` は、登録したURLと完全一致するか、それにクエリパラメータを足した形でなければなりません。[ウェブアプリへの組み込み手順](https://developers.line.biz/ja/docs/line-login/integrate-line-login/)にあるscopeの組み合わせは次のとおりです。

| scope                | 取得できる情報                | 前提             |
| -------------------- | ---------------------- | -------------- |
| openid               | ユーザーID                 | なし             |
| profile openid       | ユーザーID・表示名・プロフィール画像URL | なし             |
| openid email         | ユーザーID・メールアドレス         | メールアドレス取得権限の申請 |
| profile openid email | 上記すべて                  | メールアドレス取得権限の申請 |

emailを使うには、チャネル基本設定タブの「OpenID Connect」から申請し、メールアドレスの取得と利用目的をユーザーに示す画面のスクリーンショットを提出します。emailだけを指定し `openid` を外すと `INVALID_SCOPE` で弾かれます。なお、トークン応答の `scope` には、emailを許可されていても `email` の文字は入りません。

## 認可リクエストからトークン発行までをFlaskとPKCEで実装する手順

### state・nonce・code\_verifierを作り認可URLへ送る実装

ログインボタンの遷移先で、3つの乱数を作ってセッションに保存し、`https://access.line.me/oauth2/v2.1/authorize` へリダイレクトします。[PKCE対応の説明](https://developers.line.biz/ja/docs/line-login/integrate-pkce/)では、`code_verifier` は英数字と `-._~` の43〜128字、`code_challenge_method` は `S256` のみ（plainは不可）というパラメータの指定です。PyJWT 2.15系（2026年9月公開・Python 3.9以上）とFlaskで書くと次のようになります。

```
# pip install flask requests "pyjwt[crypto]"
import base64
import hashlib
import secrets
import urllib.parse

import jwt
import requests
from flask import Flask, abort, redirect, request, session

app = Flask(__name__)
app.secret_key = "..."          # 環境変数やシークレット管理から読み込む
CHANNEL_ID = "1234567890"       # LINEログインチャネルのチャネルID
CHANNEL_SECRET = "..."          # チャネルシークレット（クライアントに出さない）
REDIRECT_URI = "https://example.com/callback"
AUTHORIZE_URL = "https://access.line.me/oauth2/v2.1/authorize"
TOKEN_URL = "https://api.line.me/oauth2/v2.1/token"


@app.get("/login")
def login():
    state = secrets.token_urlsafe(32)
    nonce = secrets.token_urlsafe(32)
    verifier = secrets.token_urlsafe(64)  # 86字。使える文字だけで構成される
    digest = hashlib.sha256(verifier.encode("ascii")).digest()
    challenge = base64.urlsafe_b64encode(digest).rstrip(b"=").decode("ascii")
    session.update(line_state=state, line_nonce=nonce, line_verifier=verifier)
    params = {
        "response_type": "code",
        "client_id": CHANNEL_ID,
        "redirect_uri": REDIRECT_URI,
        "state": state,
        "scope": "profile openid",
        "nonce": nonce,
        "code_challenge": challenge,
        "code_challenge_method": "S256",
    }
    query = urllib.parse.urlencode(params, quote_via=urllib.parse.quote)
    return redirect(f"{AUTHORIZE_URL}?{query}")
```

`quote_via=urllib.parse.quote` を指定しているのは、scopeの区切りを `+` ではなく `%20` にするためです。stateはログインのたびに作り直し、Cookie署名つきのセッションなど第三者が読めない場所に置きます。この2点は[LINEログインのセキュリティチェックリスト](https://developers.line.biz/ja/docs/line-login/security-checklist/)の項目そのものです。PKCEが防ぐ攻撃の中身は[PKCEのcode\_verifierと検証設計を解説した記事](https://www.issoh.co.jp/tech/details/16405/)に詳しくまとめています。

### コールバックでstateを照合しtokenエンドポイントで認可コードを交換する

コールバックでは、まずstateを照合し、一致しなければ何もせずに止めます。そのうえで認可コードを `application/x-www-form-urlencoded` で送ります。[LINEログイン v2.1 APIリファレンス](https://developers.line.biz/ja/reference/line-login/)では、PKCEを使う場合も `client_secret` は省けません。

```
@app.get("/callback")
def callback():
    expected = session.pop("line_state", None)
    if not expected or not secrets.compare_digest(request.args.get("state", ""), expected):
        abort(400)  # stateが無い・一致しない場合は処理しない
    if "error" in request.args:
        # ACCESS_DENIED などはログイン画面へ戻す
        return redirect("/login-failed")

    res = requests.post(TOKEN_URL, data={
        "grant_type": "authorization_code",
        "code": request.args["code"],
        "redirect_uri": REDIRECT_URI,
        "client_id": CHANNEL_ID,
        "client_secret": CHANNEL_SECRET,
        "code_verifier": session.pop("line_verifier"),
    }, timeout=10)
    res.raise_for_status()
    tokens = res.json()  # access_token・expires_in・id_token・refresh_token・scope・token_type

    claims = verify_web_id_token(tokens["id_token"], session.pop("line_nonce"))
    member_id = find_or_link_member(claims["sub"])  # 次章の紐づけ処理
    session["member_id"] = member_id
    return redirect("/mypage")
```

応答の `access_token` は30日、`refresh_token` は発行から最長90日有効です。ログイン判定だけが目的ならアクセストークンを長く持つ必要はありませんが、後述の退会処理で使うため、会員と紐づけて暗号化して保存しておく設計にしています。リファレンスは応答のプロパティが将来増える可能性に触れているので、JSONを厳密なスキーマで受けないでください。

### ACCESS\_DENIEDなどのエラー応答と10分で失効する認可コードの扱い

同意画面でキャンセルされると、コールバックに `error=ACCESS_DENIED` と送ったstateが返ります。組み込み手順に載っているエラーコードは7種類で、実装上の扱いは2つに分かれます。

- 利用者の操作によるもの：`ACCESS_DENIED`（同意の拒否）、`LOGIN_REQUIRED` と `INTERACTION_REQUIRED`（`prompt=none` で自動ログインできなかった）
- 実装やサーバーの問題：`INVALID_REQUEST`、`UNSUPPORTED_RESPONSE_TYPE`、`INVALID_SCOPE`、`SERVER_ERROR`

前者はログイン画面へ戻して別の手段を示し、後者はアラートの対象にします。`client_id` や `redirect_uri` が誤っているときはコールバックへ戻らずLINE側の画面で止まるため、ログに何も残りません。認可コードの有効期間は10分で、使えるのは1回だけです。ブラウザの戻る操作でコールバックが再実行されても、前述のコードではstateをセッションから取り出し済みのため400で止まります。この400はログイン画面へ戻す扱いで足ります。

## IDトークンをverifyエンドポイントとPyJWTで検証するコードと署名方式

### verifyエンドポイントにid\_tokenとnonceを送るcurlと6種類のエラー

いちばん手堅いのは、LINEのverifyエンドポイントに検証を任せる方法です。[IDトークンの検証の説明](https://developers.line.biz/ja/docs/line-login/verify-id-token/)では、LINEプラットフォームから直接受け取った場合を除き、IDトークンはサーバーで検証するよう求めています。

```
curl -s -X POST https://api.line.me/oauth2/v2.1/verify \
  -H 'Content-Type: application/x-www-form-urlencoded' \
  --data-urlencode "id_token=${ID_TOKEN}" \
  --data-urlencode "client_id=${LINE_CHANNEL_ID}" \
  --data-urlencode "nonce=${NONCE}"
```

成功すると `iss`・`sub`・`aud`・`exp`・`iat`・`nonce`・`amr`・`name`・`picture` などを含むJSONが返ります。失敗時の `error_description` は、署名不正の `Invalid IdToken.`、発行者違いの `Invalid IdToken Issuer.`、期限切れの `IdToken expired.`、チャネルID違いの `Invalid IdToken Audience.`、nonce違いの `Invalid IdToken Nonce.`、`user_id` 違いの `Invalid IdToken Subject Identifier.` の6種類です。HTTPを1往復増やす代わりに、鍵の扱いを持たずに済みます。

### ウェブログインはHS256、LIFFとSDKはES256になる署名方式の分岐

自前で検証するなら、署名方式の違いに注意してください。ウェブログインで得たIDトークンはHS256でチャネルシークレットを鍵に署名され、ヘッダに `kid` がありません。LIFFアプリやネイティブアプリのLINE SDKで得たものはES256で、`kid` に一致する公開鍵を [JWKS](https://api.line.me/oauth2/v2.1/certs) から引きます。紛らわしいのは、OpenID設定の `id_token_signing_alg_values_supported` にES256しか書かれていない点です（2026年11月5日取得）。設定だけを見てES256で検証すると、ウェブログインのトークンは必ず失敗します。

```
ISSUER = "https://access.line.me"
jwks_client = jwt.PyJWKClient("https://api.line.me/oauth2/v2.1/certs")


def verify_web_id_token(id_token, expected_nonce):
    """ウェブログインのIDトークン（HS256・鍵はチャネルシークレット）"""
    claims = jwt.decode(id_token, CHANNEL_SECRET, algorithms=["HS256"],
                        audience=CHANNEL_ID, issuer=ISSUER)
    if not secrets.compare_digest(claims.get("nonce", ""), expected_nonce):
        raise jwt.InvalidTokenError("nonce mismatch")
    return claims


def verify_liff_id_token(id_token):
    """LIFF・LINE SDKのIDトークン（ES256・鍵はJWKSのkid一致分）"""
    signing_key = jwks_client.get_signing_key_from_jwt(id_token)
    return jwt.decode(id_token, signing_key.key, algorithms=["ES256"],
                      audience=CHANNEL_ID, issuer=ISSUER)
```

`algorithms` は経路ごとに1つだけ指定し、両方を許す書き方はしないでください。HS256とES256を同じ関数で受け付けると、鍵の取り違えを狙う攻撃の余地が生まれます。`exp` の確認は `jwt.decode` が既定で行います。JWTの署名検証そのものの考え方は[JWTの構造と署名検証の仕組みを解説した記事](https://www.issoh.co.jp/tech/details/13453/)、検証手順の一般形は[OpenID Connect Core 1.0](https://openid.net/specs/openid-connect-core-1%5F0.html)の「ID Token Validation」が原典です。

### profile・userinfo・IDトークンで取得できるユーザー情報の違い

ログイン後にユーザー情報を取る経路は4つあり、必要なスコープと返る項目が少しずつ違います。リファレンスの記載を並べると次のとおりです。

- IDトークン（verifyエンドポイント含む）：scopeは `openid`。`sub`・`name`・`picture`・`email`・`amr` が入る
- `GET /oauth2/v2.1/userinfo`：scopeは `openid`。`sub`・`name`・`picture` を返す
- `GET /v2/profile`：scopeは `profile`。`userId`・`displayName`・`pictureUrl`・`statusMessage` を返す
- `GET /friendship/v1/status`：scopeは `profile`。公式アカウントと友だちかを `friendFlag` で返す

メールアドレスが返るのはIDトークンだけです。ログイン直後の会員登録にはIDトークンのクレームで足り、APIを追加で呼ぶ必要はありません。`/v2/profile` を使うのは、ステータスメッセージが要る場合か、保存したアクセストークンで後から最新の表示名を取り直す場合に限られます。`amr` には `pwd`・`lineautologin`・`lineqr`・`linesso`・`mfa` が入りえますが、条件によって含まれないことがあるため、必須項目として扱わないでください。

## 既存会員IDとLINEユーザーIDを紐づけるテーブル設計と退会時の権限取消

### 会員テーブルの主キーは自社IDに置きLINEのsubを別テーブルで持つ設計

LINEユーザーIDを会員テーブルの主キーにすると、プロバイダーを移したときや、LINE以外のログイン手段を足したときに全テーブルの外部キーを書き換えることになります。主キーは自社で採番し、LINEとの対応は別テーブルに切り出します。

```
CREATE TABLE members (
  id          BIGINT PRIMARY KEY,
  email       VARCHAR(255),
  created_at  TIMESTAMP NOT NULL
);

CREATE TABLE member_line_links (
  member_id          BIGINT NOT NULL REFERENCES members(id),
  line_user_id       CHAR(33) NOT NULL UNIQUE,  -- IDトークンのsub（U＋16進数32桁）
  login_channel_id   VARCHAR(20) NOT NULL,      -- プロバイダーの取り違え調査用
  access_token_enc   TEXT,                      -- 退会時のdeauthorizeに使う（暗号化して保存）
  linked_at          TIMESTAMP NOT NULL,
  UNIQUE (member_id)
);
```

`line_user_id` に一意制約を付け、1つのLINEアカウントが2人の会員に紐づく状態をDBで防ぎます。`member_id` にも一意制約を付けているのは、1人の会員に1つのLINEアカウントという運用を前提にしているためで、複数のLINEアカウントを許すならこの制約を外します。

### メールアドレス一致で自動統合しない理由とログイン中に連携させる流れ

既存会員がLINEログインを初めて使ったとき、IDトークンのemailと会員テーブルのemailが一致したら同一人物とみなして紐づけたくなります。この自動統合は採用しません。LINEアカウントに登録されたメールアドレスを、その人が今も持っているとは限らないからです。既存アカウントの乗っ取りにつながる経路を自分で作ることになります。

既存会員の連携は、自社のIDとパスワードでログインした状態のマイページに「LINEと連携する」ボタンを置き、そこからLINEログインを通す流れにします。コールバックでは、セッションの `member_id` と `sub` を `member_line_links` に書き込むだけです。未ログインでLINEログインを通った人のsubが未登録なら、新規会員として登録するか、既存会員なら先にログインしてから連携するよう案内します。クライアントからユーザーIDだけを送らせて紐づける実装は、チェックリストが禁じている形です。必ず生のIDトークンかアクセストークンをサーバーへ送り、サーバー側で検証します。

### 退会・連携解除でdeauthorizeを呼ぶ必須事項とログに残す4項目

[LINEログイン開発ガイドライン](https://developers.line.biz/ja/docs/line-login/development-guidelines/)は、ユーザーが退会したときや連携を解除したときに、連動アプリへの権限を取り消すことを必須事項にしています。使うのは `/user/v1/deauthorize` で、ヘッダに[チャネルアクセストークン](https://developers.line.biz/ja/docs/basics/channel-access-token/)（任意の有効期間を指定できるv2.1かステートレス）、ボディにユーザーのアクセストークンを入れます。

```
curl -s -o /dev/null -w "%{http_code}\n" -X POST https://api.line.me/user/v1/deauthorize \
  -H 'Content-Type: application/json' \
  -H "Authorization: Bearer ${CHANNEL_ACCESS_TOKEN}" \
  -d "{\"userAccessToken\": \"${USER_ACCESS_TOKEN}\"}"
# 204 なら取消完了。400 invalid token は既に取り消し済みのことが多い
```

ユーザーのアクセストークンが要るため、保存していたトークンが期限切れなら退会の操作時にもう一度LINEログインを通してもらうと確実です。ガイドラインはあわせて、問い合わせ調査のために次のログを一定期間残すよう勧めています。LINE側はログを提供しないので、残さなければ調べようがありません。

1. 認可リクエストの時刻とパラメータ
2. 認可コードまたはエラー応答を受け取った時刻・メソッド・内容
3. LINEログインAPIの `x-line-request-id`・時刻・メソッド・エンドポイント・ステータスコード
4. 可能ならAPIのリクエストボディとレスポンスボディ

4つ目にはトークンが含まれるため、保存するならトークン部分を伏せてから書き出してください。

## LINEログインを自前で実装する条件と認証基盤サービスに任せる場面

### LINEだけを入口にするWeb会員サイトで自前実装を選んでよい条件

[LINEログインの概要](https://developers.line.biz/ja/docs/line-login/overview/)にあるとおり、LINEログイン自体は無料で使えます。ログイン手段がLINEだけで、会員DBもアプリも自社で持っているなら、この記事のコードの範囲（認可・交換・検証・紐づけ・取消）で完結し、外部の認証サービスを挟む理由はありません。店舗の会員証、予約サイト、LINE公式アカウントと組み合わせた通知つきのサービスがこの形です。

ただし、LINEアプリの中で開く画面を作るならWebのLINEログインではなくLIFFを選びます。LIFFブラウザ内での認可リクエストは動作保証の対象外とされ、外部ブラウザで開くLIFFアプリでも `liff.login()` を使うよう案内されています。LIFF側の作り方は[LIFFの仕組みと開発手順を実装目線で解説した記事](https://www.issoh.co.jp/tech/details/3396/)を参照してください。LINEログインと会員基盤、Messaging APIの通知までをまとめて設計したい場合は、[一創のLINEミニアプリ開発](https://www.issoh.co.jp/service/apps/line/)で要件整理から相談できます。

### Googleアカウントやメール認証と併用するなら認証基盤を先に置く判断

LINEに加えてGoogleやApple、メールアドレスとパスワードのログインも並べるなら、LINEログインをアプリに直接書くのは見送ります。プロバイダーごとにstate・nonce・PKCE・IDトークン検証・連携テーブル・退会時の取消を作ることになり、署名方式の分岐のような個別の癖もプロバイダーの数だけ抱えるからです。

この場合は、OpenID Connectのカスタムプロバイダーを登録できる認証基盤（Keycloak、Auth0、Amazon Cognitoなど）を先に置き、アプリはその認証基盤とだけ話す構成にします。LINE側の設定は、認証基盤のコールバックURLを登録し、チャネルIDとチャネルシークレットを渡すことが中心です。ウェブログインのIDトークンがHS256である点は認証基盤側でも問題になりうるので、導入前に署名アルゴリズムを指定できるかを確かめてください。OpenID Connectの役割分担は[OIDCの仕組みとIDトークンの検証手順を解説した記事](https://www.issoh.co.jp/tech/details/6532/)が前提知識になります。

## よくある質問

LINEログイン APIの実装で、着手前によく出る質問をまとめました。

### LINEログインの利用に料金はかかりますか？

かかりません。LINE Developersの概要ページに、LINEログインは無料で利用できると書かれています。費用が発生するのは、ログインした会員にLINE公式アカウントからメッセージを送る場合で、こちらはMessaging APIの通数として料金プランの計算対象です。ログインのたびに友だち追加を促したいときは、認可URLに `bot_prompt=normal` か `aggressive` を付けると、リンクした公式アカウントの友だち追加の選択肢をログイン画面に表示できます。

### LINEログインで電話番号や住所を取得できますか？

できません。LINEログインで要求できるscopeは `profile`・`openid`・`email` の3つで、取得できるのはユーザーID・表示名・プロフィール画像URL・ステータスメッセージと、申請が通った場合のメールアドレスまでです。電話番号や住所が必要なら、ログイン後の会員登録フォームで本人に入力してもらいます。氏名もLINEの表示名は本名とは限らないため、請求書や配送に使う値は別に取得してください。

### LIFFアプリの中でLINEログインの認可URLを開いてもよいですか？

使わないでください。組み込み手順に、LIFFブラウザ内での認可リクエストは動作を保証しないと明記されています。LIFFアプリでは `liff.getIDToken()` で取ったIDトークンをサーバーへ送り、サーバー側でverifyエンドポイントかES256の公開鍵で検証します。外部ブラウザで開くLIFFアプリの場合も、認可URLを自前で組み立てず `liff.login()` を呼ぶのが公式の案内です。

### バックエンドにはユーザーIDとIDトークンのどちらを送るべきですか？

IDトークンかアクセストークンを、加工せずにそのまま送ります。フロントエンドで取り出したユーザーIDだけを送ると、改ざんされたIDをサーバーが信じてしまうためです。セキュリティチェックリストでも、この点はサーバー側での確認項目です。アクセストークンを送る場合は、サーバーで `GET /oauth2/v2.1/verify` を呼び、`client_id` が自社チャネルのIDと一致し、`expires_in` が正の値であることを確かめてから使います。OAuth 2.0の認可と認証の違いは[OAuth 2.0の仕組みを解説した記事](https://www.issoh.co.jp/tech/details/8369/)で整理しています。

### LINEログイン v2.0で作った実装はそのまま使い続けられますか？

新しく手を入れるならv2.1へ移してください。APIリファレンスではv2.0は非推奨とされ、v2.1の利用が推奨されています。IDトークン・emailスコープの申請・PKCEは、いずれもv2.1のドキュメントで説明されている機能です。移行の中心は、認可URLとtokenエンドポイントのパスを `v2.1` に変え、IDトークンの検証を足すことです。プロバイダーとチャネルを変えなければユーザーIDは変わらないため、会員との紐づけは引き継げます。

## 関連記事

- [LINEミニアプリとは？未認証と認証済みの違い・LIFFとの使い分け・審査と開発費用【2026年版】](https://www.issoh.co.jp/column/details/15161/)：Webアプリかミニアプリかを決める判断材料です。
- [LIFFとは？LINEアプリ内で動くWebアプリの仕組み・できること・開発手順](https://www.issoh.co.jp/tech/details/3396/)：LINEアプリ内でログインさせる場合の作り方です。
- [OIDC（OpenID Connect）とは？仕組み・IDトークンの検証手順とOAuth 2.0との違い](https://www.issoh.co.jp/tech/details/6532/)：IDトークン検証の一般形です。
- [PKCEとは？認可コード横取り攻撃を防ぐcode\_verifierの実装と検証設計を解説](https://www.issoh.co.jp/tech/details/16405/)：認可リクエストに付けるPKCEの背景です。
- [LINE Messaging APIのプッシュメッセージ送信：push・multicastの実装とリトライキー](https://www.issoh.co.jp/tech/details/19335/)：ログインした会員へ通知を送る実装です。

---

出典: [LINEログイン APIの実装手順：PKCE・IDトークン検証と既存会員IDの連携](<https://www.issoh.co.jp/tech/details/19337/>)（株式会社一創）
