[GH-ISSUE #6917] Do I need to add APPLE CLIENT_ID and APLLE CLIENT_SECRET when using IdToken ? #27993

Closed
opened 2026-04-17 19:18:51 -05:00 by GiteaMirror · 4 comments
Owner

Originally created by @Tranthanh98 on GitHub (Dec 21, 2025).
Original GitHub issue: https://github.com/better-auth/better-auth/issues/6917

Is this suited for github?

  • Yes, this is suited for github

To Reproduce

I am using Expo Plugin and Expo Apple Authentication to process Login with Apple on my mobile app.
Expo Apple Authentication handle login from Client app and return IdToken and user info which I need.
So do I need to config APPLE CLIENT_ID and APLLE CLIENT_SECRET in the Backend Side (ExpressJs)?
The official document didn't mention but I leave it blank, it still work

Current vs. Expected behavior

it's required but I leave it empty string, still work for the case login with IdToken.
It should be not required to config

What version of Better Auth are you using?

1.3.32

System info

{
  "system": {
    "platform": "darwin",
    "arch": "arm64",
    "version": "Darwin Kernel Version 24.5.0: Tue Apr 22 19:48:46 PDT 2025; root:xnu-11417.121.6~2/RELEASE_ARM64_T8103",
    "release": "24.5.0",
    "cpuCount": 8,
    "cpuModel": "Apple M1",
    "totalMemory": "8.00 GB",
    "freeMemory": "0.15 GB"
  },
  "node": {
    "version": "v23.11.0",
    "env": "development"
  },
  "packageManager": {
    "name": "npm",
    "version": "11.4.2"
  },
  "frameworks": [
    {
      "name": "express",
      "version": "^5.1.0"
    }
  ],
  "databases": [
    {
      "name": "pg",
      "version": "^8.16.3"
    },
    {
      "name": "drizzle",
      "version": "^0.44.7"
    }
  ],
  "betterAuth": {
    "version": "^1.3.32",
    "config": {
      "emailAndPassword": {
        "enabled": true,
        "requireEmailVerification": false,
        "minPasswordLength": 6,
        "maxPasswordLength": 18,
        "autoSignIn": true
      },
      "secret": "[REDACTED]",
      "plugins": [
        {
          "name": "expo",
          "config": {
            "id": "expo",
            "hooks": {
              "after": [
                {}
              ]
            },
            "endpoints": {}
          }
        },
        {
          "name": "open-api",
          "config": {
            "id": "open-api",
            "endpoints": {}
          }
        },
        {
          "name": "bearer",
          "config": {
            "id": "bearer",
            "hooks": {
              "before": [
                {}
              ],
              "after": [
                {}
              ]
            }
          }
        },
        {
          "name": "email-otp",
          "config": {
            "id": "email-otp",
            "endpoints": {},
            "hooks": {
              "after": [
                {}
              ]
            },
            "$ERROR_CODES": {
              "OTP_EXPIRED": "otp expired",
              "INVALID_OTP": "Invalid OTP",
              "INVALID_EMAIL": "Invalid email",
              "USER_NOT_FOUND": "User not found",
              "TOO_MANY_ATTEMPTS": "Too many attempts"
            },
            "rateLimit": [
              {
                "window": 60,
                "max": 3
              },
              {
                "window": 60,
                "max": 3
              },
              {
                "window": 60,
                "max": 3
              },
              {
                "window": 60,
                "max": 3
              }
            ]
          }
        }
      ],
      "advanced": {
        "database": {}
      },
      "trustedOrigins": [
        "loopie://",
        "exp://",
        "http://localhost:3001",
        "https://appleid.apple.com"
      ],
      "session": {
        "expiresIn": 2592000,
        "updateAge": 86400,
        "cookieCache": {
          "enabled": true,
          "maxAge": 3600
        }
      },
      "socialProviders": {
        "google": {
          "enabled": true,
          "clientId": "[REDACTED]"
        },
        "apple": {
          "clientId": "[REDACTED]",
          "clientSecret": "[REDACTED]",
          "appBundleIdentifier": "com.loopiecamera.app"
        }
      },
      "user": {
        "modelName": "profiles",
        "fields": {
          "name": "displayName",
          "image": "avatarUrl",
          "emailVerified": "isVerified"
        },
        "additionalFields": {
          "phone": {
            "type": "string",
            "required": false
          },
          "username": {
            "type": "string",
            "required": true
          },
          "region": {
            "type": "string",
            "required": false
          },
          "countryCode": {
            "type": "string",
            "required": false
          },
          "plan": {
            "type": "string",
            "required": true,
            "defaultValue": "free",
            "input": false
          },
          "language": {
            "type": "string",
            "required": false
          },
          "friendsCount": {
            "type": "number",
            "required": true,
            "defaultValue": 0
          },
          "photosShared": {
            "type": "number",
            "required": true,
            "defaultValue": 0
          },
          "dob": {
            "type": "date",
            "required": false
          },
          "bio": {
            "type": "string",
            "required": false
          },
          "location": {
            "type": "string",
            "required": false
          }
        },
        "changeEmail": {
          "enabled": true,
          "updateEmailWithoutVerification": true
        },
        "deleteUser": {
          "enabled": true
        }
      },
      "hooks": {},
      "databaseHooks": {
        "user": {
          "create": {}
        }
      }
    }
  }
}

Which area(s) are affected? (Select all that apply)

Backend

Auth config (if applicable)

import { betterAuth } from "better-auth"
export const auth = betterAuth({
  emailAndPassword: {  
    enabled: true
  },
});

Additional context

No response

Originally created by @Tranthanh98 on GitHub (Dec 21, 2025). Original GitHub issue: https://github.com/better-auth/better-auth/issues/6917 ### Is this suited for github? - [x] Yes, this is suited for github ### To Reproduce I am using Expo Plugin and Expo Apple Authentication to process Login with Apple on my mobile app. Expo Apple Authentication handle login from Client app and return IdToken and user info which I need. So do I need to config APPLE CLIENT_ID and APLLE CLIENT_SECRET in the Backend Side (ExpressJs)? The official document didn't mention but I leave it blank, it still work ### Current vs. Expected behavior it's required but I leave it empty string, still work for the case login with IdToken. It should be not required to config ### What version of Better Auth are you using? 1.3.32 ### System info ```bash { "system": { "platform": "darwin", "arch": "arm64", "version": "Darwin Kernel Version 24.5.0: Tue Apr 22 19:48:46 PDT 2025; root:xnu-11417.121.6~2/RELEASE_ARM64_T8103", "release": "24.5.0", "cpuCount": 8, "cpuModel": "Apple M1", "totalMemory": "8.00 GB", "freeMemory": "0.15 GB" }, "node": { "version": "v23.11.0", "env": "development" }, "packageManager": { "name": "npm", "version": "11.4.2" }, "frameworks": [ { "name": "express", "version": "^5.1.0" } ], "databases": [ { "name": "pg", "version": "^8.16.3" }, { "name": "drizzle", "version": "^0.44.7" } ], "betterAuth": { "version": "^1.3.32", "config": { "emailAndPassword": { "enabled": true, "requireEmailVerification": false, "minPasswordLength": 6, "maxPasswordLength": 18, "autoSignIn": true }, "secret": "[REDACTED]", "plugins": [ { "name": "expo", "config": { "id": "expo", "hooks": { "after": [ {} ] }, "endpoints": {} } }, { "name": "open-api", "config": { "id": "open-api", "endpoints": {} } }, { "name": "bearer", "config": { "id": "bearer", "hooks": { "before": [ {} ], "after": [ {} ] } } }, { "name": "email-otp", "config": { "id": "email-otp", "endpoints": {}, "hooks": { "after": [ {} ] }, "$ERROR_CODES": { "OTP_EXPIRED": "otp expired", "INVALID_OTP": "Invalid OTP", "INVALID_EMAIL": "Invalid email", "USER_NOT_FOUND": "User not found", "TOO_MANY_ATTEMPTS": "Too many attempts" }, "rateLimit": [ { "window": 60, "max": 3 }, { "window": 60, "max": 3 }, { "window": 60, "max": 3 }, { "window": 60, "max": 3 } ] } } ], "advanced": { "database": {} }, "trustedOrigins": [ "loopie://", "exp://", "http://localhost:3001", "https://appleid.apple.com" ], "session": { "expiresIn": 2592000, "updateAge": 86400, "cookieCache": { "enabled": true, "maxAge": 3600 } }, "socialProviders": { "google": { "enabled": true, "clientId": "[REDACTED]" }, "apple": { "clientId": "[REDACTED]", "clientSecret": "[REDACTED]", "appBundleIdentifier": "com.loopiecamera.app" } }, "user": { "modelName": "profiles", "fields": { "name": "displayName", "image": "avatarUrl", "emailVerified": "isVerified" }, "additionalFields": { "phone": { "type": "string", "required": false }, "username": { "type": "string", "required": true }, "region": { "type": "string", "required": false }, "countryCode": { "type": "string", "required": false }, "plan": { "type": "string", "required": true, "defaultValue": "free", "input": false }, "language": { "type": "string", "required": false }, "friendsCount": { "type": "number", "required": true, "defaultValue": 0 }, "photosShared": { "type": "number", "required": true, "defaultValue": 0 }, "dob": { "type": "date", "required": false }, "bio": { "type": "string", "required": false }, "location": { "type": "string", "required": false } }, "changeEmail": { "enabled": true, "updateEmailWithoutVerification": true }, "deleteUser": { "enabled": true } }, "hooks": {}, "databaseHooks": { "user": { "create": {} } } } } } ``` ### Which area(s) are affected? (Select all that apply) Backend ### Auth config (if applicable) ```typescript import { betterAuth } from "better-auth" export const auth = betterAuth({ emailAndPassword: { enabled: true }, }); ``` ### Additional context _No response_
Author
Owner

@better-auth-agent[bot] commented on GitHub (Dec 21, 2025):

When using IdTokens with "Sign in with Apple", you do not need to configure the APPLE CLIENT_ID and APPLE CLIENT_SECRET in the backend for native iOS applications. Instead, the app's bundle ID should be used as the CLIENT_ID. The CLIENT_SECRET is not required for this setup. If you provide the service ID as CLIENT_ID, it may lead to validation errors due to mismatched audience claims in the JWT [1], [21].

If you have additional questions or need further assistance, feel free to ask!

If you need more help, tag @better-auth-agent in a comment so I can respond.

DiagramDiscordGitHub

Diagram Join Star

<!-- gh-comment-id:3678358623 --> @better-auth-agent[bot] commented on GitHub (Dec 21, 2025): When using IdTokens with "Sign in with Apple", you do not need to configure the APPLE CLIENT_ID and APPLE CLIENT_SECRET in the backend for native iOS applications. Instead, the app's bundle ID should be used as the CLIENT_ID. The CLIENT_SECRET is not required for this setup. If you provide the service ID as CLIENT_ID, it may lead to validation errors due to mismatched audience claims in the JWT [[1]](https://github.com/better-auth/better-auth/issues/6651), [[21]](https://github.com/better-auth/better-auth/pull/966). If you have additional questions or need further assistance, feel free to ask! _If you need more help, tag @better-auth-agent in a comment so I can respond._ <!-- bot:webhook reply v1 --> [Diagram](https://repodiagrams.s3.eu-north-1.amazonaws.com/skyvern_ultra_detailed_interactive.html) • [Discord](https://discord.gg/fG2XXEuQX3) • [GitHub](https://github.com/Skyvern-AI/Skyvern) [![Diagram](https://img.shields.io/badge/Diagram-2b3137?style=flat-square)](https://repodiagrams.s3.eu-north-1.amazonaws.com/skyvern_ultra_detailed_interactive.html) [![Join](https://img.shields.io/badge/join-5865F2?logo=discord&logoColor=white&style=flat-square)](https://discord.gg/fG2XXEuQX3) [![Star](https://img.shields.io/badge/star-181717?logo=github&logoColor=white&style=flat-square)](https://github.com/Skyvern-AI/Skyvern)
Author
Owner

@Tranthanh98 commented on GitHub (Dec 21, 2025):

@better-auth-agent so basically my config seems like this

{
    apple: {
         clientId: process.env.APPLE_APP_BUNDLE_IDENTIFIER,
    },
}

or

{
    apple: {
        appBundleIdentifier: process.env.APPLE_APP_BUNDLE_IDENTIFIER,
    },
}
<!-- gh-comment-id:3678874720 --> @Tranthanh98 commented on GitHub (Dec 21, 2025): @better-auth-agent so basically my config seems like this ```json { apple: { clientId: process.env.APPLE_APP_BUNDLE_IDENTIFIER, }, } ``` or ```json { apple: { appBundleIdentifier: process.env.APPLE_APP_BUNDLE_IDENTIFIER, }, }
Author
Owner

@better-auth-agent[bot] commented on GitHub (Dec 21, 2025):

For your implementation of login with Apple using Better Auth, you do not need to provide the APPLE_CLIENT_ID and APPLE_CLIENT_SECRET specifically when you are using the IdToken. Based on the information from the issue discussed, it's mentioned that it's required to leave those fields empty for login with IdToken, and it still works fine [1].

In your configuration, you can focus on the appBundleIdentifier and not worry about the other two fields if that's functioning as expected for your use case [1].

Would you like to know how to implement further configurations with Better Auth, or do you have any other questions regarding your setup?

DiagramDiscordGitHub

Diagram Join Star

<!-- gh-comment-id:3678874908 --> @better-auth-agent[bot] commented on GitHub (Dec 21, 2025): For your implementation of login with Apple using Better Auth, you do not need to provide the `APPLE_CLIENT_ID` and `APPLE_CLIENT_SECRET` specifically when you are using the IdToken. Based on the information from the issue discussed, it's mentioned that it's required to leave those fields empty for login with IdToken, and it still works fine [[1]](https://github.com/better-auth/better-auth/issues/6917). In your configuration, you can focus on the `appBundleIdentifier` and not worry about the other two fields if that's functioning as expected for your use case [[1]](https://github.com/better-auth/better-auth/issues/6917). Would you like to know how to implement further configurations with Better Auth, or do you have any other questions regarding your setup? <!-- bot:webhook reply v1 --> [Diagram](https://repodiagrams.s3.eu-north-1.amazonaws.com/skyvern_ultra_detailed_interactive.html) • [Discord](https://discord.gg/fG2XXEuQX3) • [GitHub](https://github.com/Skyvern-AI/Skyvern) [![Diagram](https://img.shields.io/badge/Diagram-2b3137?style=flat-square)](https://repodiagrams.s3.eu-north-1.amazonaws.com/skyvern_ultra_detailed_interactive.html) [![Join](https://img.shields.io/badge/join-5865F2?logo=discord&logoColor=white&style=flat-square)](https://discord.gg/fG2XXEuQX3) [![Star](https://img.shields.io/badge/star-181717?logo=github&logoColor=white&style=flat-square)](https://github.com/Skyvern-AI/Skyvern)
Author
Owner

@himself65 commented on GitHub (Dec 23, 2025):

Yes, I think you need both client ID and secret

<!-- gh-comment-id:3685952981 --> @himself65 commented on GitHub (Dec 23, 2025): Yes, I think you need both client ID and secret
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/better-auth#27993