Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Oauth2 Server Laravel Package

dingo/oauth2-server

Dingo OAuth2 Server adds a full OAuth2 authorization server to Laravel and Dingo API, supporting grant types, scopes, access tokens, and middleware for securing API endpoints. Configurable and easy to integrate.

View on GitHub
Deep Wiki
Context7

Getting Started

Treat this as a legacy integration, not a greenfield choice. The last release was April 2014, the repository is not clearly available, and the package predates modern OAuth guidance (PKCE, OAuth 2.1, OpenID Connect). Use it only when maintaining an existing Laravel 4/early Laravel 5 or Dingo API application, or when you need a small, self-contained OAuth 2.0 token endpoint and accept the maintenance risk.

Minimal steps:

  1. Confirm the package still installs on your PHP version:

    composer show dingo/oauth2-server
    composer require dingo/oauth2-server
    

    Check vendor/dingo/oauth2-server/composer.json for PHP constraints. On PHP 7.2+ you will likely need to patch deprecations or pin an older runtime.

  2. Look first at these areas in vendor/dingo/oauth2-server/src:

    • Server/Authorization — issues tokens.
    • Server/Resource — validates bearer tokens on protected routes.
    • Grant/ — password, client credentials, authorization code, refresh token, implicit.
    • Storage/ — persistence adapters and interfaces.
    • Entity/ — token/client/scope value objects.
    • Exception/ — OAuth error codes and responses.
  3. Pick one first use case: a password grant for a first-party SPA/mobile client, or client credentials for machine-to-machine access. Avoid authorization-code flows until you have verified redirect and state handling.

  4. Bootstrap the authorization server manually if there is no framework bridge you trust:

    use Dingo\OAuth2\Storage\Fluent;
    use Dingo\OAuth2\Server\Authorization;
    use Dingo\OAuth2\Grant\Password;
    
    $storage = new Fluent($db); // existing PDO/Laravel connection
    $server  = new Authorization($storage);
    $server->addGrant(new Password($storage));
    
    // Route this behind POST /oauth/token
    $server->issueAccessToken();
    

    Exact constructor signatures changed across the 2013–2014 releases; confirm against the vendored source before copying examples from old blog posts.

Implementation Patterns

Split authorization and resource servers. Use Server\Authorization only on the token endpoint (POST /oauth/token). Use Server\Resource (or the equivalent bearer-token validator) in middleware on protected API routes. Do not let the resource server issue tokens.

Register only the grants you need. Typical mappings:

Client type Grant
First-party mobile/SPA password + refresh_token
Server-to-server client_credentials
Third-party web app authorization_code + refresh_token
Legacy JS app implicit (avoid for new work)

Register grants explicitly so unsupported grant_type values fail closed.

Use storage adapters as the integration seam. The package expects storage implementations for clients, access tokens, refresh tokens, authorization codes, and scopes. A common pattern is to extend or wrap the included Fluent adapter when using Laravel’s query builder, or implement the storage interfaces against your own schema. Keep a consistent schema:

oauth_clients       (id, secret, name, redirect_uri, scopes)
oauth_access_tokens (token, client_id, user_id, scope, expires_at)
oauth_refresh_tokens(token, client_id, user_id, scope, expires_at)
oauth_codes         (code, client_id, user_id, redirect_uri, scope, expires_at)
oauth_scopes        (id, description)

Wrap token issuance behind a controller. Keep request parsing and response formatting in your application, and let the package handle grant validation and token creation:

public function token()
{
    try {
        return $this->oauthServer->issueAccessToken();
    } catch (\Dingo\OAuth2\Exception\OAuthException $e) {
        return response()->json([
            'error'             => $e->getError(),
            'error_description' => $e->getMessage(),
        ], $e->getStatusCode());
    }
}

Validate bearer tokens in middleware. Parse Authorization: Bearer <token>, reject missing/malformed headers with 401 and WWW-Authenticate: Bearer, then load the token and check expiry and scope. Attach the resolved user/client to the request for downstream authorization.

