LIFFアプリへの外部ブラウザによるアクセスを制御する

## はじめに
[前回の記事](https://qiita.com/course_k/items/8bdda799832c9207f26e)でLIFFブラウザとLINE内ブラウザの違いについて触れました。

今回はLIFFアプリに外部ブラウザからアクセスした場合の制御について解説します。

:::note warn
外部ブラウザとは通常のWebブラウザのことを指しますが、本記事においてはLINE内ブラウザも含めて外部ブラウザと呼称しています。
（要は、LIFFブラウザ以外を外部ブラウザとする）
:::

## 外部ブラウザからのアクセスを拒否する
LIFFブラウザからのアクセスに限定し、外部ブラウザではLIFFアプリを利用できないようにするにはいくつか方法がありますが、最もシンプルな方法を紹介します。

### liff.isInClientの使用
LIFFブラウザでのアクセスかどうかを判定するメソッドです。
`liff.init()`による初期化の前でも呼び出すことができます。
※LIFF SDKに用意されている多くの処理は初期化しないと実行することができない。

LIFFブラウザでのアクセスの場合には`true`、外部ブラウザの場合には`false`を返します。

### 使用例
```react:App.tsx
import liff from "@line/liff";

function App() {
  const isInClient = liff.isInClient();

  return (
    <>
      {isInClient ? (
        <h1>LIFFブラウザによるアクセスです</h1>
      ) : (
        <h1>外部ブラウザによるアクセスです</h1>
      )}
    </>
  );
}

export default App;
```
`liff.isInClient()`の結果を変数に格納し、三項演算子で結果を出し分けました。
これだけで外部ブラウザの場合には別ページにアクセスさせることができます。

### 実行結果
#### LIFFブラウザ
<img width='80%' src='https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/251137/563dbf59-fa08-f9b8-66ec-679964971291.png'>

#### 外部ブラウザ（LINE内ブラウザ）
<img width='80%' src='https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/251137/1570b876-add5-249a-b543-6eaa3fea1209.png'>

#### 外部ブラウザ（Chrome）
<img width='80%' src='https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/251137/82d8537b-be81-e3db-a9cc-55672cc41b49.png'>

以上のように、外部ブラウザアクセスの場合にはLIFFブラウザでのアクセスとは異なるページを表示させることができました。

### その他の方法
`liff.isInClient()`が一番シンプルな方法なのですが、`liff.getLineVersion()`や、`liff.getContext()`を使うことで、同じようなことを実現できます。

ただ、あまりメリットはないように思うので、やはり`liff.isInClient()`がベストかと思います。

気になる方は以下の公式ページからそれぞれのメソッドの挙動を確認してみてください。

* [liff.getLineVersion](https://developers.line.biz/ja/reference/liff/#get-version
)
→初期化（`liff.init()`）前でも使用可能

* [liff.getContext](https://developers.line.biz/ja/reference/liff/#get-context)
→初期化しないと使えない

## 外部ブラウザからのアクセス時、ログインを強制する
`liff.shareTargetPicker()`など、LINEログインをしていないと実行できない処理があります。
LIFFブラウザからのアクセスの場合には`liff.init()`時に自動でログインされますが、外部ブラウザの場合には、明示的なログイン処理が必要です。

### withLoginOnExternalBrowserプロパティの指定
`liff.init()`時、このプロパティを使用することで、外部ブラウザからのアクセスの場合にログイン処理を自動実行するかどうかを決定できます。

デフォルトは`false`になっており、`true`とすることで`liff.login()`処理が自動で実行されます。

### 使用例
```react:App.tsx（一部抜粋）
  useEffect(() => {
    initializeLiff();
  }, []);

  // liffの初期化
  const initializeLiff = async () => {
    try {
      await liff.init({
        liffId: LIFF_ID,
        withLoginOnExternalBrowser: true,
      });
    } catch (error) {
      console.log(error);
    }
  };
```

このように、`liff.init()`時に渡すオブジェクトのプロパティとして`withLoginOnExternalBrowser`を追加で指定するだけです。

これだけで、外部ブラウザからのアクセス時にLINEログイン処理が自動で呼び出されます。

### その他の方法
一般的な方法としては
`liff.isLoggedIn()`でログイン状態を判定し、未ログインの場合に`liff.login()`を実行する
というものが考えられますが、個人的にはあまりおすすめしません。

まず第一に、ログインの無限ループに陥る可能性があります。
何らかの原因でログインがうまくいかない場合、`liff.isLoggedIn()`が常に`false`担ってしまうため、延々とログイン処理が呼び出されることになります。

第二に、不必要な条件判定を実施することになるためです。
LIFFブラウザからのアクセスの場合には自動でログイン処理が呼び出されるため、わざわざログイン状態の判定をする必要がありません。

よって、特別な事情のない限りは`withLoginOnExternalBrowser`を使用するのがよいかと思います。


## まとめ
外部ブラウザからLIFFアプリにアクセスする場合の制御方法を整理しました。

基本的にLIFFアプリはLINE公式アカウントと組み合わせるなどして利用するものなので、LINEからのアクセスであることが大前提ですが、今回解説した方法を使うことで、外部ブラウザからのアクセス時にも適切な対応を行うことができるようになります。
ぜひ参考にしてみてください。

また、もしよければ「いいね」やシェアをしていただけるととても嬉しいです。