Backend’de Sign in ...
 
Paylaş:
Bildirimler
Tümünü temizle

Backend’de Sign in with Apple + JWT Entegrasyonu: Node.js / Laravel / Go Örnekleri (2026 Güncel)

1 Gönderiler
1 Üyeler
0 Reactions
18 Görüntüleme
Apple Türk
(@appleturk)
Gönderiler: 59
Üye Admin
Konu başlatıcı
 

 

Apple’ın Sign in with Apple özelliği artık birçok uygulamanın olmazsa olmazı oldu. Ama iş backend’e gelince işler biraz karışıyor: Apple’dan gelen identity token’ı nasıl doğrulayacağız? Client secret nasıl üretilecek? Sonra bunu JWT’ye çevirip kendi auth sistemimize nasıl entegre edeceğiz?

Bu konuyu açtım çünkü Türkçe kaynaklarda hâlâ çok eksik var. Ben de son projelerimde (hem Node.js hem Laravel tarafında) epey uğraştım, öğrendiklerimi paylaşayım. Siz de deneyimlerinizi, kullandığınız framework’leri, wrapper’ları, hatta Firebase kullanıyorsanız nasıl yaptığınızı yazın. Link atabilirsiniz, kod snippet’leri paylaşabilirsiniz – herkes faydalansın.

1. Temel Mantık (Kısaca)

Apple’dan gelen id_token (JWT formatında) şu bilgileri içerir:

  • iss → Apple’ın issuer’ı[]( https://appleid.apple.com)
  • aud → Senin uygulamanın bundle ID’si (veya Services ID)
  • sub → Kullanıcının unique ID’si (her zaman aynı kalır)
  • email (ilk seferde gelir, sonra gizli olabilir)
  • exp, iat vs.

Backend’de yapman gereken:

  1. Apple’ın public key’lerini indirip id_token’ı doğrula (JWK endpoint’ten).
  2. Doğruladıktan sonra kendi JWT’ni üret (veya session başlat).
  3. Client secret üretimi için private key + team ID + key ID kullan (bu kısım en çok takılan yer).

2. Node.js Örneği (En Kolay Yolu)

const jwt = require('jsonwebtoken');
const jwksClient = require('jwks-rsa');
const client = jwksClient({
  jwksUri: 'https://appleid.apple.com/auth/keys'
});

function getAppleSigningKey(header) {
  return new Promise((resolve, reject) => {
    client.getSigningKey(header.kid, (err, key) => {
      if (err) return reject(err);
      resolve(key.getPublicKey());
    });
  });
}

async function verifyAppleToken(idToken) {
  const decoded = jwt.decode(idToken, { complete: true });
  const key = await getAppleSigningKey(decoded.header);
  
  return jwt.verify(idToken, key, {
    audience: 'com.seninapp.bundleid', // veya Services ID
    issuer: 'https://appleid.apple.com'
  });
}

// Kullanım
app.post('/auth/apple', async (req, res) => {
  const { identityToken } = req.body;
  try {
    const payload = await verifyAppleToken(identityToken);
    // Artık payload.sub ile kullanıcıyı bul/oluştur
    // Kendi JWT'ni üret
    const myJWT = jwt.sign({ userId: payload.sub, email: payload.email }, 'senin-secret');
    res.json({ token: myJWT });
  } catch (err) {
    res.status(401).json({ error: 'Token geçersiz' });
  }
});

3. Laravel Örneği (Socialite ile Basitleştirilmiş)

Laravel’de socialite + laravel-socialite-apple paketiyle çok kolay:

composer require socialiteproviders/apple

Config/services.php

'apple' => [
    'client_id' => env('APPLE_CLIENT_ID'),
    'client_secret' => env('APPLE_CLIENT_SECRET'), // aşağıda nasıl üretileceğini anlatacağım
    'redirect' => env('APPLE_REDIRECT_URI'),
],

Client secret üretimi (her seferinde dinamik yap):

use Firebase\JWT\JWT;

$header = [
    'alg' => 'ES256',
    'kid' => env('APPLE_KEY_ID'),
];

$payload = [
    'iss' => env('APPLE_TEAM_ID'),
    'iat' => time(),
    'exp' => time() + 86400 * 180, // 6 ay
    'aud' => 'https://appleid.apple.com',
    'sub' => env('APPLE_CLIENT_ID'),
];

$privateKey = file_get_contents(storage_path('apple/AuthKey_XXXX.p8')); // Apple Developer'dan indirdiğin .p8 key

$clientSecret = JWT::encode($payload, $privateKey, 'ES256', $header['kid']);

Sonra Socialite ile login:

Socialite::driver('apple')->stateless()->user();

4. Go (Golang) Örneği (Basit ve Hızlı)

import (
    "crypto/x509"
    "encoding/pem"
    "github.com/golang-jwt/jwt/v5"
    "github.com/lestrrat-go/jwx/v2/jwk"
)

func VerifyAppleToken(idToken string) (*jwt.MapClaims, error) {
    keySet, err := jwk.Fetch(context.Background(), "https://appleid.apple.com/auth/keys")
    if err != nil { return nil, err }

    token, err := jwt.Parse(idToken, func(token *jwt.Token) (interface{}, error) {
        kid := token.Header["kid"].(string)
        key, _ := keySet.LookupKeyID(kid)
        var publicKey interface{}
        key.Raw(&publicKey)
        return publicKey, nil
    }, jwt.WithIssuer("https://appleid.apple.com"), jwt.WithAudience("com.seninapp.bundleid"))

    if err != nil { return nil, err }
    claims, ok := token.Claims.(jwt.MapClaims)
    if !ok { return nil, errors.New("claims error") }
    return &claims, nil
}

5. Client Secret Üretimi (Herkesin Tıkanma Noktası)

Apple Developer → Certificates, Identifiers & Profiles → Keys → Yeni key oluştur (Sign in with Apple için). İndirdiğin AuthKey_XXXX.p8 dosyasını güvenli yerde sakla. Yukarıdaki JWT encode ile client secret’ı 6 ayda bir yenile (otomatik yapabilirsin).

Sorular & Paylaşımlarınız

  • Siz hangi framework’ü kullanıyorsunuz? (NestJS, Django, Spring Boot vs.)
  • Firebase Authentication ile entegre eden var mı? Nasıl yaptınız?
  • Apple’ın email gizleme özelliği (privaterelay.appleid.com) ile nasıl başa çıkıyorsunuz?
  • Herhangi bir wrapper öneriniz var mı? (mesela node-apple-signin-auth)

Deneyimlerinizi, kod parçacıklarınızı, linkleri bekliyorum. Birlikte Türkçe’nin en iyi Sign in with Apple rehberini oluşturalım!


Bu konu 2 hafta önce tarafından Apple Türk tarihinde düzenlendi
 
Gönderildi : 02/02/2026 6:40 am
Başa dön tuşu