Remove Apple SSO, keep Google + GitHub only

- Removed Apple from OAuth lib (config, exchange, provider type)
- Removed Apple button from auth page
- Removed Apple tab from setup guide page
- Removed Apple env vars from .env, .env.example, docker-compose.yml
- Removed Apple prompts from setup-sso.sh
This commit is contained in:
root
2026-06-15 14:36:46 +02:00
parent efe8fe36d4
commit b39bce91e4
7 changed files with 13 additions and 221 deletions
+1 -72
View File
@@ -3,7 +3,7 @@ import { prisma } from "@/lib/prisma";
// ─── Provider Config ────────────────────────────────────────────────────────
export type Provider = "google" | "apple" | "github";
export type Provider = "google" | "github";
interface ProviderConfig {
authorizeUrl: string;
@@ -21,13 +21,6 @@ export const PROVIDER_CONFIGS: Record<Provider, ProviderConfig> = {
clientIdEnv: "GOOGLE_CLIENT_ID",
clientSecretEnv: "GOOGLE_CLIENT_SECRET",
},
apple: {
authorizeUrl: "https://appleid.apple.com/auth/authorize",
tokenUrl: "https://appleid.apple.com/auth/token",
scopes: ["name", "email"],
clientIdEnv: "APPLE_CLIENT_ID",
clientSecretEnv: "APPLE_CLIENT_SECRET",
},
github: {
authorizeUrl: "https://github.com/login/oauth/authorize",
tokenUrl: "https://github.com/login/oauth/access_token",
@@ -137,63 +130,6 @@ export async function exchangeGoogleCode(
};
}
/**
* Exchange an authorization code for an Apple access token,
* then decode the ID token to get user info.
*/
export async function exchangeAppleCode(
code: string,
redirectUri: string
): Promise<ProviderUser> {
const clientId = process.env.APPLE_CLIENT_ID;
const clientSecret = process.env.APPLE_CLIENT_SECRET;
if (!clientId || !clientSecret) {
throw new Error("Apple OAuth is not configured");
}
// Exchange code for token
const tokenRes = await fetch("https://appleid.apple.com/auth/token", {
method: "POST",
headers: { "Content-Type": "application/x-www-form-urlencoded" },
body: new URLSearchParams({
code,
client_id: clientId,
client_secret: clientSecret,
redirect_uri: redirectUri,
grant_type: "authorization_code",
}),
});
if (!tokenRes.ok) {
const errBody = await tokenRes.text();
throw new Error(`Apple token exchange failed: ${errBody}`);
}
const tokenData = await tokenRes.json();
const idToken = tokenData.id_token;
if (!idToken) {
throw new Error("No ID token returned from Apple");
}
// Decode the JWT payload (second segment) — no verification needed here
// since Apple's token endpoint already verified the auth code.
const payloadBase64 = idToken.split(".")[1];
const payloadJson = Buffer.from(payloadBase64, "base64").toString("utf-8");
const payload = JSON.parse(payloadJson);
return {
providerId: payload.sub,
email: payload.email || "",
name:
payload.name ||
`${payload.given_name || ""} ${payload.family_name || ""}`.trim() ||
"User",
avatar: null, // Apple does not provide a profile photo
};
}
/**
* Exchange an authorization code for a GitHub access token,
* then fetch user info (and primary email).
@@ -292,8 +228,6 @@ export async function exchangeCode(
switch (provider) {
case "google":
return exchangeGoogleCode(code, redirectUri);
case "apple":
return exchangeAppleCode(code, redirectUri);
case "github":
return exchangeGitHubCode(code, redirectUri);
default:
@@ -381,10 +315,5 @@ export function buildAuthorizationUrl(
state,
});
// Apple requires response_mode=form_post
if (provider === "apple") {
params.set("response_mode", "form_post");
}
return `${config.authorizeUrl}?${params.toString()}`;
}