misha-in/sso-client

Jednoduchý PHP klient pro integraci s SSO serverem pomocí OAuth 2.0 (Authorization Code + PKCE).

Maintainers

Package info

gitlab.com/misha.in/sso-client

Issues

pkg:composer/misha-in/sso-client

Statistics

Installs: 5

Dependents: 0

Suggesters: 0

Stars: 0

dev-main 2026-04-23 21:36 UTC

This package is not auto-updated.

Last update: 2026-04-23 22:31:27 UTC


README

Jednoduchý PHP klient pro integraci s SSO serverem id.produkce.ai pomocí OAuth 2.0 (Authorization Code + PKCE).

Nevyžaduje žádné závislosti – používá pouze PHP curl a cookies.

Požadavky

  • PHP 8.1+
  • Rozšíření curl

Instalace

Composer (doporučeno)

composer require misha-in/sso-client
use MishaIn\SsoClient\SsoClient;

Bez Composeru

require_once __DIR__ . '/SsoClient.php';

Konfigurace

$sso = new SsoClient([
    'client_id'     => 'my-app',                           // ID klienta registrovaného na SSO
    'client_secret' => 'tajny-klic',                       // Tajný klíč klienta
    'redirect_uri'  => 'https://app.example.com/callback', // Callback URL registrovaná na SSO
]);

Poznámka k scopům: Klient neposílá seznam požadovaných scopů. SSO server automaticky vrátí všechna oprávnění, která má přihlášený uživatel přiřazena pro danou aplikaci. Správa oprávnění probíhá výhradně na SSO serveru v administraci.

Použití

1. Přihlášení – přesměrování na SSO

$sso->redirectToLogin();
// Funkce ukončí skript přesměrováním (exit).

Interně se vygeneruje state (ochrana proti CSRF) a code_verifier (PKCE), které se uloží do krátkodobých cookies (platnost 10 minut, SameSite=Lax).

2. Callback – výměna kódu za tokeny

Na callback URL (registrované na SSO) zpracujte parametry z $_GET:

$code  = $_GET['code']  ?? '';
$state = $_GET['state'] ?? '';

try {
    $tokens = $sso->handleCallback($code, $state);
    // $tokens['access_token']  – přístupový token (platnost 1 hodina)
    // $tokens['refresh_token'] – obnovovací token (platnost 1 měsíc)
    // $tokens['expires_in']    – platnost access tokenu v sekundách (3600)
    // $tokens['token_type']    – "Bearer"
} catch (RuntimeException $e) {
    // Neplatný state (CSRF) nebo chyba serveru
    die('Přihlášení selhalo: ' . $e->getMessage());
}

Tokeny jsou automaticky uloženy do $_SESSION – klient je spravuje automaticky.

3. Informace o uživateli

$user = $sso->getUserInfo($tokens['access_token']);
// $user['sub']    – ID uživatele (int)
// $user['email']  – e-mailová adresa
// $user['name']   – celé jméno
// $user['scopes'] – pole přidělených oprávnění, např. ['dashboard', 'articles.faq', 'role.admin']

Scopy jsou ve formátu dot-notace: parent.child. Scope bez rodiče je jen identifier (např. dashboard).

4. Kontrola oprávnění (scope)

if ($sso->hasScope('articles.faq')) {
    // uživatel má přístup k articles.faq
}

Metoda interně zavolá getUserInfo() – doporučuje se výsledek cachovat na úrovni aplikace (např. ukládat $user do session po dobu přihlášení).

5. Ověření přihlášení

if (!$sso->isAuthenticated()) {
    $sso->redirectToLogin();
}

Metoda automaticky obnoví access token pomocí refresh tokenu, pokud vypršel. Pokud obnova selže (refresh token expiroval), vrátí false.

6. Platný access token

Pro přímou práci s tokenem (např. vlastní API volání):

$accessToken = $sso->getValidAccessToken();
if ($accessToken === null) {
    $sso->redirectToLogin(); // session vypršela
}

7. Obnovení tokenu

