LIFFの始め方：liff.initとLIFFブラウザーの理解

LIFFは、WEBアプリをLINEと統合し、WEBアプリでネイティブ機能を活用するための強力なツールです。これは、重要なliff.initを呼び出して初期化されます。

最近、liff.initに関する問題に遭遇したため、何をしているのかを詳しく見る必要がありました。そのため、ここで共有しようと思います。このブログの課題は以下の通りです：

- LIFFを使ってWEBアプリを起動し、実行する方法
- liff.initを呼び出す際に「裏側」で起こること
- LIFFアプリ間におけるchat_message.writeスコープの保持
- LINE内でLIFFブラウザーと外部ブラウザーを識別する方法

## 起動と実行

LIFFブラウザーのアプリ開発を始めるとき、初心者はすぐに設定を完了できます。以下のように自分で設定することができます：

1. LINE Developersにログインする
2. LINEログインチャンネルを作成する
3. そのチャンネル内にLIFFアプリを作成する
4. エンドポイントURLを設定する（❖1）
5. ソースコードでliff.initにLIFFアプリのLIFF IDを使用する（❖2）
6. LINEトークルームからLIFF URLを開いてテストする -> `https://liff.line.me/` + `liffId`!

**(❖1)**
ステップ4では、アプリをホストする場所が必要です。アドレスはhttpsである必要があります。開発中やテスト中には、NGROKのようなものを使ってlocalhostを転送することをお勧めします。

**(❖2)**
ステップ5は以下のようになります：
```javascript
const liffId = "my-liff-id";
liff.init({ 
  liffId,
});
```

通常、このコードは `main.ts` 内でVueアプリを作成する前に実行します。Reactのような他のフレームワークを使用している場合は、おそらく `index.tsx` や `App.ts` で似たようなことを行います。これから見ていくように、この呼び出しのタイミングが重要です。

これは、LINEのサーバーとの通信を伴う非同期プロセスを開始します。これによりユーザーを認証し、必要な許可を取得します。

## liff.initを呼び出すと実際に何が起こるのか？

有効なLIFF IDでliff.initを呼び出しているウェブアプリがある今、もっと詳しくliff.initを見てみましょう。私たちが主に関心を持っているのは、その非同期認証プロセスです。以下のスクリーンショットはv2.11.0の[リリースノート](https://developers.line.biz/en/docs/liff/release-notes/#redirect-example)からです。これは最新ではありません（2021年）が、関与するステップを視覚的に表している点が気に入っています。最新の[ドキュメント](https://developers.line.biz/en/docs/liff/opening-liff-app/#redirect-flow)にも同様に記述されています。

![RedirectExampleEN.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3588855/c5442cf2-20d7-0747-0b3a-18f7b1c0c595.png)

情報をステップごとに見ていきましょう。

1. **ユーザーがLIFF URLにアクセスし、LINEが提供するLIFFサーバーにリクエストを送信する**
2. **ユーザーのリクエストを受け取ったLIFFサーバーは、ユーザーを「一次リダイレクト先URL」にリダイレクトする** この一次リダイレクト先URLは、ちょうど前にLINE Developersコンソールで指定したエンドポイントURLです。画像に詳しく記載されているように、一次リダイレクト先URLには、access_token、context_token、feature_token、id_tokenの形で認証情報が含まれるURLフラグメントが含まれます。

3. **その後、アプリはこれらのトークンを使ってliff.initメソッドを実行する。** これには、トークンとLIFFアプリにアクセスしようとしているユーザーの真正性を確認する作業が含まれます。これによりURLからURLフラグメントトークンが削除されます。ドメインとパスを含むliff.stateパラメータのみが残ります。パスを指定すること（例："/my-page-path"）は任意です。

4. **最終的に、ユーザーは「二次リダイレクト先URL」にリダイレクトされる** これはまだ私たちが指定したエンドポイントURLですが、パラメータから返されたパス情報をURLパスとして含んでいます。

以下に、LINE Developersのドキュメントから注目すべき警告が見られます。これはliff.initの呼び出しのタイミングの重要性を示しています。具体的には、liff.init中にリダイレクトや組み込みルーター機能に対する警告があります。非同期認証プロセスを理解することで、その理由がわかり始めます。

![NoteOnInitializing.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3588855/3f0721eb-6861-7c31-a042-123ebe08ff5b.png)

## chat_message.writeスコープについて

chat_message.writeスコープは、LIFFアプリに機能を提供します。これによりliff.sendMessagesメソッドが有効になります。これは、LIFFアプリからメッセージを送信する最も速い方法の一つであり、比較的少ない設定とユーザーデータの取り扱いが必要です。ただし、LIFFアプリが開かれたトークルームにメッセージを送信することに限定されます。

使用するには、まずLINE DevelopersコンソールのチャンネルでLIFFアプリ設定でchat_message.writeスコープを有効にします。これにより、LIFFアプリからliff.sendMessagesを使用できるようになります。

## LIFFアプリを直接トークルームから開かない場合

結論から言うと、気をつけないとliff.sendMessagesが機能しません。

私たちは最近この状況に遭遇しました。クライアントの要求により、トークルームから中間アプリが開かれ、そのアプリが私たちの作ったLIFFアプリにリンクされました。望ましい振る舞いは、私たちのアプリでchat_message.writeが引き続き利用可能であることでした。

この振行動を実現することは不可能ではありません。ただし、これは両方のアプリがLIFFアプリである場合にのみ機能します。一つ目のアプリも遷移する二つ目のアプリも、エンドポイントURLではなくLIFF URLを介して開かれる必要があります。この点については、[LINE Developersのドキュメントのセクション](https://developers.line.biz/en/docs/liff/opening-liff-app/#about-chat-message-write-scope)で非常に明確に説明されています。

私たちの場合、内で作ったLIFFアプリはLIFF URLを通じて正しく開かれました。しかし、中間アプリはLIFFアプリではなかったため、スコープは維持されませんでした。そのため、私たちのアプリでliff.sendMessagesを呼び出しても機能しませんでした。当初、私たちの側でエラー処理が行われたため、問題の原因も私たちにあると誤解されました。
しかし、すぐに中間アプリが問題であることに気づきました。LIFFアプリと通常のウェブアプリを区別するのは非常に簡単です。アプリが開かれるときに使用されるブラウザ（LINE内）をチェックするだけです。

## LIFFブラウザーの見分け方

LIFFアプリがLIFFブラウザーで正しく使用されているかどうかを認識する方法があります。視覚的違いがいくつかあります。以下は、私の画面からのスクリーンショットで、左がLIFF URLを通じて、右が直接元のURLエンドポイントを通じて同じアプリを開いた後のものです。

画像で見ると、ページの上部に細かい違いがあります。下部のナビゲーションバーを見ることで、LINE内で非LIFFブラウザーを簡単に見分けることができます。2024年4月現在、これはAndroidとiPhoneの両方のデバイスでまだ当てはまります。

![Screenshot 2024-04-30 at 13.56.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3588855/7277846b-94fb-a944-76ab-9af9ca2c68a0.png)