Laravel Sanctum support for Laravel Lighthouse

Overview

Lighthouse Sanctum

Software License GitHub Tests Action Status Coverage Status PHPStan Latest Version on Packagist Total Downloads

Add Laravel Sanctum support to Lighthouse

Requirements

Installation

1. Install using composer:

composer require daniel-de-wit/lighthouse-sanctum

2. Publish configuration and schema

php artisan vendor:publish --tag=lighthouse-sanctum

3. Import the published schema into your main GraphQL schema (./graphql/schema.graphql)

type Query
type Mutation

#import sanctum.grapqhl

4. HasApiTokens

Apply the Laravel\Sanctum\HasApiTokens trait to your Authenticatable model as described in the Laravel Sanctum documentation.

use Illuminate\Auth\Authenticatable;
use Laravel\Sanctum\Contracts\HasApiTokens as HasApiTokensContract;
use Laravel\Sanctum\HasApiTokens;

class User extends Authenticatable implements HasApiTokensContract
{
    use HasApiTokens;
}

5. Configuration

This package relies on API Token Authentication, which uses stateless Bearer tokens to authenticate requests.

By default, Laravel Sanctum assumes that requests made from localhost should use the stateful Spa Authentication instead. To disable this behaviour, remove any lines in your sanctum configuration:

// File: ./config/sanctum.php

    /*
    |--------------------------------------------------------------------------
    | Stateful Domains
    |--------------------------------------------------------------------------
    |
    | Requests from the following domains / hosts will receive stateful API
    | authentication cookies. Typically, these should include your local
    | and production domains which access your API via a frontend SPA.
    |
    */

    'stateful' => [
        // Remove entries here    
    ],

Make sure the following middleware is enabled for Lighthouse:

// File: ./config/lighthouse.php
    'middleware' => [
        ...
        
        \Nuwave\Lighthouse\Support\Http\Middleware\AttemptAuthentication::class,

        ...
    ],

Usage

Login

Authenticate the user to receive a Bearer token.

mutation Login {
    login(input: {
        email: "[email protected]"
        password: "secret"
    }) {
        token
    }
}

Apply the Authorization header on subsequent calls using the token

  "Authorization": "Bearer 1|lJo1cMhrW9tIUuGwlV1EPjKnvfZKzvgpGgplbwX9"

Logout

Revoke the current token.

mutation Logout {
    logout {
        status
        message
    }
}

Register

Successfully registering a user will immediately yield a bearer token (unless email verification is required).

mutation Register {
    register(input: {
        name: "John Doe"
        email: "[email protected]"
        password: "secret"
        password_confirmation: "secret"
    }) {
        token
        status
    }
}

☝️ Want to disable password confirmation? Update your schema

When registering a user in combination with the MustVerifyEmail contract you can optionally define the url for email verification. Both __ID__ and __HASH__ will be replaced with the proper values.

mutation Register {
    register(input: {
        name: "John Doe"
        email: "[email protected]"
        password: "secret"
        password_confirmation: "secret"
        verification_url: {
            url: "https://my-front-end.com/verify-email?id=__ID__&token=__HASH__"
        }
    }) {
        token
        status
    }
}

Email Verification

mutation VerifyEmail {
  verifyEmail(input: {
    id: "1"
    hash: "af269947ed80d4a7bc3f78a6dfd05ec369373f9d"
  }) {
    name
    email
  }
}

Forgot Password

Sends a reset password notification.

Optionally use custom reset url using both __EMAIL__ and __TOKEN__ placeholders.

mutation ForgotPassword {
    forgotPassword(input: {
        email: "[email protected]"
        reset_password_url: {
            url: "https://my-front-end.com/reset-password?email=__EMAIL__&token=__TOKEN__"
        }
    }) {
        status
        message
    }
}

Reset Password

Reset the user's password.

mutation ResetPassword {
    resetPassword(input: {
        email: "[email protected]",
        token: "af269947ed80d4a7bc3f78a6dfd05ec369373f9d"
        password: "secret"
        password_confirmation: "secret"
    }) {
        status
        message
    }
}

☝️ Want to disable password confirmation? Update your schema

Testing

composer test

Coverage

composer coverage

Static Analysis

composer analyze

Contributing

Please see CONTRIBUTING for details.

Credits

License

The MIT License (MIT). Please see License File for more information.

