Lebih lanjut ke konten utama

Bagaimana Cara Masuk dengan Apple Menggunakan Capacitor (2026)

Tambahkan Masuk dengan Apple ke aplikasi Capacitor 8 di iOS, Android, dan web: Pengaturan Pengembang Apple, plugin code, pengecekan token backend, dan kesalahan umum.

Kredit Artikel

Martin Donadieu

Pengarang

Valeria

Reviewer

Jordan

Editor

Cara Menggunakan Apple untuk Masuk dengan Capacitor (2026)

Untuk menambahkan Sign in dengan Apple ke sebuah Capacitor aplikasi, instal @capgo/capacitor-social-loginAktifkan kemampuan Sign in dengan Apple pada ID Aplikasi Anda dan di Xcode, panggil SocialLogin.initialize({ apple: {} }), kemudian panggil SocialLogin.login({ provider: 'apple' }). Pada iOS, ini membuka lembaran Apple native dan mengembalikan token identitas. Android dan web menggunakan aliran OAuth web Apple, yang memerlukan ID Layanan dan URL Redirect HTTPS.

Panduan ini mencakup pengaturan Pengembang Apple, klien code untuk iOS, Android, dan web, memverifikasi token pada backend, dan kesalahan yang paling mungkin Anda temui. Ini berfokus pada Capacitor 8 dan Xcode 26, yang App Store Connect telah memerlukan untuk unggahan sejak April 2026.

Apa yang Anda butuhkan sebelum Anda mulai

Persyaratan Mengapa
Anggota Program Pengembang Apple Berbayar ID App, ID Layanan, dan Kunci Masuk dengan Apple hanya tersedia bagi anggota
Mac dengan Xcode 26 Needed to build and upload iOS apps in 2026
Capacitor 8 proyek Plugin v8 bertarget Capacitor 8
Domain HTTPS yang Anda kendalikan Hanya untuk Android dan web. Apple menolak localhost dan URL HTTP sederhana
Endpoint backend Selalu untuk memverifikasi token. Pada Android juga menerima panggilan balik Apple

Jika Anda belum memiliki sertifikat tanda tangan, maka penghasil sertifikat iOS membuat mereka tanpa menari kunci Mac.

Bagaimana Sign in dengan Apple bekerja pada setiap platform

Apple hanya mengirimkan SDK asli untuk platformnya sendiri, sehingga aliran berbeda:

Platform Mechanisme ID Klien yang digunakan Backend yang diperlukan untuk login
iOS Asli ASAuthorizationAppleIDProvider jendela ID Paket Aplikasi Anda Tidak
Android OAuth web Apple di Tab Custom Chrome, Apple mengirimkan ke server Anda, server mengarah kembali ke aplikasi ID Layanan Ya
Web Pop-up JavaScript Apple ID Layanan Tidak (tetapi verifikasi token)

The audience (aud) of the identity token follows the client ID. Tokens from iOS carry your bundle ID, tokens from Android and web carry the Services ID. Your backend has to accept both.

Langkah 1: Konfigurasi Akun Pengembang Apple

