メモ > 技術 > サービス: AmazonSNS > iOS: p8証明書
iOS: p8証明書
p8証明書については、以下で解説されている。
iOSでのPush通知について | 株式会社ウイングドア
https://wingdoor.co.jp/blog/ios%E3%81%A7%E3%81%AEpush%E9%80%9A%E7%9F%A5%E3%81%AB%E3%81%A4%E3%81%84%E...
以下のように紹介されている。
・Apple Developer Programで登録しているApple IDで管理している全てのアプリで使用可能。
・本番環境と開発環境で同じ証明書を使用できる。
・有効期限は無期限。
・証明書は一度しかダウンロードできない。(再度作成することは可能。)
・一つのApple IDで2つまでしか証明書を作成できない。
p8証明書を使うと、Androidと同じく「永続的なキーが発行されるが、使用するには都度トークンを発行する必要がある」となる。
トークンの発行については、AmazonSNSを使うことで容易に扱えるようになる。
p12の方が証明書の影響範囲が限定的というメリットはあるので、必ずしもp8証明書にしなければならないわけでは無い。
ただしAppleとしてはp8証明書を推奨しているようなので、まずはp8証明書の利用を検討するといい。
Should we use p8 Auth Key or P12 for APNs? | by Kieu Van Phuoc | Medium
https://kieuvanphuoc.medium.com/should-we-use-p8-auth-key-or-p12-for-apns-e5737938fde9
Apple Developer Programの「Keys」からキーを作成できるみたい。
curlで実際にプッシュ通知を送信するコードも以下で紹介されている。
iOSのPush通知でAPNsとの連携を証明書と認証キーでそれぞれやってみた - つばくろぐ @takamii228
https://takamii.hatenablog.com/entry/2020/07/13/190027
コマンド(curl)でPushテストする方法(iOS) #Swift - Qiita
https://qiita.com/dolfalf/items/2b65c77d11c4e8dbdd9a
以下なども参考になりそう。
iOSのプッシュ通知がp8認証キーに対応しました - ニフクラ mobile backend(mBaaS)お役立ちブログ
https://blog.mbaas.nifcloud.com/entry/2021/04/08/202417
iOS プッシュ通知の実装に必要な「p12形式の証明書」と「 p8形式の鍵」について #iOS - Qiita
https://qiita.com/kokogento/items/405703f3177ebd2e0320
APNs証明書(p8形式)の発行方法 - FANSHIPサポートガイド
https://support.fanship.jp/hc/ja/articles/900006538803-APNs%E8%A8%BC%E6%98%8E%E6%9B%B8-p8%E5%BD%A2%E...
■証明書の取得
APNs証明書(p8形式)の発行方法 - FANSHIPサポートガイド
https://support.fanship.jp/hc/ja/articles/900006538803-APNs%E8%A8%BC%E6%98%8E%E6%9B%B8-p8%E5%BD%A2%E...
iOS プッシュ通知の実装に必要な「p12形式の証明書」と「 p8形式の鍵」について #Firebase - Qiita
https://qiita.com/kokogento/items/405703f3177ebd2e0320
Certificates, Identifiers & Profiles → Keys → +
Key Nameを「refirio」とし、さらに下の一覧にある「Apple Push Notifications service (APNs)」にチェックを入れた。
キーは「1アカウントにつき2つまでしか作れない」「案件ごと、アプリごと、本番&検収環境、などで分けることができない」なので、単純に「refirio」という名前にした。
「Continue」をクリック。
確認画面が表示されるので「Register」をクリック。
鍵のダウンロードができるので「Download」をクリックして保存。(「AuthKey_XXXXXXXXXX.p8」という名前だった。)
さらに「Done」をクリックして完了。
Keysの画面に戻り、発行済みのキーとして以下が表示された。
KEY ID: XXXXXXXXXX
SERVICES: 1
NAME: refirio
Apple Developer Programにログインし、「メンバーシップの詳細」から「チームID」を確認しておく。
チームID: YYYYYYYYYY
■JWTトークンの発行
JWT(JSON Web Token)を使った認証を行う。
(Androidでも google/apiclient の内部では同様の仕組みが使われているみたい。)
JWTについては以下のページなどを参照。
初心者向けJWT講座:JSON Web Tokenを使った認証の仕組み
https://zenn.dev/collabostyle/articles/b08c7f29a2e94c
まずは、Composerで必要なライブラリをインストール。
$ composer require firebase/php-jwt
以下のとおりプログラムを作成。(今回は firebase-jwt.php としておく。)
<?php
require 'vendor/autoload.php';
use Firebase\JWT\JWT;
use Firebase\JWT\Key;
// 必要な情報を設定
$keyId = 'XXXXXXXXXX'; // Apple DeveloperのKey ID
$teamId = 'YYYYYYYYYY'; // Apple DeveloperのTeam ID
$p8FilePath = 'AuthKey_XXXXXXXXXX.p8'; // p8ファイルのパス
// p8証明書の読み込み
$privateKey = file_get_contents($p8FilePath);
if (!$privateKey) {
die('p8ファイルが見つかりません。');
}
// JWTのヘッダーとペイロードを設定
$now = time();
$payload = [
'iss' => $teamId, // チームID
'iat' => $now // JWTの発行時刻
];
$headers = [
'alg' => 'ES256', // アルゴリズム
'kid' => $keyId // キーID
];
// JWTトークンの生成
$jwt = JWT::encode($payload, $privateKey, 'ES256', $keyId);
echo "JWTトークン: " . $jwt . PHP_EOL;
プログラムを実行すると、以下のとおりJWTトークンが発行された。
$ php firebase-jwt.php
JWTトークン: eyJ0eXAiOi0000000000bGciOiJFUzI1NiIsImtpZCI6Ikc5MjNOWTRXNVkifQ.eyJpc3MiOiJENVpRUVk5OFpMIiwiaWF0IjoxNzI5ODUwOTMzfQ.kySqsqu5SkhS0WhKWmgou3SUf7188n3AHRvlK1_72aMlw6n3m019pk0cEVQuypx2M8nUr8U4K1cf5rO7Br9zIw
このJWTトークンを使って、以下のコマンドでプッシュ通知を送信できる。
$ curl -v -d '{"aps":{"alert":{"title":"[送信タイトル]","body":"[送信メッセージ]"},"sound":"default"}}' -H "Content-Type: application/json" -H "apns-topic: [アプリのID]" -H "apns-priority: 10" -H "authorization: bearer [JWTトークン]" --http2 https://api.development.push.apple.com/3/device/[デバイストークン]
具体的には、以下のように実行する。
$ curl -v -d '{"aps":{"alert":{"title":"テスト","body":"これはp8ファイルによる送信です。"},"sound":"default"}}' -H "Content-Type: application/json" -H "apns-topic: net.refirio.pushtest1" -H "apns-priority: 10" -H "authorization: bearer eyJ0eXAiOi0000000000bGciOiJFUzI1NiIsImtpZCI6Ikc5MjNOWTRXNVkifQ.eyJpc3MiOiJENVpRUVk5OFpMIiwiaWF0IjoxNzI5ODUwOTMzfQ.kySqsqu5SkhS0WhKWmgou3SUf7188n3AHRvlK1_72aMlw6n3m019pk0cEVQuypx2M8nUr8U4K1cf5rO7Br9zIw" --http2 https://api.development.push.apple.com/3/device/d6cb5af49500000000002425020838f4d4792c2de946bce49ad2...
* Trying 17.188.143.66:443...
* Connected to api.development.push.apple.com (17.188.143.66) port 443
* ALPN: curl offers h2,http/1.1
* Cipher selection: ALL:!EXPORT:!EXPORT40:!EXPORT56:!aNULL:!LOW:!RC4:@STRENGTH
* TLSv1.2 (OUT), TLS handshake, Client hello (1):
* CAfile: /etc/pki/tls/certs/ca-bundle.crt
* CApath: none
* TLSv1.2 (IN), TLS handshake, Server hello (2):
* TLSv1.2 (IN), TLS handshake, Certificate (11):
* TLSv1.2 (IN), TLS handshake, Server key exchange (12):
* TLSv1.2 (IN), TLS handshake, Request CERT (13):
* TLSv1.2 (IN), TLS handshake, Server finished (14):
* TLSv1.2 (OUT), TLS handshake, Certificate (11):
* TLSv1.2 (OUT), TLS handshake, Client key exchange (16):
* TLSv1.2 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.2 (OUT), TLS handshake, Finished (20):
* TLSv1.2 (IN), TLS change cipher, Change cipher spec (1):
* TLSv1.2 (IN), TLS handshake, Finished (20):
* SSL connection using TLSv1.2 / ECDHE-RSA-AES256-GCM-SHA384
* ALPN: server accepted h2
* Server certificate:
* subject: C=US; ST=California; O=Apple Inc.; CN=api.development.push.apple.com
* start date: Apr 24 18:16:30 2024 GMT
* expire date: Apr 10 00:00:00 2025 GMT
* subjectAltName: host "api.development.push.apple.com" matched cert's "api.development.push.apple.com"
* issuer: CN=Apple Public Server RSA CA 12 - G1; O=Apple Inc.; ST=California; C=US
* SSL certificate verify ok.
* using HTTP/2
* [HTTP/2] [1] OPENED stream for https://api.development.push.apple.com/3/device/d6cb5af49500000000002425020838f4d4792c2de946bce49ad2...
* [HTTP/2] [1] [:method: POST]
* [HTTP/2] [1] [:scheme: https]
* [HTTP/2] [1] [:authority: api.development.push.apple.com]
* [HTTP/2] [1] [:path: /3/device/d6cb5af49500000000002425020838f4d4792c2de946bce49ad240be4f19c9b2]
* [HTTP/2] [1] [user-agent: curl/8.3.0]
* [HTTP/2] [1] [accept: */*]
* [HTTP/2] [1] [content-type: application/json]
* [HTTP/2] [1] [apns-topic: net.refirio.pushtest1]
* [HTTP/2] [1] [apns-priority: 10]
* [HTTP/2] [1] [authorization: bearer eyJ0eXAiOi0000000000bGciOiJFUzI1NiIsImtpZCI6Ikc5MjNOWTRXNVkifQ.eyJpc3MiOiJENVpRUVk5OFpMIiwiaWF0IjoxNzI5ODUwOTMzfQ.kySqsqu5SkhS0WhKWmgou3SUf7188n3AHRvlK1_72aMlw6n3m019pk0cEVQuypx2M8nUr8U4K1cf5rO7Br9zIw]
* [HTTP/2] [1] [content-length: 114]
> POST /3/device/d6cb5af49500000000002425020838f4d4792c2de946bce49ad240be4f19c9b2 HTTP/2
> Host: api.development.push.apple.com
> User-Agent: curl/8.3.0
> Accept: */*
> Content-Type: application/json
> apns-topic: net.refirio.pushtest1
> apns-priority: 10
> authorization: bearer eyJ0eXAiOi0000000000bGciOiJFUzI1NiIsImtpZCI6Ikc5MjNOWTRXNVkifQ.eyJpc3MiOiJENVpRUVk5OFpMIiwiaWF0IjoxNzI5ODUwOTMzfQ.kySqsqu5SkhS0WhKWmgou3SUf7188n3AHRvlK1_72aMlw6n3m019pk0cEVQuypx2M8nUr8U4K1cf5rO7Br9zIw
> Content-Length: 114
>
< HTTP/2 200
< apns-id: 5371130C-0127-0D02-AA12-41C29AA8EE5B
< apns-unique-id: 7def9a2f-df7f-e8fc-778c-04337c567bf9
<
* Connection #0 to host api.development.push.apple.com left intact
■AmazonSNSへの登録
AmazonSNS → プッシュ通知 → PushTest1-APNS-Dev → 編集
認証方法: トークン
署名キー: (上の手順で取得したp8ファイル。)
署名キーID: XXXXXXXXXX
チームID: YYYYYYYYYY
バンドルID: net.refirio.pushtest1
「変更の保存」ボタンをクリック。
PushTest1-APNS-Dev の画面に戻る。
しばらくしてページを再読み込みすると、
認証方法: Certificate
証明書の有効期限: 2025-11-24T04:45:55Z
と表示されていた部分が
認証方法: Token
AppleバンドルID: net.refirio.pushtest1
AppleチームID: YYYYYYYYYY
と表示されるようになった。
この状態でAmazonSNS経由でプッシュ通知を送り、アプリに届くことを確認する。