Реалізація авторизації через Apple ID на сайті

Наша компанія займається розробкою, підтримкою та обслуговуванням сайтів будь-якої складності. Від простих односторінкових сайтів до масштабних кластерних систем, побудованих на мікро сервісах. Досвід розробників підтверджено сертифікатами від вендорів.
Розробка та обслуговування будь-яких видів сайтів:
Інформаційні сайти або веб-програми
Сайти візитки, landing page, корпоративні сайти, онлайн каталоги, квіз, промо-сайти, блоги, ресурси новин, інформаційні портали, форуми, агрегатори
Сайти або веб-програми електронної комерції
Інтернет-магазини, B2B-портали, маркетплейси, онлайн-обмінники, кешбек-сайти, біржі, дропшиппінг-платформи, парсери товарів
Веб-програми для управління бізнес-процесами
CRM-системи, ERP-системи, корпоративні портали, системи управління виробництвом, парсери інформації
Сайти або веб-програми електронних послуг
Дошки оголошень, онлайн-школи, онлайн-кінотеатри, конструктори сайтів, портали надання електронних послуг, відеохостинги, тематичні портали

Це лише деякі з технічних типів сайтів, з якими ми працюємо, і кожен із них може мати свої специфічні особливості та функціональність, а також бути адаптованим під конкретні потреби та цілі клієнта.

Пропоновані послуги
Показано 1 з 1 послугУсі 2065 послуг
Реалізація авторизації через Apple ID на сайті
Середня
~2-3 робочих дні
Часті питання
Наші компетенції:
Етапи розробки
Останні роботи
  • image_website-b2b-advance_0.png
    Розробка сайту компанії B2B ADVANCE
    1262
  • image_web-applications_feedme_466_0.webp
    Розробка веб-додатків для компанії FEEDME
    1171
  • image_websites_belfingroup_462_0.webp
    Розробка веб-сайту для компанії БЕЛФІНГРУП
    874
  • image_ecommerce_furnoro_435_0.webp
    Розробка інтернет магазину для компанії FURNORO
    1094
  • image_crm_enviok_479_0.webp
    Розробка веб-додатків для компанії Enviok
    831
  • image_bitrix-bitrix-24-1c_fixper_448_0.png
    Розробка веб-сайту для компанії ФІКСПЕР
    851

Впровадження Sign in with Apple для веб-сайтів

Sign in with Apple — вимога Apple для нативних iOS/macOS додатків: якщо додаток пропонує будь-яку соціальну авторизацію, Apple ID має бути у списку. Для веба ця вимога формально не обов'язкова, але реалізація потрібна там, де аудиторія — користувачі Apple-пристроїв, а також для веб-частини додатків з iOS-компонентом.

Apple ID має ряд особливостей, що відрізняють його від Google OAuth та інших провайдерів:

  • Користувач може приховати справжню адресу електронної пошти — Apple видає relay-адресу вида [email protected]
  • id_token повертається тільки при першій авторизації разом з ім'ям користувача
  • Наступні входи не повертають ім'я — його потрібно зберегти при першому вході
  • Немає refresh token у стандартному OAuth2-смислі

Реєстрація додатка в Apple Developer

  1. Certificates, Identifiers & ProfilesIdentifiers → створити App ID з увімкненим Sign In with Apple
  2. Створити Services ID (web-компонент) — указати домен та Redirect URL
  3. Створити Key з увімкненим Sign In with Apple — завантажити файл .p8 (зберігати безпечно, завантажити можна тільки один раз)
  4. Зафіксувати: Team ID, Client ID (= Services ID), Key ID

Генерування client_secret

Apple не використовує статичний секрет. client_secret — JWT, підписаний приватним ключем .p8:

use Lcobucci\JWT\Configuration;
use Lcobucci\JWT\Signer\Ecdsa\Sha256;
use Lcobucci\JWT\Signer\Key\InMemory;

