iOSのショートカットでWebサイトの二段階認証コード入力の手間を軽減する

# はじめに

Webサイトの二段階認証コード（以下、認証コード）を入力するのは、以下のステップを踏む必要があり、なかなか手間がかかります。

* Webサイトから二段階認証のアプリ(以下、認証アプリ)に切り替えて認証コードを取得する。
* その後、Webサイトに戻って、認証コードをフォームに入力する。

上記の手間をiOSのショートカットを使って自動化することで軽減する方法について紹介したいと思います。

# 前提

* iOSのショートカットを使用するため、iOS12以上が必要になります。
    * ただし、本記事はiOS13.3で検証を行なっています。
* 認証アプリのインストールが必要です。本記事のショートカットでは、以下のアプリを例に説明しています。
    * Google Authenticator
    * Microsoft Authenticator
    * Authy

# ショートカットの雛形

Webサイトの共有ボタンからショートカットを実行したいため、作成するショートカットはSafariのWebページを受け入れる設定を行います。

このWebページを受け入れる設定のショートカットを作成するにあたり、ショートカットアプリのギャラリーにあるJavaScriptショートカットのサンプルから複製する方法が手っ取り早いです。

例えば、JavaScriptショートカットの```Webページを編集```のショートカットを追加します。その後、このショートカットを編集し、JavaScriptを実行する部分のコードを一旦```completion()```のみにします。

# 個別のWebサイトに対するショートカット例

個別のWebサイトに対して認証コードを入力するケースについて、Amazonを例に説明します。
Amazonの認証コードの入力画面では、以下の要素が宣言されています。

* ```auth-mfa-otpcode```のID属性を持つインプット要素（認証コードの入力フォーム）
* ```auth-signin-button```のID属性を持つボタン要素（サインインボタン）

上記の要素に対して、ショートカットからJavaScriptを実行し、インプット要素に認証コードを設定した後にサインインボタンをクリックすると手間を軽減できそうです。

#### ショートカットの主な手順

* SafariのWebページを受け入れる 
    * ここは、テンプレートの雛形で作成済みです。
* スクリプティングの```アプリを開く```を追加する。
    * Amazonの認証コードを発行する認証アプリ(ここでは、Google Authenticatorアプリ)を起動します。
    * 認証アプリ起動後に、認証コードをクリップボードにコピーします。
* スクリプティングの```待機```を追加します。
* ```JavaScriptを実行```のコードで以下の処理を行います。
    * クリップボードにコピーした認証コードをWebサイトのフォームに設定する。
        * ```auth-mfa-otpcode```のID属性を持つインプット要素を取得し、インプット要素の値に認証コードを設定します。
    * サインインボタンをクリックする。
        * ```auth-signin-button```のID属性を持つ要素を取得し、```click()```を呼び出します。
    * JavaScriptの実行を完了する。
        * ```completion(true)```を呼び出します。

####  JavaScriptの実行コード

```javascript
// 入力フォームに認証コードを設定
document.getElementById("auth-mfa-otpcode").value = '＜クリップボードの変数＞';

// サインインボタンをクリック
document.getElementById("auth-signin-button").click()

// JavaScriptの実行を完了
completion(true)
```

#### 作成したショートカット