aktifkan kemampuan pada ID Aplikasi Anda

  1. Buka Sertifikat, Identifikasi & Profil dan pilih Identifikasi.
  2. Buka ID Aplikasi yang sesuai dengan Capacitor appId (misalnya com.example.app. Buatlah jika tidak ada.
  3. Di bawah Kemampuan, centang Masuk dengan Apple dan simpan. Biarkan sebagai ID Aplikasi utama kecuali Anda mengelompokkan beberapa aplikasi.

Jika Anda mengubah kemampuan pada ID Aplikasi yang sudah ada, regenerasi profil pengaturan yang menggunakan itu. Profil lama tidak termasuk hak baru.

Buat ID Layanan (hanya Android dan web)

  1. Dalam Pengidentifikasiklik + dan pilih Pengidentifikasi Layanan.
  2. Pilih deskripsi seperti “Contoh Login Web” dan identifikasi seperti com.example.app.signin. Nilai ini menjadi clientId di Android dan web.
  3. Terbuka layanan ID baru, centang Masuk dengan Apple, dan klik Konfigurasi.
  4. Pilih ID Aplikasi Anda sebagai ID utama.
  5. Tambahkan domain Anda di bawah Domain dan Subdomain (tanpa skema, misalnya auth.example.com).
  6. Tambahkan URL kembali di bawah URL Kembali dengan jalur penuh https:// dengan jalur penuh, misalnya https://auth.example.com/apple/callbackUntuk login web tambahkan URL halaman yang memanggil login, dengan dan tanpa slash akhir.

Buatlah kunci Sign in dengan Apple (Android dan pertukaran token server)

  1. Pergi ke Kunci, klik +, centang Sign in dengan Apple, dan klik Konfigurasi untuk memilih ID Aplikasi utama.
  2. Daftarkan kunci dan unduh .p8 file. Apple hanya memungkinkan Anda mengunduhnya sekali.
  3. Perhatikan ID Kunci dan ID Tim Anda ID Tim di bagian kanan atas portal pengembang dan di bawah Anggota.

JWT yang dikirim ke endpoint token Apple. client_secret Daftarkan sumber email jika Anda mengirim email

Daftarkan sumber email jika Anda mengirim email

Sembunyikan Alamat Email , yang memberikan Andayang memberi Anda akses ke akun Apple Anda. @privaterelay.appleid.com alamat email. Apple hanya mengirimkan surel dari domain dan alamat email yang Anda daftarkan. Jasa > Masuk dengan Apple untuk Komunikasi Email. Lepaskan ini dan email reset kata sandi dan struk Anda akan hilang secara diam-diam.

Langkah 2: Pasang plugin

bun add @capgo/capacitor-social-login
bunx cap sync

Plugin ini menyertakan beberapa penyedia. Jika Anda hanya menggunakan Apple (dan mungkin Google), matikan yang lain di capacitor.config.ts SDK mereka tidak dikirimkan.

import type { CapacitorConfig } from '@capacitor/cli';

const config: CapacitorConfig = {
  appId: 'com.example.app',
  appName: 'Example',
  webDir: 'dist',
  plugins: {
    SocialLogin: {
      providers: {
        apple: true,
        google: false,
        facebook: false,
        twitter: false,
      },
    },
  },
};

export default config;

Run bunx cap sync Jangan mengaktifkan kembali setelah mengubah blok ini. Provider yang dinonaktifkan tidak tersedia pada waktu runtime, jadi jangan menonaktifkan yang kamu gunakan. Menghapus Facebook juga menghapus AD_ID peringatan izin yang dihasilkan oleh SDK di Google Play Console.

Langkah 3: Pengaturan iOS

  1. Run bunx cap open ios.
  2. Jalankan App target, buka Tanda Tangan & Kemampuan, klik + Kemampuan, dan tambahkan Masuk dengan Apple.
  3. Pastikan identifikasi paket aplikasi sesuai dengan ID Aplikasi yang Anda konfigurasi.

Xcode menulis com.apple.developer.applesignin ke dalam App.entitlements. Jika Anda membangun di CI atau dengan Capgo Buildcommit file entitikasi tersebut, jika tidak maka build di cloud akan menghasilkan aplikasi yang gagal dengan ASAuthorizationError code 1000.

Tidak Info.plist URL scheme atau AppDelegate Langkah 4: Pengaturan Android

Langkah 4: Pengaturan Android

Apple tidak memiliki Android SDK. Plugin membuka halaman autorisasi Apple di Tab Custom dengan ID Layanan Anda. Apple kemudian mengirim hasilnya sebagai POST form ke URL HTTPS kembali Anda. Server Anda menukar code, kemudian mengarahkan ke tautan dalam yang membuka aplikasi kembali dengan token.

Dalam android/app/src/main/AndroidManifest.xml, di dalam MainActivity <activity> element:

<intent-filter>
    <action android:name="android.intent.action.VIEW" />
    <category android:name="android.intent.category.DEFAULT" />
    <category android:name="android.intent.category.BROWSABLE" />
    <data android:scheme="com.example.app" android:host="apple-login" />
</intent-filter>

Kirimkan intent ke plugin

Ubah MainActivity.java jadi tautan dalam mendalam mencapai plugin:

package com.example.app;

import android.content.Intent;
import android.net.Uri;
import com.getcapacitor.BridgeActivity;
import com.getcapacitor.Plugin;
import com.getcapacitor.PluginHandle;
import ee.forgr.capacitor.social.login.SocialLoginPlugin;

public class MainActivity extends BridgeActivity {

    @Override
    protected void onNewIntent(Intent intent) {
        Uri data = intent.getData();
        if (Intent.ACTION_VIEW.equals(intent.getAction()) && data != null
                && "apple-login".equals(data.getHost())) {
            PluginHandle handle = getBridge().getPlugin("SocialLogin");
            if (handle != null) {
                Plugin plugin = handle.getInstance();
                if (plugin instanceof SocialLoginPlugin) {
                    ((SocialLoginPlugin) plugin).handleAppleLoginIntent(intent);
                    return;
                }
            }
        }
        super.onNewIntent(intent);
    }
}

Filtering pada host menjaga tautan dalam mendalam lainnya (reset kata sandi, tautan pemasaran) tetap berfungsi.

Endpoint panggilan balik

Apple mengirimkan code, id_token, state, dan pada login pertama sebuah user String JSON ke URL Anda untuk dikembalikan. Endpoint harus menukar code dan mengarahkan ke aplikasi dengan success=true plus token, yang merupakan kontrak yang plugin ini memproses. Contoh Hono minimal menggunakan jose:

import { Hono } from 'hono';
import { SignJWT, importPKCS8, createRemoteJWKSet, jwtVerify } from 'jose';
import { saveAppleRefreshToken } from './db'; // your own persistence layer

const app = new Hono();

const TEAM_ID = process.env.APPLE_TEAM_ID!;
const KEY_ID = process.env.APPLE_KEY_ID!;
const SERVICE_ID = process.env.APPLE_SERVICE_ID!; // com.example.app.signin
const PRIVATE_KEY = process.env.APPLE_PRIVATE_KEY!; // contents of the .p8 file
const APP_REDIRECT = 'com.example.app://apple-login';
const APPLE_JWKS = createRemoteJWKSet(new URL('https://appleid.apple.com/auth/keys'));

async function appleClientSecret() {
  const key = await importPKCS8(PRIVATE_KEY, 'ES256');
  return new SignJWT({})
    .setProtectedHeader({ alg: 'ES256', kid: KEY_ID })
    .setIssuer(TEAM_ID)
    .setSubject(SERVICE_ID)
    .setAudience('https://appleid.apple.com')
    .setIssuedAt()
    .setExpirationTime('5m')
    .sign(key);
}

app.post('/apple/callback', async (c) => {
  const form = await c.req.parseBody();
  const code = String(form.code ?? '');
  if (!code) {
    return c.redirect(`${APP_REDIRECT}?success=false`);
  }

  // `form.user` is only present on the first authorization. Store it now.

  const res = await fetch('https://appleid.apple.com/auth/token', {
    method: 'POST',
    headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
    body: new URLSearchParams({
      client_id: SERVICE_ID,
      client_secret: await appleClientSecret(),
      code,
      grant_type: 'authorization_code',
      redirect_uri: 'https://auth.example.com/apple/callback',
    }),
  });
  if (!res.ok) {
    return c.redirect(`${APP_REDIRECT}?success=false`);
  }
  const tokens = await res.json();

  // Verify the identity token, then keep the long-lived refresh token on the server.
  // Only the short-lived tokens go back to the app in the deep link.
  const { payload } = await jwtVerify(tokens.id_token, APPLE_JWKS, {
    issuer: 'https://appleid.apple.com',
    audience: SERVICE_ID,
  });
  if (tokens.refresh_token) {
    await saveAppleRefreshToken(String(payload.sub), tokens.refresh_token);
  }
  const params = new URLSearchParams({
    success: 'true',
    access_token: tokens.access_token,
    id_token: tokens.id_token,
  });
  return c.redirect(`${APP_REDIRECT}?${params}`);
});

export default app;

Plugin membaca token dari tautan dalam mendalam query string, jadi apa pun yang Anda masukkan dapat berakhir di log atau dibaca oleh aplikasi lain yang mendaftarkan scheme khusus yang sama. Kirimkan hanya token yang hidup singkat access_token dan id_token, tidak pernah token refresh, verifikasi id_token token, pastikan nonce dan pada server Anda sebelum Anda percayakan, dan gunakan scheme unik untuk aplikasi Anda (ID balik aplikasi Anda).

Bagaimana client_secret Token JWT dapat bertahan hingga enam bulan, tetapi menghasilkan token singkat per permintaan dapat menghindari kegagalan waktu kedaluwarsa. Simpan .p8 file di manajer rahasia Anda, tidak dalam bundle aplikasi.

Langkah 5: Pengaturan Web

Konfigurasi web menggunakan Apple JS dengan ID Layanan. Tambahkan URL halaman yang tepat yang memicu login ke ID Layanan URL kembali. Apple tidak menerima localhost, sehingga uji coba login web pada domain pratinjau yang di-deploy atau melalui terowongan dengan hostname yang sebenarnya.

Langkah 6: Inisialisasi dan login

inisialisasi sekali pada awal aplikasi. Kirimkan redirectUrl hanya pada Android dan web. Pada iOS, nilai redirectUrl tidak kosong membuat plugin mengirimkan hasil ke URL tersebut, yang Anda tidak inginkan dengan aliran asli.

import { Capacitor } from '@capacitor/core';
import { SocialLogin } from '@capgo/capacitor-social-login';

const platform = Capacitor.getPlatform();

export async function initAuth() {
  await SocialLogin.initialize({
    apple: {
      clientId: platform === 'ios' ? 'com.example.app' : 'com.example.app.signin',
      redirectUrl:
        platform === 'android'
          ? 'https://auth.example.com/apple/callback'
          : platform === 'web'
            ? 'https://app.example.com/login'
            : '',
    },
  });
}

Kemudian, trigger login dari tombol. Gunakan nonce acak agar server Anda dapat menolak token ulang:

import { SocialLogin } from '@capgo/capacitor-social-login';

export async function signInWithApple() {
  const nonce = crypto.randomUUID();

  try {
    const { result } = await SocialLogin.login({
      provider: 'apple',
      options: {
        scopes: ['email', 'name'],
        nonce,
      },
    });

    if (!result.idToken) {
      throw new Error('Apple did not return an identity token');
    }

    // Send to your backend. Name and email are only present on the first login.
    const response = await fetch('https://api.example.com/auth/apple', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        idToken: result.idToken,
        nonce,
        givenName: result.profile.givenName,
        familyName: result.profile.familyName,
      }),
    });
    return response.json();
  } catch (error: any) {
    if (error?.code === 'USER_CANCELLED') {
      return null; // user closed the sheet, not a failure
    }
    throw error;
  }
}