Comments
  • Wrong config value usage; fixes #80

    Wrong config value usage; fixes #80

    Changes the files edited in PR #77 that make use of lighthouse-sanctum.identification.user_identifier_field_name to use lighthouse-sanctum.user_identifier_field_name instead (as per readme + config file)

    Fixes #80

    opened by xorinzor 4
  • Improve email verification token security?

    Improve email verification token security?

    Is this secure enough? https://github.com/daniel-de-wit/lighthouse-sanctum/blob/c1d5e7a6497c68fb33f8f75723a45f2c29b98070/src/Services/EmailVerificationService.php#L41

    question 
    opened by wimski 4
  • Fix phpstan issues

    Fix phpstan issues

    By checking for callable removed the need to ignore phpstan.

    Lowering phpstan to level 8 reduces the need for the custom phpstan ignore rule:

    '#Parameter \#1 \$(function|callback) of function call_user_func expects callable\(\): mixed, Closure\|null given\.#'
    

    Level 9 is unnecessarily strict, it will never allow anything other than mixed to be passed.

    1. be strict about the mixed type - the only allowed operation you can do with it is to pass it to another mixed
    opened by daniel-de-wit 3
  • Option to change email to username

    Option to change email to username

    In my application I use a username/password combination rather then email/password.

    I updated the sanctum.graphql login mutation to accept a username parameter instead of email, but it turns out the PHP controller always assumes an email.

    It'd be great if this would either be configurable, or would accept both and select which one to use based on which is provided.

    opened by xorinzor 2
  • VerificationUrlInput wrong in README

    VerificationUrlInput wrong in README

    The following example in the register section of the readme has incorrectly named hash parameters. It says token instead of hash.

    mutation {
        register(input: {
            name: "John Doe"
            email: "[email protected]"
            password: "secret"
            password_confirmation: "secret"
            verification_url: {
                url: "https://my-front-end.com/verify-email?id=__ID__&token=__HASH__"
    # Signed:   url: "https://my-front-end.com/verify-email?id=__ID__&token=__HASH__&expires=__EXPIRES__&signature=__SIGNATURE__"
            }
        }) {
            token
            status
        }
    }
    
    documentation 
    opened by wimski 2
  • Multiple users providers ?

    Multiple users providers ?

    Hello , when i modify the lighthouse-sanctum.provider variable to an array of providers an error appears:

      "errors": [
        {
          "debugMessage": "Array to string conversion",
          "message": "Internal server error",
          "extensions": {
            "category": "internal"
          },
          "locations": [
            {
              "line": 2,
              "column": 5
            }
          ],
          "path": [
            "login"
          ],
          "trace": [
            {
              "file": "/var/www/html/api/vendor/laravel/framework/src/Illuminate/Auth/CreatesUserProviders.php",
              "line": 57,
              "call": "Illuminate\\Foundation\\Bootstrap\\HandleExceptions::handleError(2, 'Array to string conversion', '/var/www/html/api/vendor/laravel/framework/src/Illuminate/Auth/CreatesUserProviders.php', 57)"
            },
            {
              "file": "/var/www/html/api/vendor/laravel/framework/src/Illuminate/Auth/CreatesUserProviders.php",
              "line": 26,
              "call": "Illuminate\\Auth\\AuthManager::getProviderConfiguration(array(2))"
            },
            {
              "file": "/var/www/html/api/vendor/daniel-de-wit/lighthouse-sanctum/src/Traits/CreatesUserProvider.php",
              "line": 21,
              "call": "Illuminate\\Auth\\AuthManager::createUserProvider(array(2))"
            },
            {
              "file": "/var/www/html/api/vendor/daniel-de-wit/lighthouse-sanctum/src/GraphQL/Mutations/Login.php",
              "line": 34,
              "call": "DanielDeWit\\LighthouseSanctum\\GraphQL\\Mutations\\Login::createUserProvider()"
            },
            {
              "file": "/var/www/html/api/vendor/nuwave/lighthouse/src/Schema/Directives/FieldDirective.php",
              "line": 51,
              "call": "DanielDeWit\\LighthouseSanctum\\GraphQL\\Mutations\\Login::__invoke(null, array(4), instance of Nuwave\\Lighthouse\\Schema\\Context, instance of GraphQL\\Type\\Definition\\ResolveInfo)"
            },
            {
              "file": "/var/www/html/api/vendor/nuwave/lighthouse/src/Schema/Directives/RenameArgsDirective.php",
              "line": 33,
              "call": "Nuwave\\Lighthouse\\Schema\\Directives\\FieldDirective::Nuwave\\Lighthouse\\Schema\\Directives\\{closure}(null, array(3), instance of Nuwave\\Lighthouse\\Schema\\Context, instance of GraphQL\\Type\\Definition\\ResolveInfo)"
            },
            {
              "file": "/var/www/html/api/vendor/nuwave/lighthouse/src/Schema/Directives/SpreadDirective.php",
              "line": 34,
              "call": "Nuwave\\Lighthouse\\Schema\\Directives\\RenameArgsDirective::Nuwave\\Lighthouse\\Schema\\Directives\\{closure}(null, array(3), instance of Nuwave\\Lighthouse\\Schema\\Context, instance of GraphQL\\Type\\Definition\\ResolveInfo)"
            },
            {
              "file": "/var/www/html/api/vendor/nuwave/lighthouse/src/Schema/Directives/ArgTraversalDirective.php",
              "line": 29,
              "call": "Nuwave\\Lighthouse\\Schema\\Directives\\SpreadDirective::Nuwave\\Lighthouse\\Schema\\Directives\\{closure}(null, array(1), instance of Nuwave\\Lighthouse\\Schema\\Context, instance of GraphQL\\Type\\Definition\\ResolveInfo)"
            },
            {
              "file": "/var/www/html/api/vendor/nuwave/lighthouse/src/Validation/ValidateDirective.php",
              "line": 53,
              "call": "Nuwave\\Lighthouse\\Schema\\Directives\\ArgTraversalDirective::Nuwave\\Lighthouse\\Schema\\Directives\\{closure}(null, array(1), instance of Nuwave\\Lighthouse\\Schema\\Context, instance of GraphQL\\Type\\Definition\\ResolveInfo)"
            },
            {
              "file": "/var/www/html/api/vendor/nuwave/lighthouse/src/Schema/Directives/ArgTraversalDirective.php",
              "line": 29,
              "call": "Nuwave\\Lighthouse\\Validation\\ValidateDirective::Nuwave\\Lighthouse\\Validation\\{closure}(null, array(1), instance of Nuwave\\Lighthouse\\Schema\\Context, instance of GraphQL\\Type\\Definition\\ResolveInfo)"
            },
            {
              "file": "/var/www/html/api/vendor/nuwave/lighthouse/src/Schema/Directives/TrimDirective.php",
              "line": 56,
              "call": "Nuwave\\Lighthouse\\Schema\\Directives\\ArgTraversalDirective::Nuwave\\Lighthouse\\Schema\\Directives\\{closure}(null, array(1), instance of Nuwave\\Lighthouse\\Schema\\Context, instance of GraphQL\\Type\\Definition\\ResolveInfo)"
            },
            {
              "file": "/var/www/html/api/vendor/nuwave/lighthouse/src/Schema/Factories/FieldFactory.php",
              "line": 92,
              "call": "Nuwave\\Lighthouse\\Schema\\Directives\\TrimDirective::Nuwave\\Lighthouse\\Schema\\Directives\\{closure}(null, array(1), instance of Nuwave\\Lighthouse\\Schema\\Context, instance of GraphQL\\Type\\Definition\\ResolveInfo)"
            },
            {
              "file": "/var/www/html/api/vendor/webonyx/graphql-php/src/Executor/ReferenceExecutor.php",
              "line": 623,
              "call": "Nuwave\\Lighthouse\\Schema\\Factories\\FieldFactory::Nuwave\\Lighthouse\\Schema\\Factories\\{closure}(null, array(1), instance of Nuwave\\Lighthouse\\Schema\\Context, instance of GraphQL\\Type\\Definition\\ResolveInfo)"
            },
            {
              "file": "/var/www/html/api/vendor/webonyx/graphql-php/src/Executor/ReferenceExecutor.php",
              "line": 550,
              "call": "GraphQL\\Executor\\ReferenceExecutor::resolveFieldValueOrError(instance of GraphQL\\Type\\Definition\\FieldDefinition, instance of GraphQL\\Language\\AST\\FieldNode, instance of Closure, null, instance of GraphQL\\Type\\Definition\\ResolveInfo)"
            },
            {
              "file": "/var/www/html/api/vendor/webonyx/graphql-php/src/Executor/ReferenceExecutor.php",
              "line": 474,
              "call": "GraphQL\\Executor\\ReferenceExecutor::resolveField(GraphQLType: Mutation, null, instance of ArrayObject(1), array(1))"
            },
            {
              "file": "/var/www/html/api/vendor/webonyx/graphql-php/src/Executor/ReferenceExecutor.php",
              "line": 857,
              "call": "GraphQL\\Executor\\ReferenceExecutor::GraphQL\\Executor\\{closure}(array(0), 'login')"
            },
            {
              "call": "GraphQL\\Executor\\ReferenceExecutor::GraphQL\\Executor\\{closure}(array(0), 'login')"
            },
            {
              "file": "/var/www/html/api/vendor/webonyx/graphql-php/src/Executor/ReferenceExecutor.php",
              "line": 859,
              "function": "array_reduce(array(1), instance of Closure, array(0))"
            },
            {
              "file": "/var/www/html/api/vendor/webonyx/graphql-php/src/Executor/ReferenceExecutor.php",
              "line": 490,
              "call": "GraphQL\\Executor\\ReferenceExecutor::promiseReduce(array(1), instance of Closure, array(0))"
            },
            {
              "file": "/var/www/html/api/vendor/webonyx/graphql-php/src/Executor/ReferenceExecutor.php",
              "line": 263,
              "call": "GraphQL\\Executor\\ReferenceExecutor::executeFieldsSerially(GraphQLType: Mutation, null, array(0), instance of ArrayObject(1))"
            },
            {
              "file": "/var/www/html/api/vendor/webonyx/graphql-php/src/Executor/ReferenceExecutor.php",
              "line": 215,
              "call": "GraphQL\\Executor\\ReferenceExecutor::executeOperation(instance of GraphQL\\Language\\AST\\OperationDefinitionNode, null)"
            },
            {
              "file": "/var/www/html/api/vendor/webonyx/graphql-php/src/Executor/Executor.php",
              "line": 156,
              "call": "GraphQL\\Executor\\ReferenceExecutor::doExecute()"
            },
            {
              "file": "/var/www/html/api/vendor/webonyx/graphql-php/src/GraphQL.php",
              "line": 162,
              "call": "GraphQL\\Executor\\Executor::promiseToExecute(instance of GraphQL\\Executor\\Promise\\Adapter\\SyncPromiseAdapter, instance of GraphQL\\Type\\Schema, instance of GraphQL\\Language\\AST\\DocumentNode, null, instance of Nuwave\\Lighthouse\\Schema\\Context, array(0), null, null)"
            },
            {
              "file": "/var/www/html/api/vendor/webonyx/graphql-php/src/GraphQL.php",
              "line": 94,
              "call": "GraphQL\\GraphQL::promiseToExecute(instance of GraphQL\\Executor\\Promise\\Adapter\\SyncPromiseAdapter, instance of GraphQL\\Type\\Schema, instance of GraphQL\\Language\\AST\\DocumentNode, null, instance of Nuwave\\Lighthouse\\Schema\\Context, array(0), null, null, array(29))"
            },
            {
              "file": "/var/www/html/api/vendor/nuwave/lighthouse/src/GraphQL.php",
              "line": 213,
              "call": "GraphQL\\GraphQL::executeQuery(instance of GraphQL\\Type\\Schema, instance of GraphQL\\Language\\AST\\DocumentNode, null, instance of Nuwave\\Lighthouse\\Schema\\Context, array(0), null, null, array(29))"
            },
            {
              "file": "/var/www/html/api/vendor/nuwave/lighthouse/src/GraphQL.php",
              "line": 164,
              "call": "Nuwave\\Lighthouse\\GraphQL::executeQuery(instance of GraphQL\\Language\\AST\\DocumentNode, instance of Nuwave\\Lighthouse\\Schema\\Context, array(0), null, null)"
            },
            {
              "file": "/var/www/html/api/vendor/nuwave/lighthouse/src/GraphQL.php",
              "line": 118,
              "call": "Nuwave\\Lighthouse\\GraphQL::executeOperation(instance of GraphQL\\Server\\OperationParams, instance of Nuwave\\Lighthouse\\Schema\\Context)"
            },
            {
              "file": "/var/www/html/api/vendor/nuwave/lighthouse/src/Support/Utils.php",
              "line": 98,
              "call": "Nuwave\\Lighthouse\\GraphQL::Nuwave\\Lighthouse\\{closure}(instance of GraphQL\\Server\\OperationParams)"
            },
            {
              "file": "/var/www/html/api/vendor/nuwave/lighthouse/src/GraphQL.php",
              "line": 117,
              "call": "Nuwave\\Lighthouse\\Support\\Utils::applyEach(instance of Closure, instance of GraphQL\\Server\\OperationParams)"
            },
            {
              "file": "/var/www/html/api/vendor/nuwave/lighthouse/src/Support/Http/Controllers/GraphQLController.php",
              "line": 32,
              "call": "Nuwave\\Lighthouse\\GraphQL::executeOperationOrOperations(instance of GraphQL\\Server\\OperationParams, instance of Nuwave\\Lighthouse\\Schema\\Context)"
            },
            {
              "file": "/var/www/html/api/vendor/laravel/framework/src/Illuminate/Routing/ControllerDispatcher.php",
              "line": 48,
              "call": "Nuwave\\Lighthouse\\Support\\Http\\Controllers\\GraphQLController::__invoke(instance of Illuminate\\Http\\Request, instance of Nuwave\\Lighthouse\\GraphQL, instance of Illuminate\\Events\\Dispatcher, instance of Laragraph\\Utils\\RequestParser, instance of Nuwave\\Lighthouse\\Execution\\SingleResponse, instance of Nuwave\\Lighthouse\\Execution\\ContextFactory)"
            },
            {
              "file": "/var/www/html/api/vendor/laravel/framework/src/Illuminate/Routing/Route.php",
              "line": 261,
              "call": "Illuminate\\Routing\\ControllerDispatcher::dispatch(instance of Illuminate\\Routing\\Route, instance of Nuwave\\Lighthouse\\Support\\Http\\Controllers\\GraphQLController, '__invoke')"
            },
            {
              "file": "/var/www/html/api/vendor/laravel/framework/src/Illuminate/Routing/Route.php",
              "line": 204,
              "call": "Illuminate\\Routing\\Route::runController()"
            },
            {
              "file": "/var/www/html/api/vendor/laravel/framework/src/Illuminate/Routing/Router.php",
              "line": 695,
              "call": "Illuminate\\Routing\\Route::run()"
            },
            {
              "file": "/var/www/html/api/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php",
              "line": 128,
              "call": "Illuminate\\Routing\\Router::Illuminate\\Routing\\{closure}(instance of Illuminate\\Http\\Request)"
            },
            {
              "file": "/var/www/html/api/vendor/nuwave/lighthouse/src/Support/Http/Middleware/AttemptAuthentication.php",
              "line": 33,
              "call": "Illuminate\\Pipeline\\Pipeline::Illuminate\\Pipeline\\{closure}(instance of Illuminate\\Http\\Request)"
            },
            {
              "file": "/var/www/html/api/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php",
              "line": 167,
              "call": "Nuwave\\Lighthouse\\Support\\Http\\Middleware\\AttemptAuthentication::handle(instance of Illuminate\\Http\\Request, instance of Closure)"
            },
            {
              "file": "/var/www/html/api/vendor/nuwave/lighthouse/src/Support/Http/Middleware/AcceptJson.php",
              "line": 27,
              "call": "Illuminate\\Pipeline\\Pipeline::Illuminate\\Pipeline\\{closure}(instance of Illuminate\\Http\\Request)"
            },
            {
              "file": "/var/www/html/api/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php",
              "line": 167,
              "call": "Nuwave\\Lighthouse\\Support\\Http\\Middleware\\AcceptJson::handle(instance of Illuminate\\Http\\Request, instance of Closure)"
            },
            {
              "file": "/var/www/html/api/vendor/laravel/sanctum/src/Http/Middleware/EnsureFrontendRequestsAreStateful.php",
              "line": 33,
              "call": "Illuminate\\Pipeline\\Pipeline::Illuminate\\Pipeline\\{closure}(instance of Illuminate\\Http\\Request)"
            },
            {
              "file": "/var/www/html/api/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php",
              "line": 128,
              "call": "Laravel\\Sanctum\\Http\\Middleware\\EnsureFrontendRequestsAreStateful::Laravel\\Sanctum\\Http\\Middleware\\{closure}(instance of Illuminate\\Http\\Request)"
            },
            {
              "file": "/var/www/html/api/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php",
              "line": 103,
              "call": "Illuminate\\Pipeline\\Pipeline::Illuminate\\Pipeline\\{closure}(instance of Illuminate\\Http\\Request)"
            },
            {
              "file": "/var/www/html/api/vendor/laravel/sanctum/src/Http/Middleware/EnsureFrontendRequestsAreStateful.php",
              "line": 34,
              "call": "Illuminate\\Pipeline\\Pipeline::then(instance of Closure)"
            },
            {
              "file": "/var/www/html/api/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php",
              "line": 167,
              "call": "Laravel\\Sanctum\\Http\\Middleware\\EnsureFrontendRequestsAreStateful::handle(instance of Illuminate\\Http\\Request, instance of Closure)"
            },
            {
              "file": "/var/www/html/api/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php",
              "line": 103,
              "call": "Illuminate\\Pipeline\\Pipeline::Illuminate\\Pipeline\\{closure}(instance of Illuminate\\Http\\Request)"
            },
            {
              "file": "/var/www/html/api/vendor/laravel/framework/src/Illuminate/Routing/Router.php",
              "line": 697,
              "call": "Illuminate\\Pipeline\\Pipeline::then(instance of Closure)"
            },
            {
              "file": "/var/www/html/api/vendor/laravel/framework/src/Illuminate/Routing/Router.php",
              "line": 672,
              "call": "Illuminate\\Routing\\Router::runRouteWithinStack(instance of Illuminate\\Routing\\Route, instance of Illuminate\\Http\\Request)"
            },
            {
              "file": "/var/www/html/api/vendor/laravel/framework/src/Illuminate/Routing/Router.php",
              "line": 636,
              "call": "Illuminate\\Routing\\Router::runRoute(instance of Illuminate\\Http\\Request, instance of Illuminate\\Routing\\Route)"
            },
            {
              "file": "/var/www/html/api/vendor/laravel/framework/src/Illuminate/Routing/Router.php",
              "line": 625,
              "call": "Illuminate\\Routing\\Router::dispatchToRoute(instance of Illuminate\\Http\\Request)"
            },
            {
              "file": "/var/www/html/api/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php",
              "line": 166,
              "call": "Illuminate\\Routing\\Router::dispatch(instance of Illuminate\\Http\\Request)"
            },
            {
              "file": "/var/www/html/api/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php",
              "line": 128,
              "call": "Illuminate\\Foundation\\Http\\Kernel::Illuminate\\Foundation\\Http\\{closure}(instance of Illuminate\\Http\\Request)"
            },
            {
              "file": "/var/www/html/api/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/TransformsRequest.php",
              "line": 21,
              "call": "Illuminate\\Pipeline\\Pipeline::Illuminate\\Pipeline\\{closure}(instance of Illuminate\\Http\\Request)"
            },
            {
              "file": "/var/www/html/api/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/ConvertEmptyStringsToNull.php",
              "line": 31,
              "call": "Illuminate\\Foundation\\Http\\Middleware\\TransformsRequest::handle(instance of Illuminate\\Http\\Request, instance of Closure)"
            },
            {
              "file": "/var/www/html/api/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php",
              "line": 167,
              "call": "Illuminate\\Foundation\\Http\\Middleware\\ConvertEmptyStringsToNull::handle(instance of Illuminate\\Http\\Request, instance of Closure)"
            },
            {
              "file": "/var/www/html/api/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/TransformsRequest.php",
              "line": 21,
              "call": "Illuminate\\Pipeline\\Pipeline::Illuminate\\Pipeline\\{closure}(instance of Illuminate\\Http\\Request)"
            },
            {
              "file": "/var/www/html/api/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/TrimStrings.php",
              "line": 40,
              "call": "Illuminate\\Foundation\\Http\\Middleware\\TransformsRequest::handle(instance of Illuminate\\Http\\Request, instance of Closure)"
            },
            {
              "file": "/var/www/html/api/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php",
              "line": 167,
              "call": "Illuminate\\Foundation\\Http\\Middleware\\TrimStrings::handle(instance of Illuminate\\Http\\Request, instance of Closure)"
            },
            {
              "file": "/var/www/html/api/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/ValidatePostSize.php",
              "line": 27,
              "call": "Illuminate\\Pipeline\\Pipeline::Illuminate\\Pipeline\\{closure}(instance of Illuminate\\Http\\Request)"
            },
            {
              "file": "/var/www/html/api/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php",
              "line": 167,
              "call": "Illuminate\\Foundation\\Http\\Middleware\\ValidatePostSize::handle(instance of Illuminate\\Http\\Request, instance of Closure)"
            },
            {
              "file": "/var/www/html/api/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/PreventRequestsDuringMaintenance.php",
              "line": 86,
              "call": "Illuminate\\Pipeline\\Pipeline::Illuminate\\Pipeline\\{closure}(instance of Illuminate\\Http\\Request)"
            },
            {
              "file": "/var/www/html/api/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php",
              "line": 167,
              "call": "Illuminate\\Foundation\\Http\\Middleware\\PreventRequestsDuringMaintenance::handle(instance of Illuminate\\Http\\Request, instance of Closure)"
            },
            {
              "file": "/var/www/html/api/vendor/fruitcake/laravel-cors/src/HandleCors.php",
              "line": 52,
              "call": "Illuminate\\Pipeline\\Pipeline::Illuminate\\Pipeline\\{closure}(instance of Illuminate\\Http\\Request)"
            },
            {
              "file": "/var/www/html/api/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php",
              "line": 167,
              "call": "Fruitcake\\Cors\\HandleCors::handle(instance of Illuminate\\Http\\Request, instance of Closure)"
            },
            {
              "file": "/var/www/html/api/vendor/fideloper/proxy/src/TrustProxies.php",
              "line": 57,
              "call": "Illuminate\\Pipeline\\Pipeline::Illuminate\\Pipeline\\{closure}(instance of Illuminate\\Http\\Request)"
            },
            {
              "file": "/var/www/html/api/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php",
              "line": 167,
              "call": "Fideloper\\Proxy\\TrustProxies::handle(instance of Illuminate\\Http\\Request, instance of Closure)"
            },
            {
              "file": "/var/www/html/api/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php",
              "line": 103,
              "call": "Illuminate\\Pipeline\\Pipeline::Illuminate\\Pipeline\\{closure}(instance of Illuminate\\Http\\Request)"
            },
            {
              "file": "/var/www/html/api/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php",
              "line": 141,
              "call": "Illuminate\\Pipeline\\Pipeline::then(instance of Closure)"
            },
            {
              "file": "/var/www/html/api/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php",
              "line": 110,
              "call": "Illuminate\\Foundation\\Http\\Kernel::sendRequestThroughRouter(instance of Illuminate\\Http\\Request)"
            },
            {
              "file": "/var/www/html/api/public/index.php",
              "line": 52,
              "call": "Illuminate\\Foundation\\Http\\Kernel::handle(instance of Illuminate\\Http\\Request)"
            }
          ]
        }
      ]
    }
    
    opened by LAGGOUNE-Walid 2
  • Fix tests that fail because validation error message changes in laravel/laravel 8.5.21

    Fix tests that fail because validation error message changes in laravel/laravel 8.5.21

    When checking out this package and running the tests, some assertions on URL validity error messages fail, if the installed version of orchestra/testbench-core is equal or higher than ^v6.23.1, because of this change: https://github.com/orchestral/testbench-core/commit/f189915445275e511ae12cef356246bee8faca6f

    Or the laravel/laravel equivalent: https://github.com/laravel/laravel/commit/866589128430c55385cb13ddae0061c628245be2

    To fix this, I have added a more explicit requirement for orchestra/testbench-core in the composer.json file. This is, unfortunately, a breaking change.

    opened by dennis-koster 2
  • Define all input validation consistently in the schema

    Define all input validation consistently in the schema

    The following situations occurred regarding input validation:

    • Some input only depended on schema restrictions (e.g. field: String!).
    • Some input used the @rules directive in the schema.
    • Some input used a validator in the mutation.

    This PR remedies that by:

    • Only using the @rules directive in the schema thereby centralizing all validation definitions.
    • Validating all input fields regardless of schema restrictions, so any mutation can always assume that the expected input is present and valid.
    opened by wimski 2
  • Problem with PR #77

    Problem with PR #77

    I discovered an issue in your PR #77 .

    The GraphQL/Mutations/Login controller on line 40 tries to look at a value of lighthouse-sanctum.identification.user_identifier_field_name.

    But both your config and readme use lighthouse-sanctum.user_identifier_field_name instead

    opened by xorinzor 1
  • Ability to customize credential keys e.g: email/username

    Ability to customize credential keys e.g: email/username

    Closes #76

    A new section is added to config/lighthouse-sanctum.php which allows for custom user identification field to be used when authenticating.

    For example, using username instead of the default email.

    /*
    |--------------------------------------------------------------------------
    | Identification
    |--------------------------------------------------------------------------
    |
    | Configure the credential fields by which the user will be identified.
    | Default: email
    */
    
    'user_identifier_field_name' => 'username',
    

    Update the GraphQL schema accordingly

    input LoginInput {
        username: String! @rules(apply: ["required"])
    }
    
    opened by daniel-de-wit 1
  • session does not seem to work for logged in graphql user

    session does not seem to work for logged in graphql user

    Wanting to store stuff in session and get it out again in custom mutators/resolvers..

    But it seems like every time I read the session data it is not set. How can I enable laravel sessions for the token?

    opened by LiamKarlMitchell 1
  • Expires_at not supported

    Expires_at not supported

    the expires_at field will not be set according to the sactum config-file right now. Right now this proptery is also missing from the HasApiTokensContract (https://github.com/laravel/sanctum/pull/402).

    opened by simbig 0
  • Provide Localization and customization

    Provide Localization and customization

    Localization and customization

    This PR provides translations for exceptions and messages that were static in the current version of lighthouse-sanctum. These files can be published with a seperate tag, which allows users to customize the exceptions and add more translations for their project. This is also mentioned in the readme.

    php artisan vendor:publish --tag=lighthouse-sanctum-translations
    

    This PR introduces new optional behavior and according to the tests no breaking changes, because of this I would suggest a minor version upgrade.

    Squashed commit messages

    • provide localization files and replace fixed messages with references to these files
    • replace fixed messages in Traits + adapt unit tests
    • adapt integration tests
    • allow to publish translations seperately
    • phpcs and unit test fixes
    • add documentation for localization publish
    opened by ArneLibbrecht 3
  • Replace snake case with camel case in field names

    Replace snake case with camel case in field names

    The only real issue with this are the password_confirmation fields, which can't easily be replaced with camel case because of the internal magic of the rule.

    enhancement 
    opened by wimski 0
Releases(2.2.0)
Owner
Daniël de Wit
Daniël de Wit
Laravel Sanctum, Websockets & Vue [SPA]

Laravel Auth [SPA] 2021-07-15_22-24-33.mp4 composer require laravel/ui php artisan ui:auth Laravel Sanctum composer require laravel/sanctum php art

Kritish Dhaubanjar 6 Jun 1, 2022
A Laravel 8 Project Implement with GraphQL With Sanctum APIs Authentications Which utilized in Any Frontend or Any Mobile Application Programs.

A Laravel 8 Project Implement with GraphQL With Sanctum APIs Authentications Which utilized in Any Frontend or Any Mobile Application Programs.

Vikas Ukani 3 Jan 6, 2022
API para Autenticación desarrollada con Laravel 8 y Sanctum

About Laravel Laravel is a web application framework with expressive, elegant syntax. We believe development must be an enjoyable and creative experie

Informática DP 3 Dec 9, 2021
Authentication for SPA (Laravel Sanctum + Vue.js)

About Laravel Laravel is a web application framework with expressive, elegant syntax. We believe development must be an enjoyable and creative experie

Damir 0 Dec 30, 2021
A package that uses blade templates to control how markdown is converted to HTML inside Laravel, as well as providing support for markdown files to Laravel views.

Install Install via composer. $ composer require olliecodes/laravel-etched-blade Once installed you'll want to publish the config. $ php artisan vendo

Ollie Codes 19 Jul 5, 2021
Laravel package to generate and to validate a UUID according to the RFC 4122 standard. Only support for version 1, 3, 4 and 5 UUID are built-in.

Laravel Uuid Laravel package to generate and to validate a universally unique identifier (UUID) according to the RFC 4122 standard. Support for versio

Christoph Kempen 1.7k Dec 28, 2022
Dead simple Laravel backend support for FilePond js.

Laravel FilePond Backend This package provides a straight forward backend support for Laravel application to work with FilePond file upload javascript

rahulhaque 64 Jan 3, 2023
📦 Adds Laravel Packages Support to Lumen and Vendor Publish Artisan Command.

Laravel Package Support for Lumen: Makes Lumen compatible with Laravel Packages. You can use any Laravel Packages in Lumen by installing Larasupport Package.

Irfaq Syed 127 Dec 17, 2022
CORS (Cross-Origin Resource Sharing) support for Laravel and Lumen

Description This package adds Cross-Origin Resource Sharing (CORS) support to your Laravel application. The package is based on Framework agnostic (PS

null 48 Feb 1, 2020
Multi theme support for Laravel application

Multi theme support for Laravel application This Laravel package adds multi-theme support to your application. It also provides a simple authenticatio

QiroLab 287 Dec 29, 2022
Reactive Form Builder for Vue.js with Laravel Support

Dynamic Form Builder for Laravel with Vue.js Create even the most complex forms with ease, using two-sided validation, eloquent, nested elements, cond

Laraform 340 Dec 31, 2022
This package provides extended support for our spatie/enum package in Laravel.

Laravel support for spatie/enum This package provides extended support for our spatie/enum package in Laravel. Installation You can install the packag

Spatie 264 Dec 23, 2022
Use eloquent joins in Laravel way, with composite key support.

Eloquent Power Joins with Compoships Support This package is an Eloquent Power Joins extension to support Compoships. You can now use joins in Laravel

Kit Loong 13 Dec 23, 2022
View themes is a simple package to provide themed view support to Laravel.

Laravel View Themes View themes is a simple package to provide themed view support to Laravel. Installation Add alexwhitman/view-themes to the require

Alex Whitman 15 Nov 29, 2022
Tag support for Laravel Eloquent models - Taggable Trait

Laravel Taggable Trait This package is not meant to handle javascript or html in any way. This package handles database storage and read/writes only.

Rob 859 Dec 11, 2022
Support multi theme for Laravel application

Very short description of the package This is where your description should go. Try and limit it to a paragraph or two, and maybe throw in a mention o

Ephraïm SEDDOR 1 Dec 1, 2021
An opinionated support package for Laravel, that provides flexible and reusable helper methods and traits for commonly used functionality.

Support An opinionated support package for Laravel, that provides flexible and reusable helper methods and traits for commonly used functionality. Ins

Ian Olson 3 Apr 14, 2021
Laravel Philips Hue package to control your lights with remote support

Laravel Philips Hue ?? Introduction I created this package for my company Ploi (https://ploi.io) to control our office lights. For example, when we re

Dennis Smink 81 Aug 11, 2022
Sweetalert and Toaster notifications for Laravel livewire with support for tailwind and bootstrap.

Larabell Integrate livewire with sweetalert. Installation How to use Sweetalert Toast Available configuration Installation composer require simtabi/la

Simtabi 3 Jul 27, 2022