Laravelにapple idでサインインを実装する

こんにちは!

とびろぐ管理人のとびうおです。

今回、Laravel8にapple idログインを実装したので、そちらについて解説をしていきたいと思います!

とびうおくん
とびうおくん

とても大変でした…。

必要なものの準備

まず、apple idログインに必要なものは、

  • client_id
  • redirect_uri
  • 秘密鍵

の3つです。

なお、apple developerからこれらは取得します。

apple developerからの取得方法

Sign In - Apple
Sign in with your Apple ID

↑のサイトにアクセスをします。

Laravelにapple idでサインインを実装する

こちらのidentifilersというのをクリックします。

続いて、右側のApple IDsというのを押して、Service IDsというのをくりっくしましょう!

Laravelにapple idでサインインを実装する
とびうおくん
とびうおくん

ここの一番右側だよ!

もし、serviceを作っていない場合は、➕ボタンから作成してみましょう!

続いて、作成できたら、作成されたものをクリックすると以下のような画面になります。

ここで、クリックをして、configuerを書きましょう。

Laravelにapple idでサインインを実装する
とびうおくん
とびうおくん

ここにリダイレクトをするドメインとかcallback urlとかを記述しましょう!

その次に、また、Identifiersに戻って、作成をして、その中にある

Laravelにapple idでサインインを実装する

にクリックをつけましょう。

とびうおくん
とびうおくん

そして、最後にkeyを作るよ!

続いて最後にkeyを作ります。

Sign In - Apple
Sign in with your Apple ID

こちらのページより、Keysにアクセスをして、➕マークでkeyを作ります。

とびうおくん
とびうおくん

こちらにチェックをいれて、

先ほど作ったIdentifiersを右側の選択できるとこから、選択しましょう!

そして、「p8」ファイルをダウンロードしてください。このファイルは一度しかダウンロードできないので気をつけてください!

続いて、コードを書いていく。

では、実際にLaravelのコードを書いていきます。

なお、この実装では、セキュア実装よりもわかりやすさを重視していますので、本番運用される場合は必ずリファクタを実行してください。

※Laravelの基本はわかっているものとします!

とびうおくん
とびうおくん

動いた!を目指すよ!

redirectする関数

ではまず、Apple IDの画面にリダイレクトできるような関数を作成してきます。

public function redirectToApple()
    {
        $client_id ='#Identifiersを指定';
        $redirect_uri = '#call back urlを指定';
        $state = bin2hex(random_bytes(16)); // CSRF対策用のランダムな文字列

        $url = "https://appleid.apple.com/auth/authorize?" . http_build_query([
                'response_type' => 'code',
                'response_mode' => 'form_post',
                'client_id' => $client_id,
                'redirect_uri' => $redirect_uri,
                'state' => $state,
                'scope' => 'name email',
            ]);

   //↓ csrf対策用のDBなので消してもOKです。
        AppleOauthState::query()->create(['state' => $state]);

        return redirect($url);
    }
とびうおくん
とびうおくん

$client_id =’#Identifiersを指定’;

$redirect_uri = ‘#call back urlを指定’;

こちらの2つを書き換えてください!
※scrf実装はしなくても良いです。

これで、まずはこのcontrollerからappleのログイン画面に飛ぶことを確認しましょう!

リダイレクトして戻ってくる画面

続いて、リダイレクトしてくるところのcontrollerを作成してきます。

最終的にemailがechoされるかと思います!

public function handleAppleCallback(Request $request)
    {
         //↓ csrf対策用のDBなので消してもOKです。
        $stateExists = AppleOauthState::query()->where('state', $request->state)->exists();

        if (!$stateExists) {
            return redirect()->route('top'); // 失敗時のリダイレクト先を適切に設定
        }
        $code = $request->input('code');

        $client = new Client();

        $response = $client->post('https://appleid.apple.com/auth/token', [
            'form_params' => [
                'client_id' =>'#Identifiersを指定';
                'client_secret' => $this->generateClientSecret(),
                'code' => $code,
                'grant_type' => 'authorization_code',
                'redirect_uri' =>'#call back urlを指定';
            ],
        ]);

        $tokenResponse = json_decode((string) $response->getBody(), true);
        $idToken = $tokenResponse['id_token'];

        // トークンからkidを取得するためにヘッダーをデコードします。
        $tks = explode('.', $idToken);
        if (count($tks) < 3) {
            throw new UnexpectedValueException('Wrong number of segments');
        }
        list($headb64, $bodyb64, $cryptob64) = $tks;
        $header = JWT::jsonDecode(JWT::urlsafeB64Decode($headb64));
        $kid = $header->kid;

        $keys = json_decode(file_get_contents('https://appleid.apple.com/auth/keys'), true);
        $key = JWK::parseKeySet($keys)[$kid];

        $decoded = JWT::decode($idToken, $key);
        $email = $decoded->email;

        return $email;
    }
function generateClientSecret()
    {
        $keyPath = storage_path('hoge.p8'); // 秘密鍵のパス
        $teamId = 'Apple Developer Team ID'; // Apple Developer Team ID
        $clientId = ''; // Service ID (Apple Developer Portalで設定)
        $keyId = ''; // .p8ファイルのKey ID

        $privateKey = file_get_contents($keyPath);

        $payload = [
            'iss' => $teamId,
            'iat' => time(),
            'exp' => time() + 3600, // トークンの有効期限 (例: 1時間)
            'aud' => 'https://appleid.apple.com',
            'sub' => $clientId,
        ];

        $clientSecret = JWT::encode($payload, $privateKey, 'ES256', $keyId);

        return $clientSecret;
    }
とびうおくん
とびうおくん

イメージとしては、リダイレクトする。

generateClientSecretでclientSecretを作成する

公開鍵によって、復元する

みたいなイメージです。

わかったこと

socilateを使って、apple idログインを実装することも可能ですが、色々な設定が難しかったので結局自作しました。

Web向けに「Appleでサインイン」を設定する - 機能を設定する - アカウント - ヘルプ - Apple Developer
Web向けに「Appleでサインイン」を設定する方法を...

↑こちらに詳しい設定内容等が書かれていますので、そちらもぜひチェックしてみてください!

まとめ

Apple IDログインのやり方について解説しました!

想像よりは大変でしたが、理解すればまあまあ書ける内容になっているかと思います!

とびうおくん
とびうおくん

頑張るしかない!

その他にも

とびろぐでは色々な記事を公開しています!

特にLaravelの記事を多く公開しているのでぜひみてみてください!

Laravel
「Laravel」の記事一覧です。
とびうお
ブログ管理人です!
swimaneというアプリをリリースしました!

コメント

タイトルとURLをコピーしました