Authentication and OAuth In Depth

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:

  1. begin login
  2. 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.