RORK LABEN
TOOLING — Rorkの開発者向けリポジトリが動き続けています。rork-xcodeが7月16日、rork-deviceが7月15日、rork-plistが7月13日に更新されましたOPUS46 — RorkでClaude Opus 4.6が稼働しています。Rork MaxはClaude Codeを土台にアプリを組み立てる設計ですSIM — ブラウザ上で動くクラウドのiOSシミュレータを備え、実機へのインストールは1クリック、App Storeへの提出は2クリックと案内されていますMAX — Rork MaxはReact Nativeではなく純粋なSwiftを出力します。iPhone・iPad・Apple Watch・Apple TV・Vision Pro、そしてiMessageまでが射程ですNATIVE — HealthKit、ARKitとLiDAR、NFC、Dynamic Island、Live Activities、Metalによる3D、Core MLのオンデバイス推論まで扱えますSEED — RorkはLeft Lane Capitalが主導する1,500万ドルのシードラウンドを実施し、Peak XVとa16z Speedrunが参加しましたTOOLING — Rorkの開発者向けリポジトリが動き続けています。rork-xcodeが7月16日、rork-deviceが7月15日、rork-plistが7月13日に更新されましたOPUS46 — RorkでClaude Opus 4.6が稼働しています。Rork MaxはClaude Codeを土台にアプリを組み立てる設計ですSIM — ブラウザ上で動くクラウドのiOSシミュレータを備え、実機へのインストールは1クリック、App Storeへの提出は2クリックと案内されていますMAX — Rork MaxはReact Nativeではなく純粋なSwiftを出力します。iPhone・iPad・Apple Watch・Apple TV・Vision Pro、そしてiMessageまでが射程ですNATIVE — HealthKit、ARKitとLiDAR、NFC、Dynamic Island、Live Activities、Metalによる3D、Core MLのオンデバイス推論まで扱えますSEED — RorkはLeft Lane Capitalが主導する1,500万ドルのシードラウンドを実施し、Peak XVとa16z Speedrunが参加しました
記事一覧/開発ツール
開発ツール/2026-04-24中級

Rork アプリに Sign in with Apple を組み込む手順 — 審査で求められる実装とよくある詰まりどころ

Rork で作ったアプリに Apple ID サインインを後付けする手順をまとめました。Google/Facebook ログインを入れた途端に審査で指摘される Guideline 4.8 の要件、expo-apple-authentication の落とし穴、Android・Web での代替フローまで、実装に詰まった時に参照できる形で整理しています。

Rork515Sign in with Apple2認証14App Store審査8Expo149

Rork で作ったアプリに Google サインインを実装して、いざ App Store に出そうとしたら「Guideline 4.8 — Login Services」でリジェクトされた、という相談をよく受けます。Apple が定めるルールはシンプルで、サードパーティのサインイン手段(Google, Facebook, LINE, X など)を1つでも提供するなら、Sign in with Apple も同等のオプションとして用意しなければなりません。

ここではRork のプロジェクトに Sign in with Apple を後付けする実装を、実際に審査を通った手順に沿って書いていきます。ドキュメントに沿って書いた通りに動かない箇所や、iOS シミュレータでは再現しない本番特有の挙動も含めて、つまずきやすいポイントを先回りで共有します。

なぜこのタイミングで実装しておくべきか

Sign in with Apple は「Apple がリジェクトしたから慌てて入れる」という順序で実装されがちですが、これは後手に回る典型例です。後から入れようとすると、既存のユーザー管理テーブルの設計を変える必要が出てきたり、Apple 固有の仕様(メール匿名化・初回サインインのみ氏名が返る、など)に合わせてバックエンドを書き直すことになります。

私自身も過去に2つのアプリで同じ失敗をしています。SNS ログインを実装した直後のリリースで必ず 4.8 リジェクトを受け、リリースが1週間遅れました。その経験から、現在は新規プロジェクトでは「他のサインイン手段を実装する前に Apple を先に入れる」ようにしています。Rork で生成したコードベースはまだ小さいうちに Apple を足しておくほうが、確実に楽です。

実装が必要になる条件

以下のいずれかに該当する場合、Sign in with Apple は実質必須です。

  • Google / Facebook / X / LINE / Microsoft などサードパーティ認証を1つ以上使っている
  • 独自のメール+パスワード認証だけなら免除されるケースがある(ただしメール必須で、Apple ユーザーには使いづらい)
  • メールマジックリンクのみの場合も実質免除されるが、UX 上不利

逆に、認証自体をしないアプリ(ゲーム、ユーティリティ、閲覧専用など)はそもそも対象外です。

Expo ベースの Rork プロジェクトで準備すること

Rork で生成される典型的な構成は Expo SDK + React Native です。Sign in with Apple は expo-apple-authentication を使います。

# Rork エディタのターミナル、またはローカルで実行
npx expo install expo-apple-authentication

インストール後、app.json に iOS 専用の設定を追加します。Rork は自動で app.json を生成しますが、認証系は手動で追記が必要です。