Respons memberikan Anda:

Bidang Isi
result.idToken JWT yang ditandatangani oleh Apple, hal yang diverifikasi oleh server Anda
result.profile.user ID pengguna stabil Apple (sama dengan klaim) sub claim)
result.profile.email Alamat email atau alamat relay pribadi, ketika diberikan
result.profile.givenName / familyName Hanya pada autentikasi pertama
result.accessToken Dengan pengaturan default ini, menyimpan otorisasi code, bukan token akses nyata
result.authorizationCode Sedia ketika Anda menginisialisasi dengan useProperTokenExchange: true

Jika server Anda memerlukan token pembaruan Apple (misalnya untuk memanggil endpoint revoke ketika pengguna menghapus akun mereka), atur useProperTokenExchange: true di dalam apple konfigurasi dan pertukaran authorizationCode di server.

Langkah 7: Verifikasi token identitas di backend Anda

Tidak pernah percaya pada bidang profil yang dikirim oleh klien. Verifikasi tanda tangan JWT terhadap kunci publik Apple dan periksa klaim:

import { createRemoteJWKSet, jwtVerify } from 'jose';

const appleKeys = createRemoteJWKSet(new URL('https://appleid.apple.com/auth/keys'));

export async function verifyAppleToken(idToken: string, expectedNonce: string) {
  const { payload } = await jwtVerify(idToken, appleKeys, {
    issuer: 'https://appleid.apple.com',
    audience: ['com.example.app', 'com.example.app.signin'], // bundle ID + Services ID
  });

  if (payload.nonce !== expectedNonce) {
    throw new Error('Nonce mismatch');
  }

  return {
    appleUserId: payload.sub as string,
    email: payload.email as string | undefined,
    emailVerified: payload.email_verified === true || payload.email_verified === 'true',
  };
}

