[GH-ISSUE #2900] Require a function for creating the Apple JWT #9385

Closed
opened 2026-04-13 04:49:41 -05:00 by GiteaMirror · 4 comments
Owner

Originally created by @vedantroy on GitHub (Jun 4, 2025).
Original GitHub issue: https://github.com/better-auth/better-auth/issues/2900

Is this suited for github?

  • Yes, this is suited for github

For Apple OAuth, we need to create a JWT and pass it in as the clientSecret:

// For Apple OAuth, we need to create a JWT and pass it in as the `clientSecret`:
const appleClientSecret = appleSignin.getClientSecret({
  clientID: serviceIdentifier, // OAuth terminology is clientID, but in apple it's serviceIdentifier
  teamID: teamIdentifier,
  // Must be the p8 file of the key associated with the keyIdentifier
  // To download the p8 file (you can only do this once), go to the key's page, click "Download" *and* make sure your key's name is in CamelCase
  // Otherwise your browser will say the key was already downloaded
  privateKey: fs.readFileSync(
    path.join(__dirname, "apple_creds/AuthKey.p8"),
    "utf8",
  ),
  keyIdentifier: keyIdentifier,
  // TODO: Do we need to manually refresh out server?
  expAfter: Math.floor(addMonths(new Date(), 5).getTime() / 1000), // now + 5 months (Apple maximum is 6 months)
});

const auth = betterAuth({
  plugins: [admin(), expo()],
  socialProviders: {
    apple: {
      clientId: serviceIdentifier,
      clientSecret: appleClientSecret,
      // Optional?
      // "On native iOS, it doesn't use the service ID but the app ID (bundle ID) as client ID"
      appBundleIdentifier: APPLE_BUNDLE_ID,
    },
  },
  trustedOrigins,
  user: {},
});

export default auth;

Unfortunately, the JWT has a maximum lifetime, which means we would need to recreate our better auth instance once every few months in order for the JWT to stay up to date.

Describe the solution you'd like

For Apple, support either a function that returns the clientSecret or have an apple-specific configuration object:

const auth = betterAuth({
  plugins: [admin(), expo()],
  socialProviders: {
    apple: {
      clientId: serviceIdentifier,
      // Option 1: Function that returns the client secret
      clientSecret: () => {
        return appleSignin.getClientSecret({
          clientID: serviceIdentifier,
          teamID: teamIdentifier,
          privateKey: fs.readFileSync(
            path.join(__dirname, "apple_creds/AuthKey.p8"),
            "utf8",
          ),
          keyIdentifier: keyIdentifier,
          expAfter: Math.floor(addMonths(new Date(), 5).getTime() / 1000),
        });
      },
      
      // Option 2: Apple-specific config object (library handles JWT creation internally)
      appleConfig: {
        teamID: teamIdentifier,
        keyIdentifier: keyIdentifier,
        privateKeyPath: path.join(__dirname, "apple_creds/AuthKey.p8"),
        // or privateKey: fs.readFileSync(...), 
        jwtExpiration: '5m', // 5 months, library validates against Apple's 6-month max
      },
      
      appBundleIdentifier: APPLE_BUNDLE_ID,
    },
  },
  trustedOrigins,
  user: {},
});

Describe alternatives you've considered

  • Restart the server once every few months
  • Cache the better auth instance, check when the JWT is invalidated, and then re-create it (clunky)

Additional context

No response

Originally created by @vedantroy on GitHub (Jun 4, 2025). Original GitHub issue: https://github.com/better-auth/better-auth/issues/2900 ### Is this suited for github? - [x] Yes, this is suited for github ### Is your feature request related to a problem? Please describe. For Apple OAuth, we need to create a JWT and pass it in as the `clientSecret`: ``` // For Apple OAuth, we need to create a JWT and pass it in as the `clientSecret`: const appleClientSecret = appleSignin.getClientSecret({ clientID: serviceIdentifier, // OAuth terminology is clientID, but in apple it's serviceIdentifier teamID: teamIdentifier, // Must be the p8 file of the key associated with the keyIdentifier // To download the p8 file (you can only do this once), go to the key's page, click "Download" *and* make sure your key's name is in CamelCase // Otherwise your browser will say the key was already downloaded privateKey: fs.readFileSync( path.join(__dirname, "apple_creds/AuthKey.p8"), "utf8", ), keyIdentifier: keyIdentifier, // TODO: Do we need to manually refresh out server? expAfter: Math.floor(addMonths(new Date(), 5).getTime() / 1000), // now + 5 months (Apple maximum is 6 months) }); const auth = betterAuth({ plugins: [admin(), expo()], socialProviders: { apple: { clientId: serviceIdentifier, clientSecret: appleClientSecret, // Optional? // "On native iOS, it doesn't use the service ID but the app ID (bundle ID) as client ID" appBundleIdentifier: APPLE_BUNDLE_ID, }, }, trustedOrigins, user: {}, }); export default auth; ``` Unfortunately, the JWT has a maximum lifetime, which means we would need to recreate our better auth instance once every few months in order for the JWT to stay up to date. ### Describe the solution you'd like For Apple, support either a function that returns the `clientSecret` or have an apple-specific configuration object: ``` const auth = betterAuth({ plugins: [admin(), expo()], socialProviders: { apple: { clientId: serviceIdentifier, // Option 1: Function that returns the client secret clientSecret: () => { return appleSignin.getClientSecret({ clientID: serviceIdentifier, teamID: teamIdentifier, privateKey: fs.readFileSync( path.join(__dirname, "apple_creds/AuthKey.p8"), "utf8", ), keyIdentifier: keyIdentifier, expAfter: Math.floor(addMonths(new Date(), 5).getTime() / 1000), }); }, // Option 2: Apple-specific config object (library handles JWT creation internally) appleConfig: { teamID: teamIdentifier, keyIdentifier: keyIdentifier, privateKeyPath: path.join(__dirname, "apple_creds/AuthKey.p8"), // or privateKey: fs.readFileSync(...), jwtExpiration: '5m', // 5 months, library validates against Apple's 6-month max }, appBundleIdentifier: APPLE_BUNDLE_ID, }, }, trustedOrigins, user: {}, }); ``` ### Describe alternatives you've considered - Restart the server once every few months - Cache the better auth instance, check when the JWT is invalidated, and then re-create it (clunky) ### Additional context _No response_
GiteaMirror added the locked label 2026-04-13 04:49:41 -05:00
Author
Owner

@noah-haub commented on GitHub (Jun 29, 2025):

Would desperately need this as well. This is a big con for me, and makes better-auth pretty much not an option in production.

<!-- gh-comment-id:3016390100 --> @noah-haub commented on GitHub (Jun 29, 2025): Would desperately need this as well. This is a big con for me, and makes better-auth pretty much not an option in production.
Author
Owner

@dosubot[bot] commented on GitHub (Sep 28, 2025):

Hi, @vedantroy. I'm Dosu, and I'm helping the better-auth team manage their backlog and am marking this issue as stale.

Issue Summary

  • You requested a feature to support Apple OAuth JWT creation by allowing the clientSecret to be provided as a function or through an Apple-specific config.
  • This would enable automatic JWT regeneration before expiration, addressing Apple's JWT lifetime limitation.
  • Another contributor, noah-haub, also highlighted that this limitation impacts betterAuth's practicality for production use.
  • The issue remains unresolved with no implemented solution yet.

Next Steps

  • Please let me know if this issue is still relevant to the latest version of better-auth by commenting here.
  • If I do not hear back within 7 days, this issue will be automatically closed.

Thank you for your understanding and contribution!

<!-- gh-comment-id:3343831077 --> @dosubot[bot] commented on GitHub (Sep 28, 2025): Hi, @vedantroy. I'm [Dosu](https://dosu.dev), and I'm helping the better-auth team manage their backlog and am marking this issue as stale. **Issue Summary** - You requested a feature to support Apple OAuth JWT creation by allowing the clientSecret to be provided as a function or through an Apple-specific config. - This would enable automatic JWT regeneration before expiration, addressing Apple's JWT lifetime limitation. - Another contributor, noah-haub, also highlighted that this limitation impacts betterAuth's practicality for production use. - The issue remains unresolved with no implemented solution yet. **Next Steps** - Please let me know if this issue is still relevant to the latest version of better-auth by commenting here. - If I do not hear back within 7 days, this issue will be automatically closed. Thank you for your understanding and contribution!
Author
Owner

@vedantroy commented on GitHub (Sep 28, 2025):

Yes

On Sun, Sep 28, 2025, 12:03 PM dosubot[bot] @.***>
wrote:

dosubot[bot] left a comment (better-auth/better-auth#2900)
https://github.com/better-auth/better-auth/issues/2900#issuecomment-3343831077

Hi, @vedantroy https://github.com/vedantroy. I'm Dosu https://dosu.dev,
and I'm helping the better-auth team manage their backlog and am marking
this issue as stale.

Issue Summary

  • You requested a feature to support Apple OAuth JWT creation by
    allowing the clientSecret to be provided as a function or through an
    Apple-specific config.
  • This would enable automatic JWT regeneration before expiration,
    addressing Apple's JWT lifetime limitation.
  • Another contributor, noah-haub, also highlighted that this
    limitation impacts betterAuth's practicality for production use.
  • The issue remains unresolved with no implemented solution yet.

Next Steps

  • Please let me know if this issue is still relevant to the latest
    version of better-auth by commenting here.
  • If I do not hear back within 7 days, this issue will be
    automatically closed.

Thank you for your understanding and contribution!


Reply to this email directly, view it on GitHub
https://github.com/better-auth/better-auth/issues/2900#issuecomment-3343831077,
or unsubscribe
https://github.com/notifications/unsubscribe-auth/ACAEWC7AZGBL2OS5YT3BCY33VABDTAVCNFSM6AAAAAB6RX6WXCVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZTGNBTHAZTCMBXG4
.
You are receiving this because you were mentioned.Message ID:
@.***>

<!-- gh-comment-id:3343905609 --> @vedantroy commented on GitHub (Sep 28, 2025): Yes On Sun, Sep 28, 2025, 12:03 PM dosubot[bot] ***@***.***> wrote: > *dosubot[bot]* left a comment (better-auth/better-auth#2900) > <https://github.com/better-auth/better-auth/issues/2900#issuecomment-3343831077> > > Hi, @vedantroy <https://github.com/vedantroy>. I'm Dosu <https://dosu.dev>, > and I'm helping the better-auth team manage their backlog and am marking > this issue as stale. > > *Issue Summary* > > - You requested a feature to support Apple OAuth JWT creation by > allowing the clientSecret to be provided as a function or through an > Apple-specific config. > - This would enable automatic JWT regeneration before expiration, > addressing Apple's JWT lifetime limitation. > - Another contributor, noah-haub, also highlighted that this > limitation impacts betterAuth's practicality for production use. > - The issue remains unresolved with no implemented solution yet. > > *Next Steps* > > - Please let me know if this issue is still relevant to the latest > version of better-auth by commenting here. > - If I do not hear back within 7 days, this issue will be > automatically closed. > > Thank you for your understanding and contribution! > > — > Reply to this email directly, view it on GitHub > <https://github.com/better-auth/better-auth/issues/2900#issuecomment-3343831077>, > or unsubscribe > <https://github.com/notifications/unsubscribe-auth/ACAEWC7AZGBL2OS5YT3BCY33VABDTAVCNFSM6AAAAAB6RX6WXCVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZTGNBTHAZTCMBXG4> > . > You are receiving this because you were mentioned.Message ID: > ***@***.***> >
Author
Owner

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

We don't want to do this, since it's only for apple provider but we will introduce many breaking changes

<!-- gh-comment-id:3690174048 --> @himself65 commented on GitHub (Dec 24, 2025): We don't want to do this, since it's only for apple provider but we will introduce many breaking changes
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/better-auth#9385