Testing
The package ships test helpers in Bambamboole\LaravelOidc\Server\Testing. Add the
trait to your suite:
// Pest (tests/Pest.php)uses(Bambamboole\LaravelOidc\Server\Testing\InteractsWithOidc::class)->in('Feature');
// PHPUnitabstract class TestCase extends BaseTestCase{ use \Bambamboole\LaravelOidc\Server\Testing\InteractsWithOidc;}Authenticating an identity
Section titled “Authenticating an identity”actingAsIdentity() logs the user in on the identity guard and seeds the
session keys the authorization grant reads (oidc.auth_time, oidc.amr,
oidc.id_token_claims, oidc.access_token_claims):
$this->actingAsIdentity($user, amr: ['pwd', 'otp'], authTime: time() - 60);There is no acr parameter: the grant derives acr from amr through the bound
AcrResolver (oidc.login.acr_single_factor / oidc.login.acr_multi_factor: 1 for a single method, 2 for multiple by default).
Acting as a token user
Section titled “Acting as a token user”actingAsOidcUser() authenticates a user on the token guard with an
unpersisted token that grants the listed scopes — for routes behind
auth:oidc that only inspect scopes:
$this->actingAsOidcUser($user, ['openid', 'email']);Acting as a machine client
Section titled “Acting as a machine client”actingAsOidcClient() is the counterpart for a client_credentials caller: it
authenticates a ClientPrincipal on the token guard with an unpersisted token
granting the listed scopes.
$client = $this->createOidcMachineClient(); // a confidential client_credentials client
$this->actingAsOidcClient($client, ['orders.read']);Minting tokens without the HTTP dance
Section titled “Minting tokens without the HTTP dance”issueTokenFor() returns a signed at+jwt access token with a persisted
persisted token row — ready for a Bearer header:
$jwt = $this->issueTokenFor($user, scopes: ['openid', 'email'], audience: ['https://api.orders.test']);
$this->withHeader('Authorization', 'Bearer '.$jwt)->get('/api/orders');When no client is given, a default authorization-code client is created once per test and reused.
issueClientToken() mints the userless equivalent — the token
client_credentials issues, whose principal is the client itself:
$jwt = $this->issueClientToken($this->createOidcMachineClient(), ['orders.read']);A token minted with a custom audience: does not authenticate on plain
auth:oidc routes unless that audience is the realm issuer or a resource registered under
oidc.resources — the guard accepts a token only when its aud names one of them. Without
audience: the token is addressed to the issuer and passes plain auth:oidc routes, but not a
route behind CheckAudience for another resource. See Resource servers (CheckAudience).
Clients
Section titled “Clients”$client = $this->createOidcClient(); // auth-code grant client$client = $this->createOidcMachineClient(); // client_credentials grant client$client = $this->withFirstPartyClient(); // + sets oidc.clients.first_party.* configConfig mutated in a test takes effect immediately — the package reads
oidc.clients.first_party.* at call time, so no forgetInstance() ceremony is
needed after config([...]) changes.
withFirstPartyClient() sets oidc.clients.first_party.trusted = true, so consent
is skipped for that client; register a client via createOidcClient()
instead when a test asserts consent behavior.
Rows the package stores
Section titled “Rows the package stores”Sessions, session participants, consents, access and refresh tokens, authorization codes and authentication contexts have model factories, for a test that needs the row without the flow that writes it:
use Bambamboole\LaravelOidc\Server\Sessions\Models\OidcSession;use Bambamboole\LaravelOidc\Server\Tokens\Models\AccessToken;use Bambamboole\LaravelOidc\Server\Tokens\Models\RefreshToken;
$session = OidcSession::factory()->forUser($user)->create();$token = AccessToken::factory()->forClient($client)->forUser($user)->create();RefreshToken::factory()->forAccessToken($token)->create();These rows name their user and client without a foreign key, so use forUser() and
forClient() rather than for(). forClient() also puts the row in the client’s realm;
otherwise a row lands in the current one.
The full authorization-code flow
Section titled “The full authorization-code flow”authorizeAndApprove() drives authorize → approve → token with PKCE:
$result = $this->authorizeAndApprove($user, $client, scopes: 'openid email');
$result->accessToken;$result->idToken;$result->refreshToken;The authorize and approve legs assert success; the token response is returned unasserted, so error paths stay testable:
$result = $this->authorizeAndApprove($user, $misconfiguredClient);
$result->response->assertStatus(401);$result->response->json('error'); // invalid_clientparams: overrides any authorize query parameter (state, nonce,
max_age, redirect_uri, …), and pkce: accepts a fixed
PkcePair when the test needs the verifier later. The helper binds a
minimal JSON ConsentView unless the test (or FakesAuthViews, or the ui
package) already bound one.
The CSRF exemption applied by authorizeAndApprove() persists for the
remainder of the calling test method.