joselfonseca/lighthouse-graphql-passport-auth
Adds Laravel Passport authentication to Lighthouse GraphQL APIs, with register, login, refresh, logout, and current-user mutations plus configurable guards and token handling for securing GraphQL endpoints.
11.0.0 exists solely to add Passport 13 support, and Passport 13 requires Laravel 11+ / PHP 8.2+. If you're still on Laravel 10 or Passport 12, pin to ^10.0 — this is a hard constraint change, not a feature bump.composer require joselfonseca/lighthouse-graphql-passport-auth and make sure Passport itself is set up first: php artisan passport:install, HasApiTokens on your User model, and an api guard with driver => passport in config/auth.php.config/lighthouse-graphql-passport.php) and import the package schema into your Lighthouse schema (#import the auth.graphql file, or pull it into your lighthouse.php schema path) so the login, register, refreshToken, logout, forgotPassword, resetPassword and social-login mutations appear.php artisan passport:client --password) and put its ID/secret into the password_grant_client section of the config, or drive them from env.login → return access_token + refresh_token, use the access token as a Bearer header, then protect a me query with @guard(with: ["api"]) and @currentUser. That single flow validates guard config, client credentials, and schema import in one pass.resolvers map in the config lets you swap any mutation's resolver for your own class without forking the package. Extend the base resolver and override resolve() to add claims, MFA checks, audit logging, or custom response fields.auth.graphql into your own schema directory and import yours instead. This is the cleanest way to add fields to the AuthResponse/RegisterResponse types or add directives like @throttle to login/forgot-password.refreshToken, login, register, forgotPassword, resetPassword and social login must stay unguarded. Everything else (me, logout, logoutAll, updatePassword) belongs behind @guard. Keep this split explicit in your schema file so a future schema merge doesn't accidentally expose or lock a mutation.provider + access_token; the resolver validates it server-side. Keep this separate from the password flow in your front-end state machine — the token shapes differ.RegisterResolver for simple cases, listen for the registration event / use a model observer on user creation to send welcome mails, assign roles, or seed profiles.Passport::actingAs($user) for guarded queries and Lighthouse's $this->graphQL(...) helper for unguarded ones. Assert on errors[0].message for failure paths — authentication failures come back as GraphQL errors, not null data.Passport::tokensExpireIn() / refreshTokensExpireIn() in your AuthServiceProvider; the short access token + long refresh token pair is the intended model here.lighthouse-graphql-passport.php, diff it against the new stub — config keys have moved between majors before, and a stale cached config silently keeps old resolver bindings.php artisan config:cache is mandatory after changing them — and config:clear is the first thing to try when login returns "invalid client".@throttle to login, forgotPassword and resetPassword or implement it in a custom resolver. An unthrottled login mutation is a credential-stuffing target.MustVerifyEmail on the user model; without it the verifyEmail mutation silently does nothing useful.Passport::tokensCan/scope logging and check oauth_clients — a grant type missing on the client (especially refresh_token) produces confusing errors far from the actual cause.How can I help you explore Laravel packages today?