|
1 | 1 | import { PayloadRequest } from "payload";
|
2 | 2 | import { OAuth2Plugin } from "../src/index";
|
| 3 | +/** |
| 4 | +To setup Apple OAuth, refer to official documentation: |
| 5 | +https://developer.apple.com/sign-in-with-apple/get-started/ |
| 6 | +
|
| 7 | +However, the process is quite complex and requires several steps, so here's a quick start guide: |
| 8 | +
|
| 9 | +To setup Apple OAuth in Payload CMS, you need the following 4 values: |
| 10 | +1. APPLE_CLIENT_ID: Your Service ID from the Apple Developer portal (e.g. com.example.myapp) |
| 11 | +2. APPLE_CLIENT_SECRET: Your client secret, which is a JWT signed with your private key. This requires value 3 and 4 to generate: |
| 12 | +3. APPLE_KEY_ID: The Key ID from the Apple Developer portal |
| 13 | +4. APPLE_TEAM_ID: Your Apple Developer Team ID, which can be found in the Apple Developer portal. |
| 14 | +
|
| 15 | +Prerequisites: Have a valid Apple Developer account and access to the Apple Developer portal. |
| 16 | +
|
| 17 | +1. Create an App ID in the Apple Developer portal |
| 18 | + - Quick links: https://developer.apple.com/account/resources/identifiers/bundleId/add/bundle |
| 19 | + - Step by step instruction: |
| 20 | + > https://developer.apple.com/account |
| 21 | + > Certificates, IDs & Profiles |
| 22 | + > Identifiers |
| 23 | + > Create new identifiders |
| 24 | + > Select App IDs |
| 25 | + > Select App |
| 26 | + > Arbitrary description, explicit bundle ID (e.g. com.example.myapp) |
| 27 | + > Capabilities: Enable Sign In with Apple > Save (ignore Server-to-Server Notification Endpoint) |
| 28 | + > Continue/Register |
| 29 | +2. Create a service ID in the Apple Developer portal |
| 30 | + - Quick links: https://developer.apple.com/account/resources/identifiers/serviceId/add |
| 31 | + - Step by step instruction: |
| 32 | + > https://developer.apple.com/account |
| 33 | + > Certificates, IDs & Profiles |
| 34 | + > Identifiers |
| 35 | + > Create new identifiders |
| 36 | + > Select Service IDs |
| 37 | + > Arbitrary description, identifier (e.g. com.example.myapp.si) - IMPORTANT, I have found that this must be a subdomain of your app's bundle ID, notice the ".si" suffix. |
| 38 | + > Continue/Register |
| 39 | + > Value (1) APPLE_CLIENT_ID should be the identifier you just created (e.g. com.example.myapp.si) |
| 40 | +3. Create a new key in the Apple Developer portal |
| 41 | + - Quick links: https://developer.apple.com/account/resources/authkeys/add |
| 42 | + - Step by step instruction: |
| 43 | + > https://developer.apple.com/account |
| 44 | + > Certificates, IDs & Profiles |
| 45 | + > Keys |
| 46 | + > Create new key |
| 47 | + > Arbitrary key name and key usage description. |
| 48 | + > Enable Sign In with Apple |
| 49 | + > Configure |
| 50 | + > Select the App ID you created in step 1 |
| 51 | + > Continue/Register |
| 52 | + > Download the key file, which is a .p8 file. This file contains your private key. |
| 53 | + > Value (3) APPLE_KEY_ID is the Key ID from the key you just created. |
| 54 | +4. Obtain your Apple Developer Team ID |
| 55 | + > https://developer.apple.com/account |
| 56 | + > Membership details |
| 57 | + > Your Team ID is listed there, this should be value (4) APPLE_TEAM_ID. |
| 58 | +5. Based on value (3) APPLE_KEY_ID, value (4) APPLE_TEAM_ID and the private key file you downloaded in step 3, generate value (2) APPLE_CLIENT_SECRET by running: |
| 59 | +```sh |
| 60 | +pnpm payload-oauth2:generate-apple-client-secret --team-id 4659F6UUC3 --client-id com.example.app.sso --key-id XXXXXXXXXX --private-key-path AuthKey_XXXXXXXXXX.p8 |
| 61 | +``` |
| 62 | +
|
| 63 | +In the example below: |
| 64 | +- `process.env.APPLE_CLIENT_ID` is (1) APPLE_CLIENT_ID |
| 65 | +- `process.env.APPLE_CLIENT_SECRET` is (2) APPLE_CLIENT_SECRET, |
| 66 | +
|
| 67 | +Dev Note: |
| 68 | +- I consistently got an `invalid_client` error when redirecting to `https://appleid.apple.com/auth/authorize`. I noticed that newly generated keys took 2 days for it to go into effect. After waiting for 2 days, the error went away. |
| 69 | +- For web, I noticed that service id works if it is a subdomain of the app's bundle id. For example, if your app's bundle id is `com.example.myapp`, then your service id must be something like `com.example.myapp.sso`. I tried to use a service id that is not a subdomain of the app's bundle id, I got an `invalid_client` error when redirecting to `https://appleid.apple.com/auth/authorize`. |
| 70 | + */ |
3 | 71 |
|
4 | 72 | ////////////////////////////////////////////////////////////////////////////////
|
5 | 73 | // Apple OAuth
|
6 | 74 | ////////////////////////////////////////////////////////////////////////////////
|
| 75 | + |
7 | 76 | export const appleOAuth = OAuth2Plugin({
|
8 | 77 | enabled:
|
9 | 78 | typeof process.env.APPLE_CLIENT_ID === "string" &&
|
10 |
| - typeof process.env.APPLE_CLIENT_SECRET === "string", |
| 79 | + typeof process.env.APPLE_TEAM_ID === "string" && |
| 80 | + typeof process.env.APPLE_KEY_ID === "string" && |
| 81 | + (typeof process.env.APPLE_CLIENT_SECRET === "string" || |
| 82 | + typeof process.env.APPLE_CLIENT_AUTH_KEY_CONTENT === "string"), |
11 | 83 | strategyName: "apple",
|
12 | 84 | useEmailAsIdentity: true,
|
13 | 85 | serverURL: process.env.NEXT_PUBLIC_URL || "http://localhost:3000",
|
@@ -86,17 +158,10 @@ export const appleOAuth = OAuth2Plugin({
|
86 | 158 | }
|
87 | 159 | },
|
88 | 160 | successRedirect: (req: PayloadRequest, token?: string) => {
|
89 |
| - // Check user roles to determine redirect |
90 |
| - const user = req.user; |
91 |
| - if (user && Array.isArray(user.roles)) { |
92 |
| - if (user.roles.includes("admin")) { |
93 |
| - return "/admin"; |
94 |
| - } |
95 |
| - } |
96 |
| - return "/"; // Default redirect for customers |
| 161 | + return "/admin"; |
97 | 162 | },
|
98 | 163 | failureRedirect: (req, err) => {
|
99 | 164 | req.payload.logger.error(err);
|
100 |
| - return "/login?error=apple-auth-failed"; |
| 165 | + return `/admin/login?error=${JSON.stringify(err)}`; |
101 | 166 | },
|
102 | 167 | });
|
0 commit comments