To integrate Apple Sign-In in a Next.js app with TypeScript, you need to follow a structured approach involving setting up Apple Sign-In in your Apple Developer account, implementing server-side authentication, and handling the client-side login flow.
Here's a comprehensive guide to add Apple Sign-In to your Next.js TypeScript app:
1.Set Up Apple Sign-In in Apple Developer Account
Create an Apple Developer Account:
1.Go to Apple Developer and log in or create an account.
2.Create an App ID:
Go to Certificates, Identifiers & Profiles.
Navigate to Identifiers and create a new App ID with the Sign in with Apple capability.
- Generate a Service ID:
Create a new Service ID under Identifiers with the Sign in with Apple capability.
Configure the Return URLs with the callback URL you will use in your Next.js app (e.g., https://yourdomain.com/api/auth/apple/callback).
- Create a Key:
Navigate to Keys and create a new key, enabling the Sign in with Apple capability.
Download the generated key file (.p8) as it will be used for JWT signing.
- Configure Apple Sign-In:
Obtain the following credentials:
- Client ID: Your Service ID.
- Team ID: Your Apple Developer Team ID.
- Key ID: The ID of the key you created.
- Private Key: The contents of the .p8 file you downloaded.
2.Server-Side: Implement Authentication in Next.js
- Install Dependencies:
npm install next-auth @auth/core axios jwt-decode
- Create an API Route for Apple Sign-In:
Create a new file pages/api/auth/[...nextauth].ts:
// pages/api/auth/[...nextauth].ts
import NextAuth from 'next-auth';
import AppleProvider from 'next-auth/providers/apple';
export default NextAuth({
providers: [
AppleProvider({
clientId: process.env.APPLE_CLIENT_ID!,
clientSecret: {
appleId: process.env.APPLE_CLIENT_ID!,
teamId: process.env.APPLE_TEAM_ID!,
privateKey: process.env.APPLE_PRIVATE_KEY!,
keyId: process.env.APPLE_KEY_ID!,
privateKeyId: process.env.APPLE_PRIVATE_KEY_ID!,
},
}),
],
secret: process.env.NEXTAUTH_SECRET,
callbacks: {
async jwt({ token, account }) {
if (account) {
token.accessToken = account.access_token;
}
return token;
},
async session({ session, token }) {
session.accessToken = token.accessToken;
return session;
},
},
});
Ensure you have the necessary environment variables set in your .env.local:
APPLE_CLIENT_ID=your_service_id
APPLE_TEAM_ID=your_team_id
APPLE_KEY_ID=your_key_id
APPLE_PRIVATE_KEY=-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----
NEXTAUTH_SECRET=your_next_auth_secret
3.Create JWT Generator for Apple Client Secret:
In your Next.js project, create a helper file lib/apple-jwt.ts:
// lib/apple-jwt.ts
import jwt from 'jsonwebtoken';
export const generateClientSecret = () => {
const payload = {
iss: process.env.APPLE_TEAM_ID,
iat: Math.floor(Date.now() / 1000),
exp: Math.floor(Date.now() / 1000) + 3600, // 1 hour expiration
aud: 'https://appleid.apple.com',
sub: process.env.APPLE_CLIENT_ID,
};
const options = {
algorithm: 'ES256',
header: {
kid: process.env.APPLE_KEY_ID,
typ: 'JWT',
},
};
return jwt.sign(payload, process.env.APPLE_PRIVATE_KEY!, options);
};
4.Ensure the .p8 Private Key is Correctly Formatted:
Make sure your .p8 private key is correctly formatted with newline characters. You might need to replace actual newline characters with \n.
3. Client-Side: Handle Apple Sign-In Button
1.Install the Apple Sign-In Button:
npm install react-apple-signin-auth
2.Implement the Apple Sign-In Button:
Create a component for the Apple Sign-In button:
// components/AppleSignInButton.tsx
import React from 'react';
import AppleSignin from 'react-apple-signin-auth';
import { signIn } from 'next-auth/react';
const AppleSignInButton: React.FC = () => {
return (
<AppleSignin
authOptions={{
clientId: process.env.NEXT_PUBLIC_APPLE_CLIENT_ID!,
scope: 'name email',
redirectURI: `${window.location.origin}/api/auth/callback/apple`,
state: 'state',
nonce: 'nonce',
usePopup: true,
}}
onSuccess={(response) => {
console.log('Apple SignIn Success', response);
}}
onError={(error) => {
console.error('Apple SignIn Error', error);
}}
render={(props) => (
<button onClick={props.onClick} disabled={props.disabled}>
Sign in with Apple
</button>
)}
/>
);
};
export default AppleSignInButton;
3.Use the Apple Sign-In Button in Your App:
In your page or component where you want to include the Apple Sign-In:
// pages/index.tsx
import AppleSignInButton from '../components/AppleSignInButton';
const HomePage: React.FC = () => {
return (
<div>
<h1>Sign in</h1>
<AppleSignInButton />
</div>
);
};
export default HomePage;
- Environment Configuration
Ensure you have these environment variables set up in .env.local:
NEXT_PUBLIC_APPLE_CLIENT_ID=your_service_id
APPLE_TEAM_ID=your_team_id
APPLE_KEY_ID=your_key_id
APPLE_PRIVATE_KEY=-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----
NEXTAUTH_SECRET=your_next_auth_secret
- Testing 1.Run Your App:
npm run dev
2.Navigate to Your Sign-In Page and test the Apple Sign-In flow.
Troubleshooting
Ensure Redirect URI Matches: The redirect URI in your Apple Developer configuration must match the one used in your app.
**Verify JWT: **Make sure the JWT signing configuration is correct, and you have properly formatted your private key.
Console Errors: Check the browser console and network tab for any errors during the sign-in process for more debugging information.
This should set up Apple Sign-In in your Next.js TypeScript app. Make sure to test thoroughly and handle any specific requirements for your application.
Top comments (2)
Great work 👍👍