[iCloudの共有リンク](https://www.icloud.com/shortcuts/b7648dfdb5a54143bf9a4f2f7de345be)

# 汎用的なWebサイトに対するショートカット例

個別のWebサイトに対してショートカットを作成すると自動化が最適化しやすいですが、二段階認証したいサイトが多いとショートカットの作成に時間がかかります。

そこで、汎用的なWebサイトに対しても認証コードの入力の手間を軽減する方法について説明します。

## 汎用版 ver1

ショートカットのメニューから任意の認証アプリの起動・認証コードをコピーし、認証コードの設定とボタンのクリックは手動で行う例です。

#### ショートカットの主な手順

* SafariのWebページを受け入れる 
    * ここは、テンプレートの雛形で作成済みです。
* スクリプティングの```メニューから選択```を追加します。
    * メニューに複数の認証アプリを追加します。(この部分は個人の環境によって任意のアプリを指定します。)
        * Google Authenticator
        * Microsoft Authenticator
        * Authy
    * それぞれの認証アプリの項目に対して、スクリプティングの```アプリを開く```を追加し、アプリの設定を行います。
* スクリプティングの```待機```を追加します。
* ```JavaScriptを実行```のコードで以下の処理を行います。
    * JavaScriptの実行を完了する。
        * ```completion(true)```を呼び出します。

#### JavaScriptの実行コード
特に認証コードの設定とボタンのクリックはショートカット上では行わないため、単純に完了のコールバック関数を呼び出す処理のみになります。

```javascript
// JavaScriptの実行を完了
completion(true);
```

認証コードの取得以降では、手動で認証コードのインプット要素にクリップボード上の認証コードをペーストし、その後、ボタンを押下します。

#### 作成したショートカット

[iCloudの共有リンク](https://www.icloud.com/shortcuts/eb8883bf609040c0a1dff297d3063cc2)

## 汎用版 ver2

汎用版 ver1では、手動で認証コードをインプット要素にペーストする必要があり、若干煩わしいです。
ただし、認証コードのインプット要素は、各サイトによってID属性やクラス属性、type属性の値が統一されていないため、特定がしづらいです。

苦肉の策として、ここではインプット要素にフォーカスを当てた時に、フォーカスされた要素に認証コードを設定する方法について説明します。

#### ショートカットの主な手順

* SafariのWebページを受け入れる 
    * ここは、テンプレートの雛形で作成済みです。
* スクリプティングの```メニューから選択```を追加します。
    * メニューに複数の認証アプリを追加します。(この部分は個人の環境によって任意のアプリを指定いsます。)
        * Google Authenticator
        * Microsoft Authenticator
        * Authy
    * それぞれの認証アプリの項目に対して、スクリプティングの```アプリを開く```を追加し、アプリの設定を行います。
* スクリプティングの```待機```を追加します。
* ```JavaScriptを実行```のコードで以下の処理を行います。
    * 入力要素を取得し、focusイベントを追加する。
        * focusイベント時に、ターゲット要素にクリップボード上の認証コードを設定する
    * JavaScriptの実行を完了する。
        * ```completion(true)```を呼び出します。

#### JavaScriptの実行コード

入力要素に対して、focusイベントを追加し、focusイベント時にターゲット要素に対して認証コードを設定します。ボタンの要素のクリックはJavaScriptでは行いません。
※ 認証コード以外のインプット要素にフォーカスした場合にも認証コードが設定されてしまうので、利用には注意してください。

```javascript
// 入力要素に対して、focusイベントを追加する
// focusイベント時にターゲット要素にクリップボード上の認証コードを設定する。
var elms = document.querySelectorAll("input");
elms.forEach((elm) => {
  elm.addEventListener('focus', (event) => {
    event.target.value = '<クリップボードの変数>'
  });
});

// JavaScriptの実行を完了
completion(true);
```

認証コードの取得以降では、手動で認証コードのインプット要素にフォーカスを当てることでクリップボード上の認証コードを設定し、その後、ボタンを押下します。


### 作成したショートカット

[iCloudの共有リンク](https://www.icloud.com/shortcuts/d248c107b66e45e1ae94d0d65bd29ca3)

# さいごに

iOSのショートカットを使うことで、認証コード入力の手間を少しは軽減できるようにはできたかと思います。さらに手間を軽減するには、認証アプリを起動して認証コードを取得するのではなく、ローカル あるいは リモートサーバ上(SSH経由)で認証コードを生成・取得すると良いのではと考えています。

# 参考

* [iOSのショートカットで扱う秘密データの管理方法について - Qiita](https://qiita.com/mh_mobiler/items/2a75e03da22ff0a0a516)
* [iOSのショートカットの自動化レシピ - Qiita](https://qiita.com/mh_mobiler/items/578c7a179cbc917e551e)