Limit access to your Laravel applications by using invite codes

Overview

Doorman

GitHub Workflow Status GitHub release (latest SemVer)

Doorman provides a way to limit access to your Laravel applications by using invite codes.

Invite Codes:

  • Can be tied to a specific email address.
  • Can be available to anyone (great for sharing on social media).
  • Can have a limited number of uses or unlimited.
  • Can have an expiry date, or never expire.

Laravel Support

Laravel Doorman
5.x 3.x
6.x 4.x
7.x 5.x
8.x 6.x

Installation

You can pull in the package using composer:

$ composer require "clarkeash/doorman=^6.0"

Next, migrate the database:

$ php artisan migrate

Usage

Generate Invites

Make a single generic invite code with 1 redemption, and no expiry.

Doorman::generate()->make();

Make 5 generic invite codes with 1 redemption each, and no expiry.

Doorman::generate()->times(5)->make();

Make an invite with 10 redemptions and no expiry.

Doorman::generate()->uses(10)->make();

Make an invite with unlimited redemptions and no expiry.

Doorman::generate()->unlimited()->make();

Make an invite that expires on a specific date.

$date = Carbon::now('UTC')->addDays(7);
Doorman::generate()->expiresOn($date)->make();

Make an invite that expires in 14 days.

Doorman::generate()->expiresIn(14)->make();

Make an invite for a specific person.

Doorman::generate()->for('[email protected]')->make();

Alternatively instead of calling make() which will return a collection of invites you can call once() if you only want a single invite generated.

$invite = Doorman::generate()->for('[email protected]')->once();
dd($invite->code);

Redeem Invites

You can redeem an invite by calling the redeem method. Providing the invite code and optionally an email address.

Doorman::redeem('ABCDE');
// or
Doorman::redeem('ABCDE', '[email protected]');

If doorman is able to redeem the invite code it will increment the number of redemptions by 1, otherwise it will throw an exception.

  • InvalidInviteCode is thrown if the code does not exist in the database.
  • ExpiredInviteCode is thrown if an expiry date is set and it is in the past.
  • MaxUsesReached is thrown if the invite code has already been used the maximum number of times.
  • NotYourInviteCode is thrown if the email address for the invite does match the one provided during redemption, or one was not provided during redemption.

All of the above exceptions extend DoormanException so you can catch that exception if your application does not need to do anything specific for the above exceptions.

try {
    Doorman::redeem(request()->get('code'), request()->get('email'));
} catch (DoormanException $e) {
    return response()->json(['error' => $e->getMessage()], 422);
}

Check Invites without redeeming them

