Authentication strategies for AssegaiPHP and standalone PHP applications.
assegaiphp/auth is a small authentication package built around focused strategies instead of a full auth framework.
Today the package ships with:
SessionAuthStrategyfor session-backed login stateJwtAuthStrategyfor stateless JWT authenticationOAuth2AuthStrategyfor OAuth 2.0 authorization-code login flowsGitHubOAuthProvideras the first ready-to-use OAuth provider adapter
The package is intentionally narrow. It helps you:
- authenticate a known user object
- issue session or JWT auth state
- begin and complete OAuth 2.0 login flows
- hand a resolved OAuth user into session or JWT auth
It does not currently provide:
- user lookup or persistence
- registration or password reset flows
- refresh token rotation
- OAuth route/controllers for you
- OAuth guard wiring
- multiple polished provider adapters beyond GitHub
You still own the application flow around it: loading users, choosing when to authenticate, defining routes, and deciding what to do after login succeeds.
For commit and pull request conventions in this repo, see:
composer require assegaiphp/authFor a complete Core 0.10.x application flow with repository lookup, a guard, configurable failure redirects, intended-target restoration, and logout, see Session Login End to End.
Use SessionAuthStrategy when you want the authenticated user stored in $_SESSION.
<?php
use Assegai\Auth\Strategies\SessionAuthStrategy;
$user = (object) [
'id' => 7,
'email' => 'user@example.com',
'password' => password_hash('secret', PASSWORD_DEFAULT),
'name' => 'Test User',
];
$strategy = new SessionAuthStrategy([
'user' => $user,
'session_name' => 'blog_api',
'session_lifetime' => '+1 hour',
]);
if ($strategy->authenticate([
'email' => 'user@example.com',
'password' => 'secret',
])) {
$currentUser = $strategy->getUser();
}On successful authentication the strategy:
- starts a session if needed
- clones the configured user object
- removes the password field from that clone
- stores the sanitized user in
$_SESSION['user']
When this strategy runs inside an Assegai core application, core owns the already-active session and its cookie configuration. Configure the session name, lifetime, cookie flags, SameSite policy, and login redirect behavior in config/auth.php instead of passing standalone session options to each strategy instance.
For protected browser controllers, pair a session guard that raises UnauthorizedException with core's configurable LoginRedirectFilter. The filter requires the application login URL, can retain a safe intended URL in the session, and can be replaced with any application-defined exception filter when the default behavior is insufficient.
This is useful after an OAuth callback, when the user has already been verified by the provider and you just want to establish a local session.
$strategy->establishAuthenticatedUser((object) [
'id' => 42,
'email' => 'oauth@example.com',
'name' => 'OAuth User',
]);Use JwtAuthStrategy when you want to issue a JWT and later validate it from a bearer token or from a token you pass into the strategy config.
<?php
use Assegai\Auth\Strategies\JwtAuthStrategy;
$user = (object) [
'id' => 7,
'email' => 'user@example.com',
'password' => password_hash('secret', PASSWORD_DEFAULT),
'roles' => ['author'],
'name' => 'Test User',
];
$strategy = new JwtAuthStrategy([
'user' => $user,
'secret_key' => 'replace-with-a-long-random-secret-key',
'issuer' => 'blog-api',
'audience' => 'blog-api-clients',
'token_lifetime' => '+1 hour',
]);
if ($strategy->authenticate([
'email' => 'user@example.com',
'password' => 'secret',
])) {
$token = $strategy->getToken();
}On successful authentication the strategy creates a token payload with:
sub- the configured username field
iatexp- optional
iss - optional
aud - optional
roles - optional
name
isAuthenticated() validates either:
- the token generated by the strategy, or
- the
Authorization: Bearer ...header when one is present
This is useful after an OAuth callback when you want to mint a local API token for a provider-authenticated user.
$token = $strategy->issueTokenForUser((object) [
'id' => 42,
'email' => 'oauth@example.com',
'name' => 'OAuth User',
'roles' => ['member'],
]);Use OAuth2AuthStrategy when you need an authorization-code flow such as "Sign in with GitHub".
Unlike the session and JWT strategies, OAuth is a redirect-based flow, so it does not implement AuthStrategyInterface.
The OAuth flow is split into two steps:
- build the authorization request and redirect the user
- handle the callback and establish local auth state
<?php
use Assegai\Auth\OAuth\OAuth2AuthStrategy;
use Assegai\Auth\OAuth\Providers\GitHubOAuthProvider;
use Assegai\Auth\OAuth\State\SessionOAuthStateStore;
use Assegai\Auth\Strategies\SessionAuthStrategy;
$sessionStrategy = new SessionAuthStrategy([
'user' => (object) [],
'session_name' => 'blog_api',
]);
$oauth = new OAuth2AuthStrategy(
provider: new GitHubOAuthProvider(),
config: GitHubOAuthProvider::defaultConfig(
clientId: 'your-github-client-id',
clientSecret: 'your-github-client-secret',
redirectUri: 'https://example.com/auth/github/callback',
),
stateStore: new SessionOAuthStateStore(),
sessionStrategy: $sessionStrategy,
);
$request = $oauth->beginLogin();
header('Location: ' . $request->url);
exit;<?php
use Assegai\Auth\OAuth\OAuth2AuthStrategy;
use Assegai\Auth\OAuth\Providers\GitHubOAuthProvider;
use Assegai\Auth\OAuth\State\SessionOAuthStateStore;
use Assegai\Auth\Strategies\JwtAuthStrategy;
use Assegai\Auth\Strategies\SessionAuthStrategy;
$sessionStrategy = new SessionAuthStrategy([
'user' => (object) [],
]);
$jwtStrategy = new JwtAuthStrategy([
'secret_key' => 'replace-with-a-long-random-secret-key',
'user' => (object) [
'email' => 'placeholder@example.com',
'password' => password_hash('placeholder', PASSWORD_DEFAULT),
],
]);
$oauth = new OAuth2AuthStrategy(
provider: new GitHubOAuthProvider(),
config: GitHubOAuthProvider::defaultConfig(
clientId: 'your-github-client-id',
clientSecret: 'your-github-client-secret',
redirectUri: 'https://example.com/auth/github/callback',
),
stateStore: new SessionOAuthStateStore(),
sessionStrategy: $sessionStrategy,
jwtStrategy: $jwtStrategy,
);
$result = $oauth->handleCallback($_GET);
// $result->user
// $result->profile
// $result->sessionEstablished
// $result->jwtTokenOAuth2AuthStrategy:
- generates a secure state value
- generates PKCE verifier/challenge by default
- stores the state in the configured
OAuthStateStoreInterface - exchanges the callback code for tokens
- fetches the provider profile
- resolves a local user object
- optionally hands that user into session and/or JWT auth
What is ready today:
- generic OAuth provider interface
- PKCE-enabled authorization code flow
- session-backed state store
- GitHub provider adapter
- local session/JWT handoff
What you still provide:
- the login route
- the callback route
- any persistence or lookup logic for provider users
- redirects or API responses after login
If GitHub is not the right provider, implement OAuthProviderInterface.
You need to provide:
- a provider name
- how to build the authorization URL
- how to exchange a code for tokens
- how to fetch the provider user profile
You can also extend AbstractOAuthProvider to reuse the common HTTP and URL-building helpers.
If the built-in session or JWT strategies are not the right fit, implement AuthStrategyInterface.
<?php
use Assegai\Auth\Interfaces\AuthStrategyInterface;
class CustomAuthStrategy implements AuthStrategyInterface
{
public function authenticate(array $credentials): bool
{
return false;
}
public function isAuthenticated(): bool
{
return false;
}
public function getUser(): ?object
{
return null;
}
public function logout(): void
{
}
}In an Assegai app, a common pattern is:
- load a user from your repository or service
- pass that user into a session or JWT strategy, or complete an OAuth callback
- establish local auth state
- read authentication state from your guards, providers, or handlers
This package handles the strategy side of that flow. The application still owns the surrounding request flow.
| Method | Description |
|---|---|
authenticate(array $credentials): bool |
Validates credentials and establishes authentication state. |
isAuthenticated(): bool |
Checks whether the current strategy considers the request authenticated. |
getUser(): ?object |
Returns the authenticated user or token-backed user payload. |
logout(): void |
Clears the current authentication state. |
| Method | Description |
|---|---|
establishAuthenticatedUser(object $user): void |
Establishes trusted session auth without re-checking credentials. |
| Method | Description |
|---|---|
getToken(): string |
Returns the last generated JWT. |
getDecoded(): \stdClass |
Decodes the current JWT with the configured key and algorithm. |
issueTokenForUser(object $user): string |
Issues a JWT for a trusted user object without re-checking credentials. |
| Method | Description |
|---|---|
beginLogin(): OAuthAuthorizationRequest |
Builds the provider redirect request and persists state/PKCE data. |
handleCallback(array $callback): OAuthLoginResult |
Validates the callback, resolves the provider user, and optionally establishes local auth state. |
vendor/bin/pestMIT. See LICENSE.