Recent, în cadrul proiectului radio-babilon, am fost nevoiți să integrăm Apple Sign In pentru a oferi utilizatorilor noștri de iOS o experiență de autentificare rapidă și sigură. Deși Keycloak oferă suport nativ pentru Identity Providers (IdP), integrarea cu Apple este adesea o sursă de dureri de cap din cauza cerințelor stricte de securitate Apple (JWT-uri, client secrets și private keys).
Pasul 1: Configurarea în Apple Developer Portal
Înainte de a atinge Keycloak, trebuie să pregătim terenul în consola Apple:
- App ID: Activează „Sign In with Apple” în secțiunea Capabilities.
- Services ID: Creează un Service ID pentru aplicația ta web. Acesta va fi folosit de Keycloak pentru redirect-uri.
- Redirect URI: Adaugă URL-ul de callback Keycloak:
https://auth.babilon-audiobooks.ro/realms/radio-babilon/broker/apple/endpoint. - Key (.p8): Descarcă cheia privată. Este esențială pentru semnarea
client_secret.
Pasul 2: Generarea Client Secret pentru Keycloak
Apple necesită un JWT semnat cu algoritmul ES256 pentru a valida cererile. Keycloak are nevoie de acest secret pentru a comunica cu serverele Apple. Poți converti cheia ta privată pentru a fi compatibilă cu utilitarele de sistem:
# Conversia cheii private pentru Keycloak
openssl pkcs8 -topk8 -inform PEM -outform PEM -in AuthKey.p8 -nocrypt
În consola Keycloak (Identity Providers -> Apple), vei introduce Team ID, Key ID și Client ID (Services ID), alături de cheia privată generată.
Pasul 3: Maparea atributelor și Scripting
Apple trimite datele utilizatorului (nume, email) doar la prima autentificare. Pentru a ne asigura că acestea sunt stocate corect în baza de date Keycloak, am creat un mapper personalizat.
// Exemplu de mapper script pentru Keycloak
var email = user.getAttribute('email') || idp.getClaim('email');
var firstName = idp.getClaim('name') ? idp.getClaim('name').firstName : 'Utilizator';
user.setEmail(email);
user.setFirstName(firstName);
Pasul 4: Gestionarea fluxului și probleme comune
Cea mai mare provocare a fost „Email-ul ascuns” (Private Relay). Dacă utilizatorul alege să își ascundă adresa, Apple returnează un email de tip @privaterelay.appleid.com. Keycloak va trata acest email ca fiind unic, deci asigură-te că logica ta de business permite acest format.
Pentru backend-ul nostru Node.js, validăm token-ul primit de la Keycloak folosind middleware-ul standard:
const jwt = require('jsonwebtoken');
const verifyAppleToken = (req, res, next) => {
const token = req.headers.authorization.split(' ')[1];
// Verificare JWT emis de Keycloak după succesul cu Apple
jwt.verify(token, process.env.KEYCLOAK_PUBLIC_KEY, (err, decoded) => {
if (err) return res.status(401).send('Invalid Token');
req.user = decoded;
next();
});
};
Configurare prin API
Dacă preferi automatizarea, poți configura IdP-ul prin API-ul Keycloak folosind un payload JSON:
{
"alias": "apple",
"providerId": "apple",
"enabled": true,
"config": {
"clientId": "com.radio-babilon.service",
"clientSecret": "...",
"teamId": "XYZ123"
}
}
Concluzie
Integrarea Apple Sign In nu este trivială, dar odată configurată corect, oferă un nivel ridicat de încredere pentru utilizatorii de iPhone. Nu uita să testezi fluxul de „re-linkare” a contului dacă un utilizator încearcă să se autentifice cu același email, dar folosind o metodă diferită anterior. Succes la codat!

