## What the membership gets you

The same membership covers Sign in with Apple and App Store distribution, so if you are shipping an
iOS app you are paying for it regardless and this is free at the margin. If you are web only, it is a
standing annual cost for one sign-in button.

## Apple's credentials are shaped differently

Google gives you a client id and a client secret, both strings that do not expire. Apple gives you a
Services ID, a Team ID, a Key ID and a `.p8` private key file, and the client secret your app sends
is a JWT you generate and sign from those. That JWT has a maximum lifetime of six months.

So Apple has an expiry on a schedule, and Google does not. Worth a calendar entry, because the
failure is a sign-in button that worked for months and then stops.

## Both are optional

```bash
bin/dev
```

Magic-code sign-in works with no provider configured at all, and it is the primary path. Google and
Apple are additions, and an app with neither is fully functional. Everything routes through
`User.upsert_by_email!` in `app/models/user.rb` regardless, so adding a provider later does not create a second signup path
or a duplicate account for someone who already signed in by email.

## The App Store rule, if you ship mobile

If your iOS app offers any third-party social sign-in, Apple's review guidelines require Sign in with
Apple alongside it. That turns the 99 dollars from optional into required, and it is the most common
way the cost arrives unplanned. See
[Auth in the App](/docs/mobile-apps/auth-in-the-app) for how the native shells handle it.

## If you add it

Apple's callback is a cross-site `form_post`, which is why `config/routes.rb` declares both a GET and
a POST for the OAuth callback. The POST one exists for Apple specifically, and removing it as
apparent duplication breaks only Apple, and only in production.
