Choose the authentication approach that matches the kind of client you are building.
Authentication strategy vs application flow
assegaiphp/auth gives you authentication strategies.
A strategy answers questions like:
- should login result in a PHP session?
- should login result in a JWT?
- should login begin with an OAuth redirect?
Your application still owns the wider flow:
- load a user
- decide which strategy to use
- call the strategy
- decide what response to send
That distinction matters because it keeps the package usable outside Assegai too.
Session strategy in real applications
Session auth is usually the simplest fit for:
- admin panels
- dashboards
- back-office tools
- server-rendered apps
The session strategy expects a known user object:
<?php
use Assegai\Auth\Strategies\SessionAuthStrategy;
$strategy = new SessionAuthStrategy([
'user' => $user,
'session_name' => 'admin_portal',
'session_lifetime' => '+8 hours',
]);
If authentication succeeds, the package stores a safe copy of the user in the session.
That means a later request can ask:
if ($strategy->isAuthenticated()) {
$currentUser = $strategy->getUser();
}
JWT strategy in real applications
JWT auth is usually a better fit for:
- SPA clients
- mobile apps
- third-party API consumers
- machine-to-machine calls
The token is generated once and then sent back by the client on later requests:
Authorization: Bearer <token>
If you use JWT auth, think clearly about:
- token lifetime
- secret management
- issuer and audience
- how clients refresh or re-authenticate when tokens expire
assegaiphp/auth handles token creation and validation. Your app still chooses the surrounding policy.
OAuth changes the login flow
OAuth is different from a simple email/password flow because the user leaves your app and returns later.
That means the flow has two distinct phases:
- begin login
- handle the callback
Begin login
<?php
use Assegai\Auth\OAuth\OAuth2AuthStrategy;
use Assegai\Auth\OAuth\Providers\GitHubOAuthProvider;
use Assegai\Auth\OAuth\State\SessionOAuthStateStore;
$strategy = 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(),
);
$request = $strategy->beginLogin();
The returned OAuthAuthorizationRequest contains:
- the provider URL
- the generated state value
- the PKCE verifier
- the PKCE challenge
In a browser flow, your route would usually redirect the user to $request->url.
Handle the callback
<?php
$result = $strategy->handleCallback($_GET);
That callback step:
- validates provider errors
- checks the returned state value
- exchanges the code for tokens
- fetches the provider profile
- resolves a local user object
If you also pass a SessionAuthStrategy or JwtAuthStrategy, the callback can establish local auth state immediately.
GitHub is the first ready provider
The package currently ships a ready GitHub adapter:
That does not mean OAuth is GitHub-only forever. It means GitHub is the first polished adapter in the package today.
If you need another provider, implement OAuthProviderInterface or extend AbstractOAuthProvider.
Mapping provider users to local users
An OAuth provider profile is not always the same thing as your application's user record.
For example, you may need to:
- look up an existing user by email
- create a user the first time they sign in
- link one GitHub identity to one local user row
- restrict login to a company domain or allow-list
That is why OAuth2AuthStrategy uses a resolver step instead of assuming every provider profile should become a user automatically.
A realistic callback handler
The code below shows the shape of a practical callback flow:
<?php
use Assegai\Auth\OAuth\DefaultOAuthUserResolver;
use Assegai\Auth\OAuth\OAuth2AuthStrategy;
use Assegai\Auth\OAuth\Providers\GitHubOAuthProvider;
use Assegai\Auth\OAuth\State\SessionOAuthStateStore;
use Assegai\Auth\Strategies\SessionAuthStrategy;
$session = new SessionAuthStrategy(['user' => (object) []]);
$strategy = new OAuth2AuthStrategy(
provider: new GitHubOAuthProvider(),
config: GitHubOAuthProvider::defaultConfig(
clientId: $githubClientId,
clientSecret: $githubClientSecret,
redirectUri: $redirectUri,
),
stateStore: new SessionOAuthStateStore(),
userResolver: new DefaultOAuthUserResolver(),
sessionStrategy: $session,
);
$result = $strategy->handleCallback($_GET);
// Redirect to the app, return JSON, or create a local account link here.
In a production app, the resolver is often the first thing you will replace with your own logic.
What is intentionally not automatic yet
Assegai's auth package is usable today, but it is still intentionally narrow.
That means you do not get all of these automatically:
- login controllers
- callback routes
- guard decorators
- refresh tokens
- full account linking workflows
- provider-specific dashboard configuration
That is not a missing paragraph in the docs. It is the current boundary of the package.
Security notes
Keep these practical rules in mind:
- never store plain-text passwords
- use a long random JWT secret
- keep OAuth client secrets out of source control
- validate your callback URLs carefully
- use HTTPS in real deployments
Choosing the right path
- choose session auth when the browser is the main client
- choose JWT auth when the client is a separate API consumer
- choose OAuth when an external identity provider should handle login
- combine them when the user signs in through a provider and your app still needs local session or token state
Where to go next
If you have not built a full feature yet, go back to Building a Feature.
If you want an end-to-end learning path, continue with the tutorial section and build a small app from scratch using the CLI, modules, DTOs, and API docs together.