Access token se obnovuje automaticky při volání isAuthenticated() a getValidAccessToken(). Pokud potřebujete obnovit token ručně:

try {
    $newTokens = $sso->refreshToken($refreshToken);
} catch (RuntimeException $e) {
    // Refresh token vypršel – přesměrujte na přihlášení
    $sso->redirectToLogin();
}

8. Odhlášení

$sso->logout();
// nebo s přesměrováním po odhlášení:
$sso->logout('https://app.example.com/');

Pro sestavení URL bez okamžitého přesměrování (např. odkaz v šabloně):

$logoutUrl = $sso->getLogoutUrl('https://app.example.com/');

Kompletní příklad integrace

<?php
session_start();
require_once __DIR__ . '/SsoClient.php';

use MishaIn\SsoClient\SsoClient;

$sso = new SsoClient([
    'client_id'     => 'my-app',
    'client_secret' => 'tajny-klic',
    'redirect_uri'  => 'https://app.example.com/callback',
]);

$action = $_GET['action'] ?? '';

// Přihlášení
if ($action === 'login') {
    $sso->redirectToLogin();
}

// Callback ze SSO
if ($action === 'callback') {
    try {
        $sso->handleCallback($_GET['code'] ?? '', $_GET['state'] ?? '');
        header('Location: /dashboard');
        exit;
    } catch (RuntimeException $e) {
        die('Chyba přihlášení: ' . $e->getMessage());
    }
}

// Odhlášení
if ($action === 'logout') {
    $sso->logout('https://app.example.com/');
}

// Chráněná stránka
if (!$sso->isAuthenticated()) {
    $sso->redirectToLogin();
}

$accessToken = $sso->getValidAccessToken();
$user = $sso->getUserInfo($accessToken);

echo 'Přihlášen jako: ' . htmlspecialchars($user['name']);
echo 'Oprávnění: ' . implode(', ', $user['scopes']);

// Kontrola konkrétního oprávnění
if ($sso->hasScope('articles.faq')) {
    echo 'Má přístup k FAQ.';
}

Přehled metod

MetodaNávratový typPopis
redirectToLogin(): neverPřesměruje uživatele na SSO přihlašovací stránku
handleCallback(string $code, string $state): arraytokenyVymění authorization code za tokeny, uloží do session
isAuthenticated(): boolboolVrátí true pokud je uživatel přihlášen (automaticky obnoví token)
getValidAccessToken(): ?stringstring|nullVrátí platný access token nebo null pokud session vypršela
getUserInfo(string $accessToken): arrayuser arrayVrátí data uživatele vč. pole scopes
hasScope(string $scope): boolboolZkontroluje, zda má uživatel dané oprávnění
refreshToken(string $refreshToken): arraytokenyRučně obnoví access token
isTokenValid(string $accessToken): boolboolOvěří platnost tokenu dotazem na SSO
getLogoutUrl(?string $redirectUri = null): stringstringVrátí URL pro odhlášení (bez přesměrování)
logout(?string $redirectUri = null): neverOdhlásí uživatele a přesměruje na SSO

Formát scopů

Oprávnění jsou ve formátu dot-notace odpovídající hierarchii definované na SSO serveru:

rag          – přístup k celému rag modulu
rag.faq      – přístup k faq v rámci rag
rag.files    – přístup k files v rámci rag
rag.prompt   – přístup k prompt v rámci rag
role.root    – role root

Každý uživatel má oprávnění spravována administrátorem přímo na SSO serveru. Aplikace scopy nežádá – dostane automaticky vše, co má daný uživatel přiřazeno.

Bezpečnostní poznámky

  • CSRF ochrana: state parametr je generován pomocí random_bytes(32) a ověřován přes hash_equals().
  • PKCE: Každý login flow používá unikátní code_verifier (S256) – chrání i při úniku authorization code.
  • Tajný klíč (client_secret) nikdy neopouští server – nikdy ho nevkládejte do front-endového kódu nebo do verzovacího systému.
  • Tokeny jsou ukládány do $_SESSION na straně serveru.