Amazon SNSでiOS Push通知を証明書ではなく認証キーで認証する

はじめに

こんにちは、技術開発部 事業横断チーム データエンジニアの多田です。
入社時はアプリエンジニアだった私、hinataアプリの保守・運用をたまにやっております。
最近、Amazon SNSiOS Push通知認証方法を証明書形式から認証キー形式に変更しました。
ただ、Amazon SNSでの認証キーを使ったPush通知認証についてネットにあまり情報がなかったため、記事にまとめてみます。

概要

hinataアプリのPush通知にはAmazon SNSを使用しています。

最近、Amazon SNSに登録しているiOS Push通知証明書を更新する必要がありました。
作業する際に、2021年11月にAmazon SNSでも認証キーに使用ができるようになった事に気づきました。 これを機に証明書による認証から更新が不要な認証キーによる認証に変更する事としました。(参考

本記事ではその変更作業の内容及びトラブルシューティングを記載します。

Push通知の証明書?認証キー?

iOSアプリでPush通知を利用する場合、Apple Push Notification Service(以下、APNs)にリクエストを送ります。
この時、Appleに対して認証が必要で方法は下記2つあります。

  • 発行から1年の有効期限があるSSL証明書
  • 有効期限がない認証キー

証明書の方が古いやり方で、現在は認証キーの方をAppleは推奨しているそうです。
ちなみに、証明書の方は環境毎(product, staging, sandbox等々)に発行する必要がありました。
ですが、認証キーはベンダー共有になるため1個発行すれば使い回せます。

詳細は下記を。とてもわかり易かったです。
【iOS】Firebase Cloud Messagingで利用するAPNs認証キー・証明書の作り方 - Qiita

変更作業

Amazon SNSに認証キーを登録する

下記、設定を間違えると全デバイスにPush通知が届かなくなる恐れがあるため、慎重に。

手順

  1. APNs認証キーをAppleDeveloperから発行する(手順に関しては上記Qiitaのリンク参照)
  2. Amazon SNSの管理画面に入る
  3. 左サイドバーMobileプッシュ通知
  4. プラットフォームアプリケーションにある該当アプリケーションを選択
  5. 編集を押して、下記の通り設定
    1. 認証方法: トークン
    2. 署名キー: 1.でダウンロードした.p8ファイルをアップロード
    3. 署名キーID: Certificates, Identifiers & Profiles - Keysで、1で作成したキーを開いて出てくる Key ID
    4. チーム ID: Apple デベロッパーアカウントのMembershipページにある
    5. バンドルID: Certificates, Identifiers & Profiles - Identifierにある該当のアプリを開いて出てくるBundle ID
  6. 入力し終えたら 変更の保存
  7. Push通知を送ってみて届いたら完了。なお、全エンドポイントへのPush通知をしてしまうと、仮に設定が間違っていた場合全てのエンドポイントが無効になってしまう。個別Pushで試す事を推奨。

トラブルシューティング

テストPush通知後、全てのエンドポイントが無効になってしまった

最初、上記手順5で間違ったバンドルIDを登録した後、手順7で全エンドポイントにPush通知を送ってしまいました。
すると、Amazon SNSに登録されたエンドポイントが全て無効になってしまいました…
無効になるとどうなるかというと、認証情報を正しく設定し直したとしてもPush通知がそのエンドポイントへ届かなくなります。

この時はsandbox環境で行っていたため、影響は少なく済みました…本番環境でと思うとゾッとしますね。

なぜ無効になってしまったかというと、無効な認証情報に対してPush通知を行おうとしたためです。
下記、Amazon SNS プッシュ通知のエンドポイント編集画面に記載があるように、無効なPush通知リクエストがあるとAmazon SNSがエンドポイントを自動で無効にしてしまうようです。

エンドポイントへの配信を有効にします。エンドポイントが無効であることを通知サービスが Amazon SNS に示すと、Amazon SNS はこれを false に設定します。

無効になってしまったエンドポイントは、一応エンドポイント編集画面で有効・無効は切り替えられます。
かつ、APIも用意されているため↓、一括で無効→有効に切り替えることも出来ます。
SetEndpointAttributes