RocketChat/Rocket.Chat · error · Error

Could not retrieve Apple public keys

Error message

Could not retrieve Apple public keys

What it means

Thrown by getApplePublicKeys when fetching https://appleid.apple.com/auth/keys fails and there is no previously cached key set to fall back on. Apple's JWKS are required to verify Sign-in-with-Apple identityToken signatures. Keys are cached in-process for 24h and a stale cache is served if a refresh fails, so this error means the very first fetch (cold start) failed: outbound network to Apple is not working.

Source

Thrown at apps/meteor/server/lib/auth-providers/apple/handleIdentityToken.ts:59

			// SECURITY: Hardcoded URL, no SSRF protection needed
			ignoreSsrfValidation: true,
		});

		if (!response.ok) {
			throw new Error(`Failed to fetch Apple keys: ${response.status} ${response.statusText}`);
		}

		const data = (await response.json()) as { keys: AppleJWK[] };
		cachedKeys = data.keys;
		lastFetchTime = now;

		return cachedKeys;
	} catch (error) {
		if (cachedKeys) {
			console.warn('Failed to refresh Apple public keys, using stale cache', error);
			return cachedKeys;
		}
		throw new Error('Could not retrieve Apple public keys', { cause: error });
	}
}

function decodeBase64Url(str: string): string {
	return Buffer.from(str, 'base64url').toString('utf8');
}

async function verifyAppleJWT(
	headerB64: string,
	payloadB64: string,
	signatureB64: string,
	clientId: string,
): Promise<AppleJWTPayload | null> {
	const header = JSON.parse(decodeBase64Url(headerB64));
	const payload = JSON.parse(decodeBase64Url(payloadB64)) as AppleJWTPayload;

	const nowInSeconds = Math.floor(Date.now() / 1000);

View on GitHub (pinned to b2c16d5842)

Solutions

  1. Allow outbound HTTPS to appleid.apple.com from the Rocket.Chat server process (proxy/allow-list/firewall)
  2. Configure the HTTP(S)_PROXY environment for the server so server-fetch reaches Apple
  3. Retry after connectivity is fixed; once one fetch succeeds, the 24h cache absorbs short Apple outages
Defensive patterns

Strategy: retry

Validate before calling

// pre-flight egress check at startup
try {
	const res = await fetch('https://appleid.apple.com/auth/keys');
	if (!res.ok) throw new Error(`Apple JWKS unreachable: ${res.status}`);
} catch (e) {
	logger.error('Apple login will fail: no egress to appleid.apple.com', e);
}

Try / catch

try {
	const serviceData = await handleIdentityToken(identityToken, clientId);
} catch (e) {
	if (e instanceof Error && e.message === 'Could not retrieve Apple public keys') {
		// transient network / egress issue: inform user, retry with backoff; check e.cause
	} else throw e;
}

Prevention

When it happens

Trigger: Apple OAuth login on a server with blocked internet egress (firewall/proxy/DNS) so the JWKS fetch throws or returns non-200; Apple endpoint temporarily unavailable during a cold start; proxy misconfiguration stripping the request; TLS interception breaking the connection.

Common situations: Self-hosted instances in air-gapped or egress-restricted networks; containers without proxy env vars; on-prem installs where only specific domains are allow-listed and appleid.apple.com is missing.

Related errors


AI-assisted analysis of RocketChat/Rocket.Chat@b2c16d5842 (2026-08-18). Data as JSON: /api/errors/d1cea9f8bffb8bf6. Report an issue: GitHub.