> For the complete documentation index, see [llms.txt](https://codemash.gitbook.io/codemash/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://codemash.gitbook.io/codemash/cloud/membership/integrations/providers/apple-sign-in.md).

# Apple Sign In

Connect Apple Sign In to Membership — let your users sign in with Apple Sign In.

Lets your users sign in with their Apple Account, through a Services ID and a private key of your Apple Developer account.

## Get your credentials

You need a paid Apple Developer account and a primary App ID with **Sign in with Apple**.

1. Sign in to [Certificates, Identifiers & Profiles](https://developer.apple.com/account/resources/identifiers/list) and open **Identifiers**. Press **+**, choose **Services ID**, **Continue**, enter a description and an identifier such as `com.acme.app.signin`, and **Register**. This is the **Services Id**.
2. Open the Services ID, tick **Sign in with Apple** and press **Configure**. Choose your primary App ID (its bundle id, such as `com.acme.app`, is the **App Bundle Identifier**). Under **Website URLs**, add your domains and return URLs (comma separated), then **Done**, **Continue**, **Save**.
3. Open **Keys**, press **+**, tick **Sign in with Apple**, **Configure** it with the same App ID, and **Register**. Note the **Key ID** and **Download** the `.p8` file — Apple lets you download it only once.
4. Your **Team ID** is shown in your Apple Developer account under **Membership details**.

Source: Apple, [Configure Sign in with Apple for the web](https://developer.apple.com/help/account/configure-app-capabilities/configure-sign-in-with-apple-for-the-web) and [Create a Sign in with Apple private key](https://developer.apple.com/help/account/capabilities/create-a-sign-in-with-apple-private-key). The same Team ID and key steps for push notifications are on [Apple Push Notification service](/codemash/cloud/push/integrations/providers/apns.md).

## Connect it in Cloud

**Where:** Membership → Integrations → **Add New Integration** → Apple Sign In → **Connect** · `/projects/<project>/membership/integrations/new/apple`

Fill the form and press **Save**. The form stays open as **Editing Apple Sign In integration** with the **ENABLED** badge and the new id (`int_5LMZS6z39FbMeVzvFcEYls`).

| Field                  | Required | What it does                                                                                                        | Example                     |
| ---------------------- | -------- | ------------------------------------------------------------------------------------------------------------------- | --------------------------- |
| Team Id                | yes      | Your Apple Developer team.                                                                                          | `ABCDE12345`                |
| App Bundle Identifier  | yes      | The bundle id of your primary App ID.                                                                               | `com.acme.app`              |
| Services Id            | yes      | The Services ID you registered for the web.                                                                         | `com.acme.app.signin`       |
| Key Id                 | yes      | The id of the Sign in with Apple key.                                                                               | `KEY1234567`                |
| Private key (.p8)      | yes      | The text of the `.p8` file, from `-----BEGIN PRIVATE KEY-----` to the end. Encrypted on save and never shown again. | the text of your `.p8` file |
| Production environment | no       | **Use Apple production Sign-In gateway**: on for production, off for the sandbox while you build.                   | off                         |
| Integration Name       | yes      | The name in your integrations list.                                                                                 | `Sign in with Apple`        |

**OAuth Modes** — press **Add OAuth mode** for each surface of your app (web, mobile, admin) that signs in with this provider:

| Field                                      | Required | What it does                                       | Example                                       |
| ------------------------------------------ | -------- | -------------------------------------------------- | --------------------------------------------- |
| Mode name                                  | yes      | A name for the surface.                            | `web`                                         |
| Callback URL                               | yes      | Where the user lands in your app after signing in. | `https://app.example.com/auth/apple/callback` |
| Logout URL (optional)                      | no       | Where the user lands after signing out.            | —                                             |
| Failure redirect URL (optional)            | no       | Where the user lands when the sign-in fails.       | `https://app.example.com/sign-in?failed=1`    |
| Role to assign on first sign-in (optional) | no       | The role a new user gets on the first sign-in.     | —                                             |

<figure><img src="https://712692422-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FHy372bqsaex2cqS3ikhL%2Fuploads%2Fgit-blob-2b1ae5e34a8d935c2ab99f079db11f89ad618106%2Fapple-sign-in-form-1.png?alt=media" alt="New Apple Sign In Integration form: Team Id ABCDE12345, App Bundle Identifier com.acme.app, Services Id com.acme.app.signin, Key Id KEY1234567"><figcaption><p>The filled form.</p></figcaption></figure>

<figure><img src="https://712692422-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FHy372bqsaex2cqS3ikhL%2Fuploads%2Fgit-blob-d9d94af11fb1e35363827eaf22405018257fe667%2Fapple-sign-in-form-2.png?alt=media" alt="OAuth Modes with one mode: Mode name web, Callback URL https://app.example.com/auth/apple/callback, Failure redirect URL https://app.example.com/sign-in?failed=1, and Add OAuth mode"><figcaption><p>One OAuth mode for the web app.</p></figcaption></figure>

<figure><img src="https://712692422-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FHy372bqsaex2cqS3ikhL%2Fuploads%2Fgit-blob-a9e0feb9dbf398eb684481b92d7e0706ff8f836d%2Fapple-sign-in-saved-3.png?alt=media" alt="Editing Apple Sign In integration after save: the ENABLED badge, the id int_5LMZS6z39FbMeVzvFcEYls, the provider fields empty and the Integration Name Sign in with Apple"><figcaption><p>After save.</p></figcaption></figure>

{% hint style="warning" %}
Two things to know today. **(1)** When you open a saved integration, its fields come back empty — only the name and the state load, and the saved OAuth modes are not shown — so type every value again before you press **Save** on it. **(2)** No Norbix sign-in endpoint uses membership integrations yet: saving stores the settings, but your users cannot sign in with Apple Sign In through the API until it ships.
{% endhint %}

## Test and set as default

Membership integrations have no **Test** and no **Set as default** in Cloud — see [Test an integration](/codemash/cloud/membership/integrations/test.md) and [Set an integration as default](/codemash/cloud/membership/integrations/set-default.md). Check the values against the provider's console; **Actions → Disable** turns the integration off — see [Disable or delete an integration](/codemash/cloud/membership/integrations/disable.md).

## Common errors

| Message                                          | Cause                                                           | Fix                                                                                        |
| ------------------------------------------------ | --------------------------------------------------------------- | ------------------------------------------------------------------------------------------ |
| *Required* under a field                         | A required field is empty.                                      | Fill it; on a saved integration, type the secret again.                                    |
| Secret is not provided (`CM-ERRORS-SECRETS-001`) | Saved from code without the secret.                             | Send the secret on every save.                                                             |
| *invalid\_client* (at Apple)                     | Services Id, Key Id, Team Id or the key do not belong together. | Check the four values in Certificates, Identifiers & Profiles; paste the `.p8` text again. |

Messages marked *(at …)* are the provider's own, shown to the user while signing in; see the [provider documentation](https://developer.apple.com/help/account/configure-app-capabilities/configure-sign-in-with-apple-for-the-web).

## Do it from code

```sh
norbix hub membership integration save --integration '{"provider":"AppleSignIn","integrationName":"Sign in with Apple (staging)","isEnabled":true,"teamId":"ABCDE12345","appBundleId":"com.acme.app","serviceId":"com.acme.app.signin","keyId":"KEY1234567","privateKey":"your-p8-key-text","isProduction":false}'
```

With the SDK, send the same object as `integration` to `saveMembershipIntegration` — see the run example on [Providers](/codemash/cloud/membership/integrations/providers.md#do-it-from-code) and in [Save Membership Integration](/codemash/sdks/membership/integrations/save-membership-integration.md). Send `isEnabled: true`; to update, add the id as `integrationId` and the secret again. API: [Save Membership Integration](/codemash/api-reference/membership/integrations/save-membership-integration.md)