function generateAppleClientSecret(): string
{
    $config = Configuration::forAsymmetricSigner(
        new Sha256(),
        InMemory::file(storage_path('keys/apple_auth.p8')),
        InMemory::empty()
    );

    return $config->builder()
        ->issuedBy(config('services.apple.team_id'))         // iss: Team ID
        ->permittedFor('https://appleid.apple.com')          // aud
        ->relatedTo(config('services.apple.client_id'))      // sub: Services ID
        ->issuedAt(new \DateTimeImmutable())
        ->expiresAt(new \DateTimeImmutable('+6 months'))
        ->withHeader('kid', config('services.apple.key_id'))
        ->getToken($config->signer(), $config->signingKey())
        ->toString();
}

Термін дії до 6 місяців. Токен переосвітлюється заздалегідь через cron.

OAuth2 флоу

1. Перенаправлення користувача:
   GET https://appleid.apple.com/auth/authorize
     ?client_id=com.example.web
     &redirect_uri=https://example.com/auth/apple/callback
     &response_type=code id_token
     &response_mode=form_post
     &scope=name email
     &state=<random_string>
     &nonce=<random_nonce>

2. Apple робить POST на redirect_uri з:
   - code
   - id_token
   - state
   - user (JSON з ім'ям — тільки при першому вході!)

Важливо: response_mode=form_post — Apple робить POST, не GET. Redirect URI повинен приймати POST.

Обробка callback

public function handleCallback(Request $request): RedirectResponse
{
    // Верифікація state
    abort_unless($request->state === session('apple_state'), 422);

    // Декодування id_token (без верифікації підпису поки)
    $idToken = $this->decodeIdToken($request->id_token);

    // user приходить тільки при першому вході
    $appleUser = $request->has('user')
        ? json_decode($request->user, true)
        : null;

    $user = User::updateOrCreate(
        ['apple_id' => $idToken['sub']],
        [
            'email'             => $idToken['email'] ?? null,
            'email_verified_at' => $idToken['email_verified'] ? now() : null,
            // Ім'я зберігаємо тільки якщо прийшло (перший вхід)
            'name' => $appleUser
                ? trim(($appleUser['name']['firstName'] ?? '') . ' ' . ($appleUser['name']['lastName'] ?? ''))
                : null,
        ]
    );

    // Оновлюємо ім'я тільки якщо воно не було встановлено раніше
    if ($appleUser && !$user->name) {
        $user->update(['name' => ...]);
    }

    Auth::login($user);

    return redirect()->intended('/dashboard');
}

Верифікація id_token

Apple публікує публічні ключі за адресою https://appleid.apple.com/auth/keys. Верифікація через JWT:

// composer require firebase/php-jwt
use Firebase\JWT\JWT;
use Firebase\JWT\JWK;

$keys = Cache::remember('apple_public_keys', 3600, function () {
    return Http::get('https://appleid.apple.com/auth/keys')->json();
});

$payload = JWT::decode($idToken, JWK::parseKeySet($keys));

// Перевірити: iss = appleid.apple.com, aud = client_id, exp, nonce

Relay email та обмеження

Якщо користувач приховав email, Apple видає relay-адресу @privaterelay.appleid.com. Листи дістаються на неї тільки якщо домен зареєстрований у Apple Developer Console → MoreConfigure Sign in with Apple for Email Communication.

Laravel Socialite

composer require laravel/socialite socialiteproviders/apple
// config/services.php
'apple' => [
    'client_id'     => env('APPLE_CLIENT_ID'),
    'client_secret' => env('APPLE_CLIENT_SECRET'), // згенерований JWT
    'redirect'      => env('APPLE_REDIRECT_URI'),
],

Socialite Apple провайдер обробляє більшість деталей, але client_secret потрібно періодично оновлювати.

Часова розкладка робіт

Етап Час
Реєстрація в Apple Developer 0.5 дня
Генератор client_secret + cron 1 день
OAuth callback + id_token верифікація 1.5 дня
Зберігання relay email, обробка імені 0.5 дня
Тести + перевірка на реальних пристроях 1 день

Разом: 4–5 днів.