{"id":35407144,"url":"https://github.com/cesargb/laravel-magiclink","last_synced_at":"2026-01-28T18:09:28.276Z","repository":{"id":23172245,"uuid":"98337902","full_name":"cesargb/laravel-magiclink","owner":"cesargb","description":"Create link for authenticate in Laravel without password or get private content","archived":false,"fork":false,"pushed_at":"2025-09-05T04:46:55.000Z","size":271,"stargazers_count":434,"open_issues_count":4,"forks_count":49,"subscribers_count":7,"default_branch":"master","last_synced_at":"2025-09-23T23:11:34.102Z","etag":null,"topics":["auth","authentication","auto","laravel","link","login","passwordless"],"latest_commit_sha":null,"homepage":"","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/cesargb.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2017-07-25T18:31:29.000Z","updated_at":"2025-09-23T15:12:45.000Z","dependencies_parsed_at":"2024-02-02T08:47:09.574Z","dependency_job_id":"c65857de-76cb-4255-a2b9-55465d77bb1c","html_url":"https://github.com/cesargb/laravel-magiclink","commit_stats":{"total_commits":276,"total_committers":18,"mean_commits":"15.333333333333334","dds":"0.23550724637681164","last_synced_commit":"97f42b4a4f3f6ed3bf29d6717b6d8bd9ea07ff0e"},"previous_names":[],"tags_count":49,"template":false,"template_full_name":null,"purl":"pkg:github/cesargb/laravel-magiclink","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cesargb%2Flaravel-magiclink","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cesargb%2Flaravel-magiclink/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cesargb%2Flaravel-magiclink/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cesargb%2Flaravel-magiclink/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/cesargb","download_url":"https://codeload.github.com/cesargb/laravel-magiclink/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cesargb%2Flaravel-magiclink/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28173299,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2026-01-02T02:00:06.235Z","response_time":54,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["auth","authentication","auto","laravel","link","login","passwordless"],"created_at":"2026-01-02T13:00:57.743Z","updated_at":"2026-01-02T13:01:56.854Z","avatar_url":"https://github.com/cesargb.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"\n# MagicLink for Laravels App\n\nThrough the `MagicLink` class we can create a secure link that later\nbeing visited will perform certain actions, which will allow us\noffer secure content and even log in to the application.\n\n[![Latest Version on Packagist](https://img.shields.io/packagist/v/cesargb/laravel-magiclink.svg?style=flat-square)](https://packagist.org/packages/cesargb/laravel-magiclink)\n![tests](https://github.com/cesargb/laravel-magiclink/workflows/tests/badge.svg)\n[![style-fix](https://github.com/cesargb/laravel-magiclink/actions/workflows/style-fix.yml/badge.svg)](https://github.com/cesargb/laravel-magiclink/actions/workflows/style-fix.yml)\n[![Quality Score](https://img.shields.io/scrutinizer/g/cesargb/laravel-magiclink.svg?style=flat-square)](https://scrutinizer-ci.com/g/cesargb/laravel-magiclink)\n[![Total Downloads](https://img.shields.io/packagist/dt/cesargb/laravel-magiclink.svg?style=flat-square)](https://packagist.org/packages/cesargb/laravel-magiclink)\n\n## Contents\n\n- [Installation](#installation)\n- [Use case](#use-case)\n- [Create a MagicLink](#create-a-magiclink)\n- [Actions](#actions)\n  - [Login](#login-action)\n  - [Download file](#download-file-action)\n  - [View](#view-action)\n  - [Http Response](#http-response-action)\n  - [Controller](#controller-action)\n  - [Custom Action](#custom-action)\n- [Protect with an access code](#protect-with-an-access-code)\n- [Lifetime](#lifetime)\n- [Events](#events)\n- [Customization](#customization)\n- [Rate limiting](#rate-limiting)\n- [Testing](#testing)\n- [Contributing](#contributing)\n- [Security](#security)\n\n## Installation\n\nYou can install this package via composer using:\n\n```bash\ncomposer require cesargb/laravel-magiclink\n```\n\n### Preparing the database\n\nYou need to publish the migration to create the `magic_links` table:\n\n```bash\nphp artisan vendor:publish --provider=\"MagicLink\\MagicLinkServiceProvider\" --tag=\"migrations\"\n```\n\nAfter that, you need to run migrations.\n\n```bash\nphp artisan migrate\n```\n\n## Use case\n\nWith this example you can create a link to auto login on your application with\nthe desired user:\n\n```php\nuse MagicLink\\Actions\\LoginAction;\nuse MagicLink\\MagicLink;\n\n$urlToAutoLogin =  MagicLink::create(new LoginAction($user))-\u003eurl\n```\n\n## Create a MagicLink\n\nThe `MagicLink` class has the `create` method to generate a class that through\nthe `url` property we will obtain the link that we will send to our visitor.\n\nThis method requires the action to be performed.\n\n## Actions\n\nEach MagicLink is associated with an action, which is what will be performed\nonce the link is visited.\n\n- [Login Action](#login-action)\n- [Download file Action](#download-file-action)\n- [View Action](#view-action)\n- [Http Response Action](#http-response-action)\n- [Http Response](#http-response-action)\n- [Controller](#controller-action)\n- [Custom Action](#custom-action)\n- [Custom Base URL](#custom-base-url)\n\n### Login Action\n\nThrough the `LoginAction` action, you can log in to the application using the\ngenerated link by `MagicLink`.\n\nYour constructor supports the user who will login. Optionally we can specify\nthe [HTTP response](https://laravel.com/docs/master/responses) using the method\n`response` or specify other guard with method `guard`.\n\nExamples:\n\n```php\nuse MagicLink\\Actions\\LoginAction;\nuse MagicLink\\MagicLink;\n\n// Sample 1; Login and redirect to dash board\n$action = new LoginAction(User::first());\n$action-\u003eresponse(redirect('/dashboard'));\n\n$urlToDashBoard = MagicLink::create($action)-\u003eurl;\n\n// Sample 2; Login and view forms to password reset and use guard web\n$action = new LoginAction(User::first());\n$action-\u003eresponse(view('password.reset', ['email' =\u003e 'user@example.tld']));\n\n$urlShowView = MagicLink::create($action)-\u003eurl;\n\n// Sample 3; Login in other guard and redirect default\n$action = new LoginAction(User::first());\n$action-\u003eguard('customguard');\n\n$urlShowView = MagicLink::create($action)-\u003eurl;\n\n// Sample 4; Login and remember me\n$action = new LoginAction(User::first());\n$action-\u003eremember();\n\n$urlShowView = MagicLink::create($action)-\u003eurl;\n```\n\n### Download file Action\n\nThis action, `DownloadFileAction`, permit create a link to download a private file.\n\nThe constructor require the file path.\n\nExample:\n\n```php\nuse MagicLink\\Actions\\DownloadFileAction;\nuse MagicLink\\MagicLink;\n\n// Url to download the file storage_app('private_document.pdf')\n$url = MagicLink::create(new DownloadFileAction('private_document.pdf'))-\u003eurl;\n\n// Download file with other file_name\n$action = new DownloadFileAction('private_document.pdf', 'your_document.pdf');\n$url = MagicLink::create($action)-\u003eurl;\n\n// Download file from other disk\n$action = new DownloadFileAction('private_document.pdf')-\u003edisk('ftp');\n$url = MagicLink::create($action)-\u003eurl;\n\n```\n\n### View Action\n\nWith the action `ViewAction`, you can provide access to the view. You can use\nin his constructor the same arguments than method `view` of Laravel.\n\nExample:\n\n```php\nuse MagicLink\\Actions\\ViewAction;\nuse MagicLink\\MagicLink;\n\n// Url to view a internal.blade.php\n$url = MagicLink::create(new ViewAction('internal', [\n    'data' =\u003e 'Your private custom content',\n]))-\u003eurl;\n```\n\n### Http Response Action\n\nThrough the `ResponseAction` action we can access private content without need\nlogin. Its constructor accepts as argument the\n[HTTP response](https://laravel.com/docs/responses)\nwhich will be the response of the request.\n\nExamples:\n\n```php\nuse MagicLink\\Actions\\ResponseAction;\nuse MagicLink\\MagicLink;\n\n$action = new ResponseAction(function () {\n    Auth::login(User::first());\n\n    return redirect('/change_password');\n});\n\n$urlToCustomFunction = MagicLink::create($action)-\u003eurl;\n```\n\n### Controller Action\n\n`MagicLink` can directly call a controller via the `ControllerAction` action.\n\nThe constructor requires one argument, the name of the controller class. With\nthe second argument can call any controller method, by default it will use the\n`__invoke` method.\n\n```php\nuse MagicLink\\Actions\\ControllerAction;\nuse MagicLink\\MagicLink;\n\n// Call the method __invoke of the controller\n$url = MagicLink::create(new ControllerAction(MyController::class))-\u003eurl;\n\n// Call the method show of the controller\n$url = MagicLink::create(new ControllerAction(MyController::class, 'show'))-\u003eurl;\n```\n\n### Custom Action\n\nYou can create your own action class, for them you just need to extend with\n`MagicLink\\Actions\\ActionAbstract`\n\n```php\nuse MagicLink\\Actions\\ActionAbstract;\n\nclass MyCustomAction extends ActionAbstract\n{\n    public function __construct(public int $variable)\n    {\n    }\n\n    public function run()\n    {\n        // Do something\n\n        return response()-\u003ejson([\n            'success' =\u003e true,\n            'data' =\u003e $this-\u003evariable,\n        ]);\n    }\n}\n```\n\nYou can now generate a Magiclink with the custom action\n\n```php\nuse MagicLink\\MagicLink;\n\n$action = new MyCustomAction('Hello world');\n\n$urlToCustomAction = MagicLink::create($action)-\u003eurl;\n```\n\n### Custom Base URL\n\nTo set the base URL for a magic link, you can use the `baseUrl` method. This method ensures that the provided base URL has a trailing slash, making it ready for URL generation.\n\n```php\n$magiclink = MagicLink::create($action);\n\n$magiclink-\u003ebaseUrl(\"http://example.com\");\n\n$urlShowView = $magiclink-\u003eurl; // http://example.com/magiclink/...\n```\n\n## Protect with an access code\n\nOptionally you can protect the resources with an access code.\nYou can set the access code with method `protectWithAccessCode`\nwhich accepts an argument with the access code.\n\n```php\n$magiclink = MagicLink::create(new DownloadFileAction('private_document.pdf'));\n\n$magiclink-\u003eprotectWithAccessCode('secret');\n\n$urlToSend = $magiclink-\u003eurl;\n```\n\n### Custom view for access code\n\nYou can customize the view of the access code form with the config file `magiclink.php`:\n\n```php\n'access_code' =\u003e [\n    'view' =\u003e 'magiclink::access-code', // Change with your view\n],\n```\n\nThis is the [default view](/resources/views/ask-for-access-code-form.blade.php)\n\n## Lifetime\n\nBy default a link will be available for 72 hours after your creation. We can\nmodify the life time in minutes of the link by the `$lifetime` option\navailable in the `create` method. This argument accepts the value `null` so\nthat it does not expire in time.\n\n```php\n$lifetime = 60; // 60 minutes\n\n$magiclink = MagicLink::create(new ResponseAction(), $lifetime);\n\n$urlToSend = $magiclink-\u003eurl;\n```\n\nWe also have another option `$numMaxVisits`, with which we can define the\nnumber of times the link can be visited, `null` by default indicates that there\nare no visit limits.\n\n```php\n$lifetime = null; // not expired in the time\n$numMaxVisits = 1; // Only can visit one time\n\n$magiclink = MagicLink::create(new ResponseAction(), $lifetime, $numMaxVisits);\n\n$urlToSend = $magiclink-\u003eurl;\n```\n\n## Events\n\nMagicLink can fires three events:\n\n### MagicLinkWasCreated\n\nEvent `MagicLink\\Events\\MagicLinkWasCreated`\n\nThis event is fired when a magic link is created.\n\n### MagicLinkWasVisited\n\nEvent `MagicLink\\Events\\MagicLinkWasVisited`\n\nThis event is fired when a magic link is visited.\n\n### MagicLinkWasDeleted\n\nEvent `MagicLink\\Events\\MagicLinkWasDeleted`\n\nThis event is fired when you disable mass deletion. Add this line in your\n`.env` file to disable mass deletion:\n\n```.env\n# Disable mass deletion for enable event MagicLinkWasDeleted\nMAGICLINK_DELETE_MASSIVE=false\n```\n\n\u003e [!WARNING]\n\u003e If you disable mass deletion, the cleanup will be performed one by one.\n\u003e If you have many records, this can be an issue.\n\n## Customization\n\n### Config\n\nTo custom this package you can publish the config file:\n\n```bash\nphp artisan vendor:publish --provider=\"MagicLink\\MagicLinkServiceProvider\" --tag=\"config\"\n```\n\nAnd edit the file `config/magiclink.php`\n\n### Migrations\n\nTo customize the migration files of this package you need to publish the migration files:\n\n```bash\nphp artisan vendor:publish --provider=\"MagicLink\\MagicLinkServiceProvider\" --tag=\"migrations\"\n```\n\nYou'll find the published files in `database/migrations/*`\n\n### Custom response when magiclink is invalid\n\nWhen the magicLink is invalid by default the http request return a status 403.\nYou can custom this response with config `magiclink.invalid_response`.\n\n#### Response\n\nTo return a response, use class `MagicLink\\Responses\\Response::class`\nsame `response()`, you can send the arguments with options\n\nExample:\n\n```php\n    'invalid_response' =\u003e [\n        'class'   =\u003e MagicLink\\Responses\\Response::class,\n        'options' =\u003e [\n            'content' =\u003e 'forbidden',\n            'status' =\u003e 403,\n        ],\n    ],\n```\n\n#### Abort\n\nTo return a exception and let the framework handle the response,\nuse class `MagicLink\\Responses\\AbortResponse::class`.\nSame `abort()`, you can send the arguments with options.\n\nExample:\n\n```php\n    'invalid_response' =\u003e [\n        'class'   =\u003e MagicLink\\Responses\\AbortResponse::class,\n        'options' =\u003e [\n            'message' =\u003e 'You Shall Not Pass!',\n            'status' =\u003e 403,\n        ],\n    ],\n```\n\n#### Redirect\n\nDefine class `MagicLink\\Responses\\RedirectResponse::class` to\nreturn a `redirect()`\n\n```php\n    'invalid_response' =\u003e [\n        'class'   =\u003e MagicLink\\Responses\\RedirectResponse::class,\n        'options' =\u003e [\n            'to' =\u003e '/not_valid_path',\n            'status' =\u003e 301,\n        ],\n    ],\n```\n\n#### View\n\nDefine class `MagicLink\\Responses\\ViewResponse::class` to\nreturn a `view()`\n\n```php\n    'invalid_response' =\u003e [\n        'class'   =\u003e MagicLink\\Responses\\ViewResponse::class,\n        'options' =\u003e [\n            'view' =\u003e 'invalid',\n            'data' =\u003e [],\n        ],\n    ],\n```\n\n## Rate limiting\n\nYou can limit the number of requests per minute for a magic link. To do this, you need to\nset the `MAGICLINK_RATE_LIMIT` environment variable to the desired value.\n\nBy default, the rate limit is disable with value 'none', but you can set a value\nto limit the requests. For example, to limit the requests to 100 per minute, set\n\n```bash\n# .env\n\nMAGICLINK_RATE_LIMIT=100\n```\n\n## Testing\n\nRun the tests with:\n\n``` bash\ncomposer test\n```\n\n## Contributing\n\nPlease see [CONTRIBUTING](CONTRIBUTING.md) for details.\n\n## Security\n\nIf you discover any security-related issues, please email cesargb@gmail.com\ninstead of using the issue tracker.\n\n## License\n\nThe MIT License (MIT). Please see [License File](LICENSE.md) for more information.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcesargb%2Flaravel-magiclink","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcesargb%2Flaravel-magiclink","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcesargb%2Flaravel-magiclink/lists"}