You can check an invite by calling the check method. Providing the invite code and optionally an email address. (It has the same signature as the redeem method except it will return true or false instead of throwing an exception.

Doorman::check('ABCDE');
// or
Doorman::check('ABCDE', '[email protected]');

Change Error Messages (and translation support)

In order to change the error message returned from doorman, we need to publish the language files like so:

$ php artisan vendor:publish --tag=doorman-translations

The language files will then be in /resources/lang/vendor/doorman/en where you can edit the messages.php file, and these messages will be used by doorman. You can create support for other languages by creating extra folders with a messages.php file in the /resources/lang/vendor/doorman directory such as de where you could place your German translations. Read the localisation docs for more info.

Validation

If you would perfer to validate an invite code before you attempt to redeem it or you are using Form Requests then you can validate it like so:

public function store(Request $request)
{
    $this->validate($request, [
        'email' => 'required|email|unique:users',
        'code' => ['required', new DoormanRule($request->get('email'))],
    ]);

    // Add the user to the database.
}

You should pass the email address into the constructor to validate the code against that email. If you know the code can be used with any email, then you can leave the parameter empty.

Config - change table name

First publish the package configuration:

$ php artisan vendor:publish --tag=doorman-config

In config/doorman.php you will see:

return [
    'invite_table_name' => 'invites',
];

If you change the table name and then run your migrations Doorman will then use the new table name.

Console

To remove used and expired invites you can use the cleanup command:

$ php artisan doorman:cleanup
Comments
  • post-autoload-dump event returned with error code 1

    post-autoload-dump event returned with error code 1

    Hi guys, i have this problem when i execute composer require clarkeash/doorman and when use php artisan clear :/, how fix this problem? my version of laravel is 7.13.0

    composer require clarkeash/doorman       
    Using version ^5.0 for clarkeash/doorman
    ./composer.json has been updated
    Loading composer repositories with package information
    Updating dependencies (including require-dev)
    Package operations: 1 install, 0 updates, 0 removals
      - Installing clarkeash/doorman (v5.0.1): Downloading (100%)
    Writing lock file
    Generating optimized autoload files
    > Illuminate\Foundation\ComposerScripts::postAutoloadDump
    > @php artisan package:discover --ansi
    
       Error
    
      Class name must be a valid object or a string
    
      at C:\xampp\htdocs\giknomina\vendor\clarkeash\doorman\src\Providers\DoormanServiceProvider.php:46
        42|             'doorman'
        43|         );
        44|
        45|         $this->app->bind(BaseInvite::class, function($app) {
      > 46|             return new $app['config']['doorman.invite_model'];
        47|         });
        48|
        49|         $this->app->bind('doorman', Doorman::class);
        50|         $this->app->singleton(Doorman::class, Doorman::class);
    
      1   C:\xampp\htdocs\giknomina\vendor\laravel\framework\src\Illuminate\Container\Container.php:801
          Clarkeash\Doorman\Providers\DoormanServiceProvider::Clarkeash\Doorman\Providers\{closure}(Object(Illuminate\Foundation\Application), [])
    
      2   C:\xampp\htdocs\giknomina\vendor\laravel\framework\src\Illuminate\Container\Container.php:687
          Illuminate\Container\Container::build(Object(Closure))
    Script @php artisan package:discover --ansi handling the post-autoload-dump event returned with error code 1
    
    Installation failed, reverting ./composer.json to its original content.
    
    
    Composer json
    ```js
    
     "require": {
            "php": "^7.2.5",
            "fideloper/proxy": "^4.2",
            "fruitcake/laravel-cors": "^2.0",
            "guzzlehttp/guzzle": "^6.3",
            "laravel/framework": "^7.0",
            "laravel/socialite": "^4.3",
            "laravel/tinker": "^2.0",
            "laravel/ui": "^2.0",
            "ramsey/uuid": "^3 || ^4"
        },
        "require-dev": {
            "facade/ignition": "^2.0",
            "fzaninotto/faker": "^1.9.1",
            "mockery/mockery": "^1.3.1",
            "nunomaduro/collision": "^4.1",
            "phpunit/phpunit": "^8.5"
        },
        "config": {
            "optimize-autoloader": true,
            "preferred-install": "dist",
            "sort-packages": true
        },
        "extra": {
            "laravel": {
                "dont-discover": []
            }
        },
        "autoload": {
            "psr-4": {
                "App\\": "app/"
            },
            "classmap": [
                "database/seeds",
                "database/factories"
            ]
        },
        "autoload-dev": {
            "psr-4": {
                "Tests\\": "tests/"
            }
        },
        "minimum-stability": "dev",
        "prefer-stable": true,
        "scripts": {
            "post-autoload-dump": [
                "Illuminate\\Foundation\\ComposerScripts::postAutoloadDump",
                "@php artisan package:discover --ansi"
            ],
            "post-root-package-install": [
                "@php -r \"file_exists('.env') || copy('.env.example', '.env');\""
            ],
            "post-create-project-cmd": [
                "@php artisan key:generate --ansi"
            ]
        }
    
    opened by Aisakk 25
  • better code creation

    better code creation

    Right now the code generator just uses Str::random(5) so there is a big chance of duplication

    A lot of threads around the web about randomness also this one for laravel https://github.com/laravel/internals/issues/161

    I think a good compromise would be to extract the code generator process into its own class, and give the user an option to override code generator, so if someone is looking for some more secure way can easily use something like uniqueid or some uuid library and add some more options like checking for existence (there is no simple way of generating random string in multiple machines and to make sure there is no duplication without checking the db first)

    opened by boynet 10
  • Add support for Laravel 8

    Add support for Laravel 8

    This PR adds support for Laravel 8 which is going to be released on September 8th. This PR is based on the latest laravel 8 development version which should not change very much until its release.

    opened by SamuelNitsche 5
  • support

    support "ramsey/uuid": "^4.0" ?

    Hi there,

    I'm trying to use Doorman in combination with https://github.com/michaeldyrynda/laravel-model-uuid and it's causing a collision because that package supports the latest "ramsey/uuid": "^4.0" and yours is tied to ^3.6

    Any chance you could add support for the ^4.0 please?

    opened by vesper8 5
  • PHP8 and composer V2

    PHP8 and composer V2

    Good day sir and thank you very much for this nice package!

    Today i was trying to upgrade a project to PHP8.

    Composer (V2) complains:

    clarkeash/doorman v6.0.0 requires php ^7.3 -> your php version (8.0.0) does not satisfy that requirement.

    What can i do?

    Thanks in advance!

    opened by dom235 4
  • Allow a custom model to be used

    Allow a custom model to be used

    I am currently developing a multi-tenant app, so I need to add a relationship to the Invite model to connect an invite to a specific tenant.

    This was highly inspired by the way Spatie allows a custom model for (most of) their packages.

    opened by mikemand 4
  • Add an expired function to the model

    Add an expired function to the model

    It would be cool (and very useful to #10) to have an setExpiredAttribute() function on the Invite model, so you can do $invite->expired and get a boolean

    opened by m1guelpf 4
  • Bounced Email

    Bounced Email

    Is there a way to show the email bounced via Doorman? Or would I need to load this data from our third party email provider Sendgrid? Two, I removed the invite and re-added it again with same email address once the email address was actually added and working. But then no email was sent at all. How to solve that issue?

    opened by jasperf 3
  • Reedem without exceptions

    Reedem without exceptions

    It would be cool to have a reedem-like exception, but that returns true or false instead of throwing exceptions. I've had a look at the code, and it'd be easy to implement, but I couldn't come up with a namefor the function :rofl:

    opened by m1guelpf 3
  • Redeem and return redeemed invite

    Redeem and return redeemed invite

    I have implemented my own Driver and Invite class which are working well.

    In my use case I would like to get the Invite instance after Doorman::redeem. Is there an easy way to get this working without me implementing my own Doorman class as well?

    opened by issa 2
  • Invite url clicked from email hits privacy error

    Invite url clicked from email hits privacy error

    For the first time in like error an invite link

    http://url5220.site.com/ls/click?upn=kvKv-2FX7KJRO-2BuIGglPGWwYFfpq-2FfmWSsrf0-.......................
    

    opened from webmail loads a Chrome error page:

    Your connection is not private
    Attackers might be trying to steal your information from url5220.site.com (for example, passwords, messages, or credit cards). [Learn more](chrome-error://chromewebdata/#)
    NET::ERR_CERT_COMMON_NAME_INVALID
    
    Screen Shot 2022-02-14 at 10 31 09 AM

    checking the certificate I see it loads the SendGrid wildcard url and not our domain wildcard url under which this "temporary" subdomain is loading.

    So either the subdomain should load under SendGrid or the subdomain link is fine but it is trying to grab the wrong SSL certificate.

    This could very well be an issue in our setup. Just odd it pops up now after like 2 years and wondering if anyone else has dealt with this issue.

    opened by jasperf 2
Releases(v7.0.0)
Owner
Ashley Clarke
Software Engineer
Ashley Clarke
The Salla OAuth Client library is designed to provide client applications with secure delegated access to Salla Merchant stores.

Salla Provider for OAuth 2.0 Client This package provides Salla OAuth 2.0 support for the PHP League's OAuth 2.0 Client. To use this package, it will

Salla 14 Nov 27, 2022
Dynamic ACL is a package that handles Access Control Level on your Laravel Application.

Dynamic ACL Dynamic ACL is a package that handles Access Control Level on your Laravel Application. It's fast to running and simple to use. Install an

yasin 8 Jul 31, 2022
The easiest and most intuitive way to add access management to your Filament Resource Models through `spatie/laravel-permission`

Filament Shield The easiest and most intuitive way to add access management to your Filament Resource Models (more coming soon ?? ) One Plugin to rule

Bezhan Salleh 329 Jan 2, 2023
Multi-factor Authentication using a Public PGP key for web based applications

PGPmfa() a PHP Class for PGP Multi-factor Authentication using a Public PGP key for web based applications Multi-factor Authentication with PGP Second

null 2 Nov 27, 2022
An authorization library that supports access control models like ACL, RBAC, ABAC in Laravel.

Laravel Authorization Laravel-authz is an authorization library for the laravel framework. It's based on Casbin, an authorization library that support

PHP-Casbin 243 Jan 4, 2023
Tech-Admin is Laravel + Bootstrap Admin Panel With User Management And Access Control based on Roles and Permissions.

Tech-Admin | Laravel 8 + Bootstrap 4 Tech-Admin is Admin Panel With Preset of Roles, Permissions, ACL, User Management, Profile Management. Features M

TechTool India 39 Dec 23, 2022
An authorization library that supports access control models like ACL, RBAC, ABAC in PHP .

PHP-Casbin Documentation | Tutorials | Extensions Breaking News: Laravel-authz is now available, an authorization library for the Laravel framework. P

PHP-Casbin 1.1k Dec 14, 2022
Register ,Login , Logout , having access control

Helo what's up dude read by the name of creator lov3yp :D This script is inspired by Lov3yp#2018 And Burak karahan Installation steps: !- Import the s

Lov3yp 2 Nov 1, 2021
An authorization library that supports access control models like ACL, RBAC, ABAC for webman plugin

An authorization library that supports access control models like ACL, RBAC, ABAC for webman plugin

PHP-Casbin 18 Dec 30, 2022
Authentication, authorization and access control for PHP

Jasny Auth Authentication, authorization and access control for PHP. Features Multiple authorization strategies, like groups (for acl) and levels. Aut

Arnold Daniels 105 Dec 12, 2022
GUI manager for RBAC (Role Base Access Control) Yii2. Easy to manage authorization of user

RBAC Manager for Yii 2 GUI manager for RBAC (Role Base Access Control) Yii2. Easy to manage authorization of user ?? . Documentation Important: If you

MDMunir Software 1.2k Jan 7, 2023
A simple two factor authentication for laravel applications

Laravel 2fa A simple two factor authentication for laravel applications. Installation Require via composer Update database Replace authentication trai

Rezkonline 1 Feb 9, 2022
phpCAS is an authentication library that allows PHP applications to easily authenticate users via a Central Authentication Service (CAS) server.

phpCAS is an authentication library that allows PHP applications to easily authenticate users via a Central Authentication Service (CAS) server.

Apereo Foundation 780 Dec 24, 2022
Integrate reCAPTCHA using async HTTP/2, making your app fast with a few lines

Integrate reCAPTCHA using async HTTP/2, making your app fast with a few lines

Laragear 14 Dec 6, 2022
A Laravel 5 package for OAuth Social Login/Register implementation using Laravel socialite and (optionally) AdminLTE Laravel package

laravel-social A Laravel 5 package for OAuth Social Login/Register implementation using Laravel socialite and (optionally) AdminLTE Laravel package. I

Sergi Tur Badenas 42 Nov 29, 2022
Sign into your Flarum forum with your Amazon account

Log In With Amazon A Flarum extension. Log in to your Flarum forum with Amazon. An addon for FoF OAuth Installation Install with composer: composer re

Ian Morland 0 May 4, 2022
Set up Laravel Auth guards using Eloquent in seconds

Nightguard Set up Auth guards using Eloquent in seconds. Introduction Laravel guards provide a super convenient way of authorizing different areas of

Luke Downing 10 Mar 18, 2021
Login Using Laravel UI

Projeto Laravel utilizando a biblioteca Laravel UI para autenticação de usuários com Username e Senha.

AlexLeonel 2 Oct 27, 2021
Login & Register using laravel 8

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

Georgy Octavianus Fernando 1 Nov 16, 2021