← cd ../blog

Integrare Apple Sign In cu Keycloak: Ghid Practic

Integrare Apple Sign In cu Keycloak: Ghid Practic — imagine de copertă

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:

  1. App ID: Activează „Sign In with Apple” în secțiunea Capabilities.
  2. Services ID: Creează un Service ID pentru aplicația ta web. Acesta va fi folosit de Keycloak pentru redirect-uri.
  3. Redirect URI: Adaugă URL-ul de callback Keycloak: https://auth.babilon-audiobooks.ro/realms/radio-babilon/broker/apple/endpoint.
  4. 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!