{
  "expo": {
    "ios": {
      "bundleIdentifier": "com.yourcompany.yourapp",
      "usesAppleSignIn": true
    },
    "plugins": ["expo-apple-authentication"]
  }
}

usesAppleSignIn: truepluginsexpo-apple-authentication を両方入れるのがポイントです。どちらか片方だけだと、EAS Build で Entitlement が付与されず、ビルドは通るのに起動時にクラッシュするという分かりにくい失敗をします。

Apple Developer 側の設定

Apple Developer Portal で以下を有効化します。

  • Certificates, Identifiers & Profiles → Identifiers から対象の App ID を開く
  • 「Sign In with Apple」の Capability にチェックを入れる
  • 保存後、Provisioning Profile を再生成する(ここを忘れがち)

再生成した Provisioning Profile を EAS に同期させるには、一度 eas build:configure を実行するか、次回のビルド前に eas credentials で最新状態にすると確実です。

最小実装:サインインボタンとハンドラ

Rork で生成された画面に、以下のコンポーネントを追加します。Apple は「Sign in with Apple」ボタンのデザインにも厳格で、提供されている純正コンポーネントをそのまま使うのが一番安全です。

import * as AppleAuthentication from 'expo-apple-authentication';
import { Platform, View, Alert } from 'react-native';
import { useEffect, useState } from 'react';
 
export function AppleSignInButton({ onSuccess }: { onSuccess: (user: AppleUser) => void }) {
  const [available, setAvailable] = useState(false);
 
  useEffect(() => {
    // iOS 13+ のみサポート。iPad シミュレータでは動作するが実機確認を推奨
    AppleAuthentication.isAvailableAsync().then(setAvailable);
  }, []);
 
  // Android / Web では表示しない(後述のフォールバックで対応)
  if (Platform.OS !== 'ios' || !available) return null;
 
  return (
    <AppleAuthentication.AppleAuthenticationButton
      buttonType={AppleAuthentication.AppleAuthenticationButtonType.SIGN_IN}
      buttonStyle={AppleAuthentication.AppleAuthenticationButtonStyle.BLACK}
      cornerRadius={8}
      style={{ width: '100%', height: 48 }}
      onPress={async () => {
        try {
          const credential = await AppleAuthentication.signInAsync({
            requestedScopes: [
              AppleAuthentication.AppleAuthenticationScope.FULL_NAME,
              AppleAuthentication.AppleAuthenticationScope.EMAIL,
            ],
          });
          // credential.identityToken をサーバへ送り検証する
          onSuccess({
            user: credential.user,
            email: credential.email,          // 初回サインイン時のみ入る
            fullName: credential.fullName,    // 初回サインイン時のみ入る
            identityToken: credential.identityToken!,
          });
        } catch (e: any) {
          if (e.code === 'ERR_REQUEST_CANCELED') return;
          Alert.alert('サインインに失敗しました', e.message);
        }
      }}
    />
  );
}
 
type AppleUser = {
  user: string;
  email: string | null;
  fullName: AppleAuthentication.AppleAuthenticationFullName | null;
  identityToken: string;
};

このコードで押さえておきたいのは、emailfullName初回サインイン時にしか返ってこない という Apple 固有の仕様です。2回目以降は null になるため、バックエンド側で初回に受け取った値を保存しておかないと、以後ユーザー名を表示できません。ここは他のソーシャルログインと最も挙動が違う部分で、実装を見直すポイントになります。

期待される出力

初回成功時、credential.user には 001234.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.xxxx のような Apple 固有のユーザー ID が返ります。この ID はアプリとユーザーの組み合わせで一意に発番され、アプリをアンインストールしても変わりません。バックエンド側ではこの user ID を主キーに紐付けて保存します。

バックエンド検証:identityToken を捨てない

よくある実装ミスが「identityToken を使わずに credential.user だけで認証する」というものです。これだと悪意あるクライアントが任意のユーザー ID を偽装して送れるため、サーバ側での認証としては成立しません。正しくは、受け取った identityToken を Apple の公開鍵で検証します。

// Node.js / Cloudflare Workers でも動く一般的な検証コード
import { createRemoteJWKSet, jwtVerify } from 'jose';
 
const JWKS = createRemoteJWKSet(new URL('https://appleid.apple.com/auth/keys'));
 
export async function verifyAppleIdentityToken(identityToken: string, audience: string) {
  const { payload } = await jwtVerify(identityToken, JWKS, {
    issuer: 'https://appleid.apple.com',
    audience, // アプリの Bundle ID。Services ID を使う場合はそちらを指定
  });
  return {
    sub: payload.sub as string,     // = credential.user
    email: payload.email as string | undefined,
    emailVerified: payload.email_verified === 'true',
  };
}

audience には Bundle ID(例: com.yourcompany.yourapp)を入れます。Services ID(Web ログイン用)を使う場合はそちらを指定します。ここを間違えると JWTClaimValidationFailed でサーバ側だけ延々エラーが出る、という現象になります。

Android・Web ユーザーへの対応

