Apple

Get your OAuth credentials

To use Apple sign in, you need a client ID and client secret. You can get them from the Apple Developer Portal.

You will need an active Apple Developer account to access the developer portal and generate these credentials.

Follow these steps to set up your App ID, Service ID, and generate the key needed for your client secret:

  1. Navigate to Certificates, Identifiers & Profiles: In the Apple Developer Portal, go to the "Certificates, Identifiers & Profiles" section.

  2. Create an App ID:

    • Go to the Identifiers tab.
    • Click the + icon next to Identifiers.
    • Select App IDs, then click Continue.
    • Select App as the type, then click Continue.
    • Description: Enter a name for your app (e.g., "My Awesome App"). This name may be displayed to users when they sign in.
    • Bundle ID: Set a bundle ID. The recommended format is a reverse domain name (e.g., com.yourcompany.yourapp). Using a suffix like .ai (for app identifier) can help with organization but is not required (e.g., com.yourcompany.yourapp.ai).
    • Scroll down to Capabilities. Select the checkbox for Sign In with Apple.
    • Click Continue, then Register.
  3. Create a Service ID:

    • Go back to the Identifiers tab.
    • Click the + icon.
    • Select Service IDs, then click Continue.
    • Description: Enter a description for this service (e.g., your app name again).
    • Identifier: Set a unique identifier for the service. Use a reverse domain format, distinct from your App ID (e.g., com.yourcompany.yourapp.si, where .si indicates service identifier - this is for your organization and not required). This Service ID will be your client_id.
    • Click Continue, then Register.
  4. Configure the Service ID:

    • Find the Service ID you just created in the Identifiers list and click on it.
    • Check the Sign In with Apple capability, then click Configure.
    • Under Primary App ID, select the App ID you created earlier (e.g., com.yourcompany.yourapp.ai).
    • Under Domains and Subdomains, list all the root domains you will use for Sign In with Apple (e.g., example.com, anotherdomain.com).
    • Under Return URLs, enter the callback URL. https://yourdomain.com/api/auth/callback/apple. Add all necessary return URLs.
    • Click Next, then Done.
    • Click Continue, then Save.
  5. Create a Client Secret Key:

    • Go to the Keys tab.
    • Click the + icon to create a new key.
    • Key Name: Enter a name for the key (e.g., "Sign In with Apple Key").
    • Scroll down and select the checkbox for Sign In with Apple.
    • Click the Configure button next to Sign In with Apple.
    • Select the Primary App ID you created earlier.
    • Click Save, then Continue, then Register.
    • Download the Key: Immediately download the .p8 key file. This file is only available for download once. Note the Key ID (available on the Keys page after creation) and your Team ID (available in your Apple Developer Account settings).
  6. Generate the Client Secret (JWT): Apple requires a JSON Web Token (JWT) to be generated dynamically using the downloaded .p8 key, the Key ID, and your Team ID. This JWT serves as your client_secret.

    You can use the guide below from Apple's documentation to understand how to generate this client secret. You can also use our built in generator below to generate the client secret JWT required for 'Sign in with Apple'.

    Note: Apple allows a maximum expiration of 6 months (180 days) for the client secret JWT. You will need to regenerate the client secret before it expires to maintain uninterrupted authentication.

Apple's OAuth implementation requires a JWT (JSON Web Token) as the client_secret instead of a static secret string.

According to Apple's documentation, these JWTs:

  • Have a maximum expiration of 6 months
  • Must be cryptographically signed with your private key

The Ruby port uses the jwt gem and Ruby OpenSSL support to generate the client secret JWT.

Gemfile
# The better_auth gem already depends on jwt for Apple client-secret JWTs.

Configure the provider

To configure the provider, add it to the social_providers option of the auth instance.

You also need to add https://appleid.apple.com to the trusted_origins array in your auth instance configuration to allow communication with Apple's authentication servers.

config/auth.rb
require "better_auth"
require "jwt"
require "openssl"

def generate_apple_client_secret(client_id:, team_id:, key_id:, private_key:)
now = Time.now.to_i
key = OpenSSL::PKey::EC.new(private_key)

JWT.encode(
{
  iss: team_id,
  iat: now,
  exp: now + 180 * 24 * 60 * 60,
  aud: "https://appleid.apple.com",
  sub: client_id
},
key,
"ES256",
{ kid: key_id }
)
end

auth = BetterAuth.auth(
secret: ENV.fetch("BETTER_AUTH_SECRET"),
base_url: ENV.fetch("BETTER_AUTH_URL", "http://localhost:3000"),
social_providers: {
apple: BetterAuth::SocialProviders.apple(
  client_id: ENV.fetch("APPLE_CLIENT_ID"),
  client_secret: generate_apple_client_secret(
    client_id: ENV.fetch("APPLE_CLIENT_ID"),
    team_id: ENV.fetch("APPLE_TEAM_ID"),
    key_id: ENV.fetch("APPLE_KEY_ID"),
    private_key: ENV.fetch("APPLE_PRIVATE_KEY")
  ),
  app_bundle_identifier: ENV["APPLE_APP_BUNDLE_IDENTIFIER"]
)
},
trusted_origins: ["https://appleid.apple.com"]
)

On native iOS, it doesn't use the service ID but the app ID (bundle ID) as client ID, so if using the service ID as client_id in auth.api.sign_in_social with id_token, it throws an error: JWTClaimValidationFailed: unexpected "aud" claim value. So you need to provide the app_bundle_identifier when you want to sign in with Apple using the ID Token.

Apple emits the email claim only on the first authorization; every subsequent sign-in omits it, and Apple provides no user-info endpoint to fetch it later. See Handling Providers Without Email for persistence guidance and the map_profile_to_user fallback.

Localhost and Non-TLS Restrictions

Apple Sign In does not support localhost or non-HTTPS URLs. During development:

  • You cannot use http://localhost as a return URL
  • You must use a domain with valid HTTPS/TLS certificate

This limitation is enforced by Apple's security requirements and cannot be bypassed.

Usage

Sign In with Apple

To sign in with Apple, call auth.api.sign_in_social on your Ruby auth instance. The endpoint body takes the following properties:

  • provider: The provider to use. It should be set to apple.
server.rb
response = auth.api.sign_in_social(
  body: {
    provider: "apple",
    callback_url: "/dashboard",
    error_callback_url: "/login",
    disable_redirect: true
  }
)

redirect_url = response.fetch(:url)

Sign In with Apple With ID Token

To sign in with Apple using the ID Token, you can use the auth.api.sign_in_social function to pass the ID Token.

This is useful when you have the ID Token from Apple on your app and want to use it to sign in on the server.

If ID token is provided no redirection will happen, and the user will be signed in directly.

server.rb
result = auth.api.sign_in_social(
  body: {
    provider: "apple",
    id_token: {
      token: apple_id_token,
      access_token: apple_access_token
    }
  }
)

user = result.fetch(:user)

Generate Apple Client Secret (JWT)

The identifier for the service you created in Apple Developer.

The ID associated with your private key (.p8 file).

Paste the entire content of your .p8 private key file here. Ensure it's in PKCS#8 format.

On this page