Přeskočit na hlavní obsah

Client Credentials Flow

Client Credentials Flow se používá pro komunikaci mezi stroji (M2M), kde není zapojen žádný uživatel. Toto flow je ideální pro backendové služby, cron joby a mikroslužby.

Kdy použít​

  • Backendová služba přistupující k API
  • Plánované úlohy / cron joby
  • Komunikace mezi mikroslužbami
  • Jakýkoli scénář bez interakce uživatele

Omezení​

  • Žádný kontext uživatele: Tokeny nereprezentují uživatele, pouze aplikaci
  • Žádné refresh tokeny: Při vypršení musíte požádat o nový token
  • Žádný ID token: Claims o identitě uživatele nejsou dostupné

Požadavek na token​

curl -X POST https://your-sso-domain.com/connect/token \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=client_credentials" \
-d "client_id=my-backend-service" \
-d "client_secret=my-service-secret" \
-d "scope=api"

Parametry:

ParametrPovinnýPopis
grant_typeAnoMusí být client_credentials
client_idAnoClient ID vaší aplikace
client_secretAnoClient secret vaší aplikace
scopeNePožadovaný scope pro přístup k API (api). Uživatelské scopes (openid, profile, …) zde nelze použít.

Odpověď:

{
"access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6ImF0K2p3dCJ9...",
"token_type": "Bearer",
"expires_in": 1800,
"scope": "api"
}

Claims v tokenu​

Tokeny client credentials obsahují identitu aplikace:

{
"sub": "my-backend-service",
"name": "My Backend Service",
"scope": "api",
"exp": 1704067200,
"iss": "https://your-sso-domain.com/"
}

sub odpovídá client_id aplikace a name je její zobrazovaný název. Token client credentials neobsahuje žádné uživatelské claims (např. email) ani role.

Osvědčené postupy​

  1. Cachujte tokeny: Opakovaně používejte tokeny dokud nevyprší (kontrolujte expires_in)
  2. Požadujte minimální scopes: Požadujte pouze scopes, které skutečně potřebujete
  3. Zabezpečte přihlašovací údaje: Ukládejte client_secret v environment proměnných nebo secret manageru
  4. Ošetřete vypršení tokenu: Požádejte o nový token, když aktuální vyprší
// Příklad: Logika cachování tokenů
let cachedToken = null;
let tokenExpiry = null;

async function getAccessToken() {
// Vrátit cachovaný token pokud je stále platný (s 60s rezervou)
if (cachedToken && tokenExpiry > Date.now() + 60000) {
return cachedToken;
}

// Požádat o nový token
const response = await fetch('https://your-sso-domain.com/connect/token', {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: 'grant_type=client_credentials&client_id=...&client_secret=...'
});

const data = await response.json();
cachedToken = data.access_token;
tokenExpiry = Date.now() + (data.expires_in * 1000);

return cachedToken;
}