Scope checks belong in your app. The package can carry scopes, but route-level authorization (“does this token have orders:write?”) is usually application logic. Centralize it in middleware or a policy layer.

Refresh-token rotation. The package can issue refresh tokens, but reuse detection and rotation policy are generally your responsibility. On refresh, invalidate the old refresh token and issue a new pair. Log reuse attempts.

Testing pattern. Seed a client and user, call the token endpoint through an HTTP test, then use the returned bearer token against a protected route. For unit tests, mock the storage interfaces rather than hitting a real database.

Dingo API integration. If the surrounding app uses Dingo API, configure its oauth2 auth provider to point at this package’s resource server. Keep the Dingo API version and this package’s 2014 API aligned; they were designed for the same era and may not work with later Dingo releases.

Gotchas and Tips

  • Abandonment is the primary risk. No security patches, no PKCE, no modern token binding. Plan migration to league/oauth2-server, Laravel Passport, or a hosted identity provider. Do not expose this directly to third-party developers without a security review.
  • No canonical repository. Documentation is whatever is in vendor/dingo/oauth2-server/README.md and the source. Old tutorials frequently show method names that no longer match the final 2014 release.
  • PHP compatibility. The code was written for PHP 5.4/5.5-era projects. Expect dynamic property warnings, deprecated constructors, and possible fatal errors on PHP 8. Pin PHP or patch the vendored package.
  • Request parsing assumptions. OAuth token requests are application/x-www-form-urlencoded. If your client sends JSON, grant_type, client_id, client_secret, and scope may not be read. Test with curl -d, not a JSON body.
  • Client authentication modes. Decide whether credentials go in the request body or HTTP Basic auth. Public clients (SPAs, mobile apps) cannot keep a client_secret; do not issue one and pretend it is secret.
  • Plaintext token storage. Older OAuth servers often store bearer tokens directly. If you can, hash tokens at rest and compare hashes; a database leak otherwise exposes live sessions.
  • Expiry and clock handling. Verify that token expires_at comparisons use the same timezone and that expired tokens return invalid_grant/invalid_token appropriately. Add a small clock-skew allowance only if you understand the trade-off.
  • Scope subset validation. Ensure requested scopes are a subset of the client’s allowed scopes. Empty or omitted scopes often default to “all client scopes”; make that behavior explicit.
  • Error format matters. OAuth clients expect JSON with error and error_description, and token endpoints should return 400/401 rather than generic 500 pages. Catch OAuthException at the boundary.
  • Hardcoded table/column names. The Fluent adapter may assume specific table names. If your schema differs, either create compatibility views or implement a custom storage adapter.
  • Refresh-token reuse. Without reuse detection, a stolen refresh token can be replayed indefinitely. Rotate tokens and revoke the family on reuse.
  • HTTPS only. Bearer tokens and client secrets must never travel over plain HTTP or appear in query strings/logs.
  • Composer conflicts. Do not install this alongside league/oauth2-server or Laravel Passport expecting them to cooperate. Pick one token implementation per application.
  • Debugging checklist. For failed token requests, inspect: grant registration, storage lookup returning null, client secret mismatch, expired/revoked token, scope mismatch, and request content type — in that order. Most “it just returns 401” issues are storage or content-type problems, not cryptographic ones.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
abbasudo/artisan-route
mirvan/ippanel
ignibyte/aic-framework
glavweb/data-schema-bundle
glavweb/datagrid-bundle
tacticmedia/scim-server
uni-method/frame
neika-ai/sdk
adachsoft/php-code-style
pharaonic/laravel-notification-dependencies
beautinow/translug
dev-brainiac/bot-cloaked
octoberrain/html
octoberrain/extension
octoberrain/exception
octoberrain/contracts
adachsoft/api-version-bundle
cgv/localized-resource
noith/settings
kda/laravel-package