Simpan rekaman pengguna pada sub, bukan pada alamat email. Alamat email dapat menjadi alamat relay, dan pengguna dapat menghentikan berbaginya alamat tersebut. Setelah verifikasi, keluarkan token sesi Anda sendiri. Jika Anda menggunakan Supabase atau Firebase, mereka akan memverifikasi token untuk Anda, lihat Supabase dengan Capacitor Login Sosial.

Aturan App Store yang perlu diingat

  • Pedoman 4.8: jika Anda menawarkan login Google, Facebook, atau login pihak ketiga lainnya sebagai sistem akun utama, Anda harus menawarkan pilihan privasi yang setara. Sign in dengan Apple memenuhi syarat.
  • Pedoman 5.1.1(v)Aplikasi yang memungkinkan pengguna membuat akun harus memungkinkan mereka menghapus akun di aplikasi. Untuk pengguna Sign in dengan Apple, hubungi Apple's https://appleid.apple.com/auth/revoke endpoint pada penghapusan. Lihat di Petunjuk Menghapus Akun.
  • Desain Tombol: Gunakan gaya tombol yang disetujui oleh Apple dan buat tombol ini setidaknya sebesar tombol login lainnya.

Penyelesaian Masalah

Symptom Penyebab yang Mungkin Fix
ASAuthorizationError code 1000 di iOS Keterampilan atau hak istimewa hilang dalam target yang dibangun Kemampuan atau hak istimewa hilang di target yang dibangun App.entitlementsregenerasi profil
Code 1001 di iOS Pengguna batal Plugin menolak dengan USER_CANCELLED, dianggap sebagai tidak ada kesalahan
invalid_client pada Android atau web Salah clientId Gunakan ID Layanan, periksa ID Tim, ID Kunci, dan isi kunci client_secret Gunakan ID Layanan, periksa ID Tim, ID Kunci, dan isi kunci
invalid_request: Invalid redirect_uri URL Pengembalian tidak terdaftar dengan tepat Tambahkan fullstack https:// Aplikasi tidak kembali setelah login Android
Skenario atau host filter intent berbeda dari redirect server Diferensiasi scheme atau host filter intent dengan host redirect server Bandingkan com.example.app://apple-login character by character
apple.android.redirectUrl is null or empty Tidak redirectUrl Pada Android Masukkan URL panggilan HTTPS Anda saat menginisialisasi pada Android
Nama dan email adalah null Bukan otorisasi pertama Baca dari database Anda. Revoke aplikasi di pengaturan perangkat untuk menguji lagi
Token ditolak oleh backend: aud Tidak cocok Hanya server yang menerima satu audiens Menerima baik ID paket dan ID Layanan

Perbaikan pengiriman setelah rilis

Masalah autentikasi paling banyak hidup di TypeScript: ID klien salah per platform, nonce yang hilang, penanganan kesalahan yang buruk. Mereka dapat dikirimkan kepada pengguna pada hari yang sama dengan Capgo pembaruan hidup tanpa harus menunggu Tinjauan Aplikasi. Perubahan akses, manifesto Android atau MainActivity perlu dibangun ulang di toko.

Dimana untuk pergi selanjutnya

Update instan untuk aplikasi Capacitor

Ketika bug layer web masih aktif, kirimkan perbaikan melalui Capgo bukan menunggu hari-hari untuk persetujuan toko aplikasi. Pengguna mendapatkan update di latar belakang sementara perubahan native tetap dalam jalur review normal.

Bantuan manusia dari Martin

Mulai Sekarang

Terbaru dari Blog Kami

Capgo memberikan Anda wawasan terbaik yang Anda butuhkan untuk menciptakan aplikasi mobile profesional yang sebenarnya.