Sign in with Apple はネイティブ UI としては iOS 限定ですが、Apple は「iOS 以外のプラットフォームでも同等のサインイン手段を提供すること」を求めています。Android / Web 版を出している場合は、Apple の OAuth フローをブラウザ経由で呼び出す必要があります。

Rork で Android ビルドや Web 版を出すなら、expo-auth-session を使って Apple の OAuth エンドポイント(Services ID 経由)に誘導するのが現実的です。ここは本記事の範囲を超えるため、Rork で iOS 実機テストを行う Rork Companion ガイドApp Store 提出の完全ガイド と併せて、別途 Services ID の準備手順を確認してください。

審査でつまずきやすい3つのポイント

実装できたと思っても、審査で指摘されやすいのは以下の3つです。

1. ボタンが他のサインインより下にある

Apple のガイドラインでは、Sign in with Apple を他の認証オプションより 上に、または同等に 配置することが推奨されています。Google ボタンだけ強調されていると、4.8 で指摘されることがあります。ボタンのサイズ・色のコントラストも揃えましょう。

2. メール共有オプションの説明不足

Apple はユーザーに「メールを共有する/隠す」を選ばせます。「隠す」を選ぶと @privaterelay.appleid.com の匿名メールがアプリに届きます。この匿名メールに送信したメールは Apple 経由でユーザーに転送される仕組みですが、これをテストせずに「この宛先は無効なユーザー」として除外する実装にしていると、匿名メールユーザーからの問い合わせに気づけません。

3. Apple ID 削除リクエストへの対応未実装

2022年6月以降、Sign in with Apple を使うアプリには「アカウント削除機能」の実装が義務付けられています。サインイン機能だけ入れて削除機能がないと、4.8 ではなく 5.1.1(v) で指摘されます。アプリ内に「アカウントを削除する」ボタンを設け、削除処理の際は AppleAuthentication.revokeAsync を呼び出して、Apple 側のトークンも失効させる必要があります。

料金プランと実機テストの組み合わせ

Sign in with Apple の開発は Apple Developer Program(年間 $99)が必須です。ここは Rork の料金とは別枠です。Rork 側のプラン選びについては Rork 料金プラン正直比較 2026 年版 にまとめてありますので、Apple Developer との組み合わせで最低限かかる費用を見積もるときに参考にしてください。

次のステップ

この記事のコードは最小構成ですが、これだけで iOS ビルド → TestFlight → 審査までの流れに乗せられます。次に取り組むなら、まずはシミュレータではなく実機で Apple ID サインインを試してみてください。匿名メールの動作や、同じ Apple ID でアンインストール→再インストールした時の挙動は、実機でないと再現しないものが多くあります。より本格的な課金連携まで踏み込むなら、Rork での Stripe サブスクリプション実装ガイド に進むとスムーズです。

シェア

お読みいただきありがとうございます

Rork Lab は広告なしで運営しており、サーバー費用などの運営コストはメンバーシップのご支援で賄っています。実装コード・ベンチマーク・本番設計パターンなど、実務でお役立ていただける記事を毎日更新しています。もし読んでよかったと感じていただけましたら、ぜひご覧ください。

  • コピー&ペーストで使える実装コード付き
  • 毎日新しい上級ガイドを追加
  • ¥580/月 または ¥1,480 の永久アクセス
メンバーシップを見る →

もしこの記事がお役に立ちましたら、チップ(¥150)で応援いただけると大変励みになります。広告なしでの運営を続けるため、皆さまのご支援が大きな力になっています。

関連記事

開発ツール2026-06-15
Rork で作った Expo アプリのログインを切らさない — トークン更新の競合を単一化で防ぐ
Rork が生成する Expo アプリにログインを足すと、最初は動いても本番でじわじわ「勝手にログアウトされる」報告が増えます。原因の多くはトークン更新の競合です。リフレッシュを単一化し、安全に保存し、失効を正しく扱う信頼性設計を実装視点でまとめます。
開発ツール2026-06-14
Rork で出したアプリが ITMS-91053 で弾かれたら — Privacy Manifest と Required Reason API の実務
Rork が生成する Expo アプリを App Store に提出すると、コードに覚えがなくても Privacy Manifest 関連の警告で止まることがあります。Required Reason API と SDK 側のマニフェスト漏れの両方を、提出前に潰す手順をまとめました。
開発ツール2026-05-23
Rork 生成 Expo アプリの Privacy Manifest を SDK 連鎖まで監査する — 提出前1日で洗い切る個人開発者の手順
Rork が生成する Expo アプリの依存 SDK を Privacy Manifest 観点で全数監査する手順。Required Reason API の事前検出・PrivacyInfo.xcprivacy 自動収集・ITMS-91053 ゼロでの提出を、個人開発12年の運用視点でまとめます。
📚RECOMMENDED BOOKS
大規模言語モデル入門
山田育矢
LLM開発
生成AIプロンプトエンジニアリング入門
我妻幸長
プロンプト
Claude CodeによるAI駆動開発入門
平川知秀
AI駆動開発
※ アフィリエイトリンクを含みます
もっと見る →