/callback as redirect URI for your client first. require __DIR__ . '/vendor/autoload.php'; use Jumbojett\OpenIDConnectClient; $issuer = getenv('CODEB_ISSUER') ?: 'https://phone.aloaha.com'; $appBaseUrl = getenv('APP_BASE_URL') ?: 'http://localhost:3000'; $walletAcrs = ['urn:codeb:acr:eudi-wallet', 'urn:codeb:acr:eudi-wallet-linked']; session_start(); $path = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH); if ($path === '/login' || $path === '/callback') { $oidc = new OpenIDConnectClient( $issuer, getenv('CODEB_CLIENT_ID') ?: '', getenv('CODEB_CLIENT_SECRET') ?: '' ); $oidc->setRedirectURL($appBaseUrl . '/callback'); $oidc->addScope(['openid', 'profile', 'email']); $oidc->setCodeChallengeMethod('S256'); $oidc->addAuthParam(['acr_values' => $walletAcrs[0]]); // straight to the wallet sign-in // First call redirects to CodeB; on /callback it exchanges the code and checks // state, nonce, signature, issuer, audience and expiry of the id_token. try { $oidc->authenticate(); } catch (\Jumbojett\OpenIDConnectClientException $e) { http_response_code(400); // wrong state, expired code, invalid token ... echo 'Sign-in failed: ' . htmlspecialchars($e->getMessage()); exit; } $acr = $oidc->getVerifiedClaims('acr'); if (!in_array($acr, $walletAcrs, true)) { http_response_code(403); echo 'This page needs a sign-in with the EU Digital Identity Wallet (acr=' . htmlspecialchars((string)$acr) . ').'; exit; } session_regenerate_id(true); $_SESSION['user'] = ['sub' => $oidc->getVerifiedClaims('sub'), 'acr' => $acr]; header('Location: /'); exit; } if (!empty($_SESSION['user'])) { echo 'Signed in as ' . htmlspecialchars($_SESSION['user']['sub']) . ' (acr=' . htmlspecialchars($_SESSION['user']['acr']) . ')'; } else { echo 'Sign in with your EU Digital Identity Wallet'; }