PHPackages                             amtgard/idp-php-client - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Authentication &amp; Authorization](/categories/authentication)
4. /
5. amtgard/idp-php-client

ActiveLibrary[Authentication &amp; Authorization](/categories/authentication)

amtgard/idp-php-client
======================

Opinionated PHP client for the Amtgard Identity Provider OAuth 2.0 and resource API

v0.12.0(yesterday)010↑2600%proprietaryPHPPHP ^8.2

Since Jun 8Pushed yesterdayCompare

[ Source](https://github.com/amtgard/amtgard-idp-php-client)[ Packagist](https://packagist.org/packages/amtgard/idp-php-client)[ RSS](/packages/amtgard-idp-php-client/feed)WikiDiscussions main Synced yesterday

READMEChangelog (4)Dependencies (11)Versions (8)Used By (0)

amtgard-idp-php-client
======================

[](#amtgard-idp-php-client)

Opinionated PHP client for the [Amtgard Identity Provider](https://github.com/amtgard/amtgard-bastion-idp) OAuth 2.0 authorization code + PKCE flow and resource API.

This library encodes **one** integration path so third-party apps stop re-implementing OAuth details incorrectly:

- Authorization code grant with **PKCE (S256)** — always, including confidential clients
- Scopes: `profile email` (space-separated)
- Resource calls: `GET /resources/userinfo`, `GET /resources/validate`, `GET /resources/jwt`
- Policy evaluation: `POST /api/is_authorized` (backend services)
- Typed results: `TokenSet`, `UserProfile`, `OrkProfile`, `ValidatedSession`, `AuthorizationCheck`

Apps can wire config manually (`IdpClientEnvironment`) or use the on-rails factories that read standard `IDP_*` environment variables.

Installation
------------

[](#installation)

```
composer require amtgard/idp-php-client guzzlehttp/guzzle
```

Slim apps should also install Slim to use the bundled auth controller:

```
composer require slim/slim
```

Configuration (`.env`)
----------------------

[](#configuration-env)

Load `.env` before your DI container boots (e.g. `vlucas/phpdotenv` in `public/index.php`). The on-rails factories expect these variables:

```
IDP_BASE_URL=https://idp.amtgard.com
IDP_CLIENT_ID=my-app
IDP_CLIENT_SECRET=your-confidential-client-secret
IDP_REDIRECT_URI=https://my.app/oauth/callback
# IDP_HTTP_USER_AGENT is optional — defaults to AmtgardIDP/1.0
# IDP_HTTP_USER_AGENT=MyApp/1.0
```

VariableRequiredExampleNotes`IDP_BASE_URL`Yes`https://idp.amtgard.com`No trailing slash`IDP_CLIENT_ID`Yes`my-app`Registered with IDP maintainers`IDP_REDIRECT_URI`Yes`https://my.app/oauth/callback`Must match registration **exactly**`IDP_CLIENT_SECRET`No`(secret)`Omit for public clients (PKCE only)`IDP_HTTP_USER_AGENT`No`AmtgardIDP/1.0`Sent on **every** server-side IDP request (`/oauth/token`, `/resources/*`, `/api/*`). Override only when IDP ops instruct you to.Quick start (on-rails factories)
--------------------------------

[](#quick-start-on-rails-factories)

With `.env` populated, one factory call wires environment, OAuth flow state, and HTTP client:

```
use Amtgard\IdpClient\IdpClientFactory;

session_start();

$idp = IdpClientFactory::fromEnvVars();

// GET /login
return $idp->beginAuthorization(returnTo: '/dashboard');

// GET /oauth/callback
$session = $idp->completeLogin($request);
// $session->tokens, $session->profile, $session->returnTo
```

Factory chain:

FactoryBuilds`IdpClientEnvironmentFactory::fromEnvVars()``EnvIdpClientEnvironment` from `IDP_*` vars (throws `IdpConfigurationException` if required vars missing)`IdpClientFactory::fromEnvVars()`Full `IdpClient` with `SessionOAuthFlowStateStore` + Guzzle`IdpClient::completeLogin()`Token exchange + `/resources/userinfo` in one call`SessionAuthStore`Persist `AuthenticatedSession` in `$_SESSION` (framework-agnostic)### Session persistence (any PHP app)

[](#session-persistence-any-php-app)

```
use Amtgard\IdpClient\SessionAuthStore;

$authStore = new SessionAuthStore();

// After callback:
$authStore->store($idp->completeLogin($request));

// Later requests:
if ($authStore->isAuthenticated()) {
    $session = $authStore->get();
    $email = $session->profile->email;
}

// Logout:
$authStore->clear();
```

Manual configuration (custom environments)
------------------------------------------

[](#manual-configuration-custom-environments)

When you cannot use `IDP_*` env vars (multi-tenant config, tests, non-`.env` apps), implement `IdpClientEnvironment` yourself or use `ArrayEnvironment`:

```
use Amtgard\IdpClient\ArrayEnvironment;
use Amtgard\IdpClient\IdpClientFactory;
use Amtgard\IdpClient\SessionOAuthFlowStateStore;

$env = new ArrayEnvironment(
    idpBaseUrl: 'https://idp.amtgard.com',
    clientId: 'my-app',
    clientSecret: 'your-secret',
    redirectUri: 'https://my.app/oauth/callback',
);

$idp = IdpClientFactory::fromEnvironment($env, new SessionOAuthFlowStateStore());
```

Equivalent to the on-rails env factory, but explicit:

```
use Amtgard\IdpClient\IdpClientEnvironmentFactory;

$env = IdpClientEnvironmentFactory::fromEnvVars([
    'IDP_BASE_URL' => 'https://idp.amtgard.com',
    'IDP_CLIENT_ID' => 'my-app',
    'IDP_REDIRECT_URI' => 'https://my.app/oauth/callback',
    'IDP_CLIENT_SECRET' => 'secret',
]);
```

For app-specific env layout, wrap or replace `EnvIdpClientEnvironment` with your own class implementing `IdpClientEnvironment` and pass it to `IdpClientFactory::fromEnvironment()`.

Resource API
------------

[](#resource-api)

After login, use the access token from `TokenSet` or `AuthenticatedSession`:

```
$token = $session->tokens->accessToken();

// Full profile (includes optional ORK link data)
$profile = $idp->fetchUserProfile($token);

// Session heartbeat — lighter than userinfo; returns id, email, jwt
$validated = $idp->validate($token);

// Fresh authorization JWT (cached server-side for validate/pubsub)
$jwt = $idp->fetchJwt($token);
```

Backend services can evaluate IAM policies without a user bearer token:

```
$check = $idp->checkAuthorization(
    policy: $userPolicyOrnArray,
    requirement: 'Idp:0:0:0:0:IDP/EditClient',
);

if ($check->isAuthorized) {
    // allow action
}
```

`checkAuthorization()` posts to the public `/api/is_authorized` endpoint. Most OAuth client apps only need `fetchUserProfile()` and `validate()`; use policy evaluation when your service already holds a user's IAM policy JSON.

Slim 4 integration
------------------

[](#slim-4-integration)

[Slim 4](https://www.slimframework.com/) apps can use the bundled Slim helpers in `Amtgard\IdpClient\Slim\` — a drop-in auth controller and session middleware. Layout matches other Amtgard PHP projects: PHP-DI `container.php` + `routes.php`.

**Assumptions:** Slim 4, PHP-DI, `vlucas/phpdotenv`, `guzzlehttp/guzzle`, `.env` configured as above.

### On-rails Slim setup (recommended)

[](#on-rails-slim-setup-recommended)

**`config/container.php`** — minimal wiring with env factories:

```
