Repository: olssonm/l5-very-basic-auth
Branch: master
Commit: 59ae0468eb07
Files: 21
Total size: 36.1 KB
Directory structure:
gitextract_4ggz17vw/
├── .editorconfig
├── .github/
│ ├── FUNDING.yml
│ └── workflows/
│ └── test.yml
├── .gitignore
├── LICENSE.md
├── README.jp.md
├── README.md
├── composer.json
├── phpstan.neon
├── phpunit.xml
├── src/
│ ├── Console/
│ │ └── GeneratePassword.php
│ ├── Handlers/
│ │ ├── DefaultResponseHandler.php
│ │ └── ResponseHandler.php
│ ├── Http/
│ │ └── Middleware/
│ │ └── VeryBasicAuth.php
│ ├── VeryBasicAuthServiceProvider.php
│ ├── config.php
│ └── resources/
│ └── views/
│ └── default.blade.php
└── tests/
├── Fixtures/
│ └── CustomResponseHandler.php
├── Pest.php
├── TestCase.php
└── VeryBasicAuthTest.php
================================================
FILE CONTENTS
================================================
================================================
FILE: .editorconfig
================================================
; This file is for unifying the coding style for different editors and IDEs.
; More information at http://editorconfig.org
root = true
[*]
charset = utf-8
indent_size = 4
indent_style = space
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
[*.md]
trim_trailing_whitespace = false
[*.{yml,yaml}]
indent_size = 2
================================================
FILE: .github/FUNDING.yml
================================================
# These are supported funding model platforms
github: [olssonm]
================================================
FILE: .github/workflows/test.yml
================================================
name: Run tests
on:
push:
pull_request:
jobs:
php-tests:
runs-on: ubuntu-latest
strategy:
matrix:
php: [8.5, 8.4, 8.3, 8.2]
laravel: ['12.*', '13.*']
exclude:
- laravel: 13.*
php: 8.2
- laravel: 12.*
php: 8.5
name: P${{ matrix.php }} - L${{ matrix.laravel }}
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php }}
extensions: dom, curl, libxml, mbstring, zip
tools: composer:v2
coverage: none
- name: Install dependencies
run: |
composer require "illuminate/support:${{ matrix.laravel }}" --no-interaction --no-progress --no-suggest
composer update --prefer-dist --no-interaction --no-progress
- name: Execute tests
run: composer test
================================================
FILE: .gitignore
================================================
/vendor
composer.lock
.DS_Store
.phpunit.result.cache
.phpunit.cache
phpunit-output
================================================
FILE: LICENSE.md
================================================
# The MIT License (MIT)
Copyright (c) 2024 Marcus Olsson <contact@marcusolsson.me>
> Permission is hereby granted, free of charge, to any person obtaining a copy
> of this software and associated documentation files (the "Software"), to deal
> in the Software without restriction, including without limitation the rights
> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
> copies of the Software, and to permit persons to whom the Software is
> furnished to do so, subject to the following conditions:
>
> The above copyright notice and this permission notice shall be included in
> all copies or substantial portions of the Software.
>
> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
> THE SOFTWARE.
================================================
FILE: README.jp.md
================================================
# Laravel Very Basic Auth
[![Latest Version on Packagist][ico-version]][link-packagist]
[![Total downloads][ico-downloads]][link-packagist]
[![Software License][ico-license]](LICENSE.md)
[![Build Status][ico-build]][link-build]

**利用可能なドキュメントは以下です:**
🇬🇧 [English](README.md)
🇯🇵 [日本語](README.jp.md)
Laravel 5 Very Basic AuthはLaravel標準の`auth.basic`とは違い、実際のデータベースの情報を使うことなくBasic認証を追加します。
<img width="400" alt="Screenshot" src="https://user-images.githubusercontent.com/907114/29876493-3907afd8-8d9d-11e7-8068-f461855c493b.png">
例えば、開発中のサイトにユーザーをアクセスさせたい時や、まだデータベースやモデルを用意していない時に使うと便利です。あなたのサイトがデータベースを利用していない場合でも、アクセスを制御することができます。
認証に失敗した場合には、"401 Unauthorized"のレスポンスを返します。
#### 注意点
Basic認証は望まないユーザーからのアクセスを排除することができますが、ブルートフォース攻撃に対しては厳密には安全ではありません。もしこのパッケージをセキュリティのために単独で利用するのであれば、ログインの試行回数を制限するために、少なくともApacheかNginxのrate-limitersを確認するべきです。
## インストール
Composer経由
``` bash
$ composer require olssonm/l5-very-basic-auth
```
このパッケージのv4.* (for Laravel 5.5)以降では、サービスプロバイダーからパッケージを読み込むのに、パッケージのオートディスカバリーを使用しています。パッケージをインストールすると、以下のメッセージが表示されるはずです。
```
Discovered Package: olssonm/l5-very-basic-auth
```
もしも手動でプロバイダーに追加したい場合は、composer.jsonファイルでオートディスカバリーを切って、
``` json
"extra": {
"laravel": {
"dont-discover": [
"olssonm/l5-very-basic-auth"
]
}
},
```
(`config/app.php`)のprovidersにプロバイダーを追加してください。
``` php
'providers' => [
Olssonm\VeryBasicAuth\VeryBasicAuthServiceProvider::class
]
```
## 設定
`$ php artisan vendor:publish`のコマンドを実行し、`Provider: Olssonm\VeryBasicAuth\VeryBasicAuthServiceProvider`を選んで設定ファイルを公開してください。`$ php artisan vendor:publish --provider="Olssonm\VeryBasicAuth\VeryBasicAuthServiceProvider"`でも設定ファイルを公開することができます。
`very_basic_auth.php`のファイルがあなたの`app/config`ディレクトリにコピーされます。ここにusernameやpasswordなどの幾つかの設定を置くことができます。
### 注意
**デフォルトのパスワードはありません。** セキュリティのために(誰もが同じパスワードになってしまわないように)、インストール時にランダムなパスワードが設定されます。個別のパスワードを設定するためにもパッケージ設定の公開をして下さい。
#### ビューとメッセージ
`very_basic_auth.php`ファイルでは、メッセージの代わりにカスタマイズしたビューを設定することができます。
``` php
// ユーザーがオプトアウトするか、キャンセルを押した場合に表示されるメッセージ
'error_message' => 'You have to supply your credentials to access this resource.',
// エラーメッセージの代わりにviewを使いたい場合は"error_view"のコメントアウトを外して下さい。
// この場合、あなたのデフォルトのレスポンスメッセージよりもエラービューが優先されます。
// 'error_view' => 'very_basic_auth::default'
```
`error_view`のコメントアウトを外した場合、ミドルウェアは指定されたviewを探そうとします。このビュー名は通常と同じように`.blade.php`の拡張子無しで設定してください。
*以前のバージョンから2.1にアップグレードする場合、このkeyとvalueは公開された設定には存在しないので、自分自身で設定を追加する必要があります。*
## 使い方
このミドルウェアはルートを保護するのに`auth.very_basic`の短縮キーを使います。`Route::group()`に適用して複数のルートを保護することもできますし、個別に保護するルートを選ぶこともできます。
**グループを使う場合**
``` php
Route::group(['middleware' => 'auth.very_basic'], function() {
Route::get('/', ['as' => 'start', 'uses' => 'StartController@index']);
Route::get('/page', ['as' => 'page', 'uses' => 'StartController@page']);
});
```
**単独で使う場合**
``` php
Route::get('/', [
'as' => 'start',
'uses' => 'StartController@index',
'middleware' => 'auth.very_basic'
]);
```
認証情報をルート上に記述することもできます。
``` php
Route::get('/', [
'as' => 'start',
'uses' => 'StartController@index',
'middleware' => 'auth.very_basic:username,password'
]);
```
*Note:* 認証情報をルート上に記述した場合、設定ファイルの`very_basic_auth.php`より優先されます。
## テスト
``` bash
$ composer test
```
または
``` bash
$ phpunit
```
テストを実行する際は、Laravelは常にenvironmentの値を"testing"にします。`testing`が`very_basic_auth.php`の`envs`配列内に存在することを確認して下さい。
## ライセンス
MITライセンスです。 詳しくはこちらを見てください。[License File](LICENSE.md)
© 2024 [Marcus Olsson](https://marcusolsson.me).
[ico-version]: https://img.shields.io/packagist/v/olssonm/l5-very-basic-auth.svg?style=flat-square
[ico-license]: https://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat-square
[ico-build]: https://img.shields.io/github/workflow/status/olssonm/l5-very-basic-auth/Run%20tests.svg?style=flat-square&label=tests
[ico-downloads]: https://img.shields.io/packagist/dt/olssonm/l5-very-basic-auth.svg?style=flat-square
[link-packagist]: https://packagist.org/packages/olssonm/l5-very-basic-auth
[link-build]: https://github.com/olssonm/l5-very-basic-auth/actions?query=workflow%3A%22Run+tests%22
================================================
FILE: README.md
================================================
# Laravel Very Basic Auth
[![Latest Version on Packagist][ico-version]][link-packagist]
[![Total downloads][ico-downloads]][link-packagist]
[![Software License][ico-license]](LICENSE.md)
[![Build Status][ico-build]][link-build]

**Documentation available in:**
🇬🇧 [English](README.md)
🇯🇵 [日本語](README.jp.md)
This package allows you to add a HTTP Basic Auth filter on your routes, without the need to use a database – which the Laravel default `auth.basic`-middleware relies on.
<img width="400" alt="Screenshot" src="https://user-images.githubusercontent.com/907114/29876493-3907afd8-8d9d-11e7-8068-f461855c493b.png">
Perfect when you want to give your clients access to your development site before you have yet to set up your database and/or models. Or perhaps your site doesn't even use a database and you still wish to keep it protected.
On failed authentication the user will get a "401 Unauthorized" response.
#### A thing to note
While HTTP Basic Auth does give you a protection layer against unwanted visitors, it is still not strictly safe from brute-force attacks. If you are solely using this package for security, you should at least consider looking into Apache or Nginx rate-limiters to limit login attempts.
## Installation
Via Composer
``` bash
$ composer require olssonm/l5-very-basic-auth
```
Since v4.* (for Laravel 5.5) this package uses Package Auto-Discovery for loading the service provider. Once installed you should see the message
```
Discovered Package: olssonm/l5-very-basic-auth
```
If you would like to manually add the provider, turn off Auto-Discovery for the package in your composer.json-file:
``` json
"extra": {
"laravel": {
"dont-discover": [
"olssonm/l5-very-basic-auth"
]
}
},
```
And then add the provider in the providers array (`config/app.php`).
``` php
'providers' => [
Olssonm\VeryBasicAuth\VeryBasicAuthServiceProvider::class
]
```
## Configuration
Run the command `$ php artisan vendor:publish` and select `Provider: Olssonm\VeryBasicAuth\VeryBasicAuthServiceProvider` to publish the configuration. You could also type `$ php artisan vendor:publish --provider="Olssonm\VeryBasicAuth\VeryBasicAuthServiceProvider"` to directly publish the files.
The file `very_basic_auth.php` will then be copied to your `app/config`-folder – here you can set various options such as username and password.
#### Note
**There is no default password**. Upon installation you will need to set your own username and password. Please publish the packages configuration to have the ability to set these. **If left empty, basic auth will not be active**.
### Environments
You may set the environments that the package should be applied for. You may simply use "`*`" to use in all environments (this is also the default).
``` php
'envs' => [
'*'
],
```
Or
``` php
'envs' => [
'production',
'development',
'local'
],
```
### Response handlers
When the authentication fails the response handler sends out an error response (see "Views and messages" for more about these options). By default the handler will be `\Olssonm\VeryBasicAuth\Handlers\DefaultResponseHandler` (see `response_handler` in `very_basic_auth.php`). You may however write your own response-logic if you so choose. The only requirement is that it implements the `\Olssonm\VeryBasicAuth\Handlers\ResponseHandler`-interface, and has an `__invoke`-method that accepts a request-object, like so:
``` php
use Illuminate\Http\Request;
use Olssonm\VeryBasicAuth\Handlers\ResponseHandler;
class CustomResponseHandler implements ResponseHandler
{
public function __invoke(Request $request)
{
// Do some stuff
return response('Custom response', 401);
}
}
```
### Views and messages
In the `very_basic_auth.php`-configuration you have the ability to set a custom view instead of a message.
``` php
// Message to display if the user "opts out"/clicks "cancel"
'error_message' => 'You have to supply your credentials to access this resource.',
// If you prefer to use a view with your error message you can uncomment "error_view".
// This will supersede your default response message
// 'error_view' => 'very_basic_auth::default'
```
If you uncomment `error_view`, the middleware will try to find your specified view. You supply this value as usual (without the `.blade.php`-extention).
## Usage
The middleware uses the `auth.very_basic`-filter to protect routes. You can either use `Route::group()` to protect multiple routes, or chose just to protect them individually.
**Group**
``` php
Route::group(['middleware' => 'auth.very_basic'], function() {
Route::get('/', ['as' => 'start', 'uses' => 'StartController@index']);
Route::get('/page', ['as' => 'page', 'uses' => 'StartController@page']);
});
```
**Single**
``` php
Route::get('/', [
'as' => 'start',
'uses' => 'StartController@index',
'middleware' => 'auth.very_basic'
]);
```
You may also set the credentials inline;
``` php
Route::get('/', [
'as' => 'start',
'uses' => 'StartController@index',
'middleware' => 'auth.very_basic:username,password'
]);
```
*Note:* inline credentials always take president over the `very_basic_auth.php`-configuration file.
### Generating hash for password
If you want to generate a hash for your password, you can use the `artisan`-command:
``` bash
php artisan very-basic-auth:generate-password
```
It will ask you for a password, and then automatically insert the hash into your `.env`-file
## Testing
``` bash
$ composer test
```
or
``` bash
$ phpunit
```
Laravel always runs in the "testing" environment while running tests. Make sure that `testing` is set in the `envs`-array in `very_basic_auth.php`.
## Thank you
A big thank you to the people who has contributed to this package, among others:
**[kazuhei](https://github.com/kazuhei)** – for providing the awesome Japanese translation
**[freekmurze](https://github.com/freekmurze)** – for additional information on package/vendor installations
**[faiare](https://github.com/faiare)** – for pointing out and implementing the `realm`-attribute ([RFC7235](https://tools.ietf.org/html/rfc7235#section-2.2))
## License
The MIT License (MIT). Please see [License File](LICENSE.md) for more information.
© 2024 [Marcus Olsson](https://marcusolsson.me).
[ico-version]: https://img.shields.io/packagist/v/olssonm/l5-very-basic-auth.svg?style=flat-square
[ico-license]: https://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat-square
[ico-build]: https://img.shields.io/github/actions/workflow/status/olssonm/l5-very-basic-auth/test.yml?branch=master&style=flat-square
[ico-downloads]: https://img.shields.io/packagist/dt/olssonm/l5-very-basic-auth.svg?style=flat-square
[link-packagist]: https://packagist.org/packages/olssonm/l5-very-basic-auth
[link-build]: https://github.com/olssonm/l5-very-basic-auth/actions?query=workflow%3A%22Run+tests%22
================================================
FILE: composer.json
================================================
{
"name": "olssonm/l5-very-basic-auth",
"description": "Laravel stateless HTTP basic auth without the need for a database",
"license": "MIT",
"keywords": [
"olssonm",
"laravel",
"authentication",
"http basic auth"
],
"authors": [
{
"name": "Marcus Olsson",
"email": "contact@marcusolsson.me",
"homepage": "https://marcusolsson.me"
}
],
"homepage": "https://github.com/olssonm/l5-very-basic-auth",
"require": {
"php": "^8.2",
"illuminate/support": "^12.0 || ^13.0"
},
"require-dev": {
"laravel/helpers": "^1.1",
"orchestra/testbench": "^10.0 || ^11.0",
"pestphp/pest": "^3.7 || ^4.4",
"pestphp/pest-plugin-laravel": "^3.1 || ^4.1",
"phpstan/phpstan": "^2.0",
"phpunit/phpunit": "^11.5.3 || ^12.5.12",
"squizlabs/php_codesniffer": "^3.5 || ^4.0"
},
"minimum-stability": "dev",
"prefer-stable": true,
"autoload": {
"psr-4": {
"Olssonm\\VeryBasicAuth\\": "src"
}
},
"autoload-dev": {
"psr-4": {
"Olssonm\\VeryBasicAuth\\Tests\\": "tests"
}
},
"config": {
"allow-plugins": {
"pestphp/pest-plugin": true
},
"sort-packages": true
},
"extra": {
"branch-alias": {
"dev-master": "11.x-dev"
},
"laravel": {
"providers": [
"Olssonm\\VeryBasicAuth\\VeryBasicAuthServiceProvider"
]
}
},
"scripts": {
"phpfix": "vendor/bin/phpcbf --standard=\"PSR12\" ./src --ignore=./src/resources/*",
"phpsniff": "vendor/bin/phpcs --standard=\"PSR12\" ./src --ignore=./src/resources/*",
"phpstan": "./vendor/bin/phpstan",
"test": "vendor/bin/pest"
}
}
================================================
FILE: phpstan.neon
================================================
parameters:
level: 8
paths:
- src
ignoreErrors:
- identifier: missingType.generics
================================================
FILE: phpunit.xml
================================================
<?xml version="1.0" encoding="UTF-8"?>
<phpunit
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/10.5/phpunit.xsd"
bootstrap="vendor/autoload.php"
backupGlobals="false"
colors="true"
processIsolation="false"
stopOnFailure="false"
cacheDirectory=".phpunit.cache"
backupStaticProperties="false"
>
<testsuites>
<testsuite name="Package Test Suite">
<directory>tests</directory>
</testsuite>
</testsuites>
<source>
<include>
<directory>src</directory>
</include>
<exclude>
<directory suffix=".blade.php">src</directory>
</exclude>
</source>
</phpunit>
================================================
FILE: src/Console/GeneratePassword.php
================================================
<?php
namespace Olssonm\VeryBasicAuth\Console;
use Illuminate\Console\Command;
use Symfony\Component\Console\Attribute\AsCommand;
#[AsCommand('very-basic-auth:generate-password')]
class GeneratePassword extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'very-basic-auth:generate-password';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Allows to securely set the `BASIC_AUTH_PASSWORD` in your Laravel `.env` file.';
/**
* Execute the console command.
*
* @return int
*/
public function handle(): int
{
$password = $this->promptForValidPassword();
if ($this->writeNewEnvironmentFileWith($this->hashPassword($password))) {
$this->info('The password has been set successfully.');
}
return static::SUCCESS;
}
/**
* Keep asking for a password until a valid one is provided.
*/
protected function promptForValidPassword(): string
{
while (true) {
$password = (string) $this->secret('Please enter a password for the very basic auth');
if (!$this->isPasswordAccepted($password)) {
$this->error('The password must be at least 8 characters.');
continue;
}
if (!$this->passwordsMatch($password)) {
$this->error('The passwords do not match. Please try again.');
continue;
}
return $password;
}
}
/**
* Determine if the provided password fulfills minimum requirements.
*/
protected function isPasswordAccepted(?string $password): bool
{
return !empty($password) && strlen($password) >= 8;
}
/**
* Ask for confirmation and ensure it matches.
*/
protected function passwordsMatch(string $password): bool
{
return $password === (string) $this->secret('Please confirm your password');
}
/**
* Hash the password using Laravel's configured hasher.
*/
protected function hashPassword(string $password): string
{
return app()->make('hash')->make($password);
}
/**
* Write a new environment file with the given password.
*
* @param string $password
* @return bool
*/
protected function writeNewEnvironmentFileWith(string $password): bool
{
$envPath = $this->laravel->environmentFilePath();
$input = file_get_contents($envPath);
$replaced = preg_replace_callback(
$this->passwordReplacementPattern(),
fn($matches) => 'BASIC_AUTH_PASSWORD="' . $password . '"',
$input
);
if ($replaced === $input || $replaced === null) {
$this->error('Unable to set password. No BASIC_AUTH_PASSWORD variable was found in the .env file. Please add it first');
return false;
}
file_put_contents($envPath, $replaced);
return true;
}
/**
* Get a regex pattern that will match env BASIC_AUTH_PASSWORD with any password.
*
* @return string
*/
protected function passwordReplacementPattern(): string
{
return '/^BASIC_AUTH_PASSWORD=.*$/m';
}
}
================================================
FILE: src/Handlers/DefaultResponseHandler.php
================================================
<?php
namespace Olssonm\VeryBasicAuth\Handlers;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
class DefaultResponseHandler implements ResponseHandler
{
public function __invoke(Request $request): Response|JsonResponse
{
// Build header
$header = [
'WWW-Authenticate' => sprintf(
'Basic realm="%s", charset="UTF-8"',
config('very_basic_auth.realm', 'Basic Auth')
),
];
// View
$view = config('very_basic_auth.error_view');
// If the request want's JSON, else view
if ($request->wantsJson()) {
return response()->json([
'message' => config('very_basic_auth.error_message'),
], 401, $header);
} elseif (isset($view)) {
return response()->view($view, [], 401)
->withHeaders($header);
}
// Return default message
return response()->make(config('very_basic_auth.error_message'), 401, $header);
}
}
================================================
FILE: src/Handlers/ResponseHandler.php
================================================
<?php
namespace Olssonm\VeryBasicAuth\Handlers;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
interface ResponseHandler
{
public function __invoke(Request $request): Response|JsonResponse;
}
================================================
FILE: src/Http/Middleware/VeryBasicAuth.php
================================================
<?php
namespace Olssonm\VeryBasicAuth\Http\Middleware;
use Closure;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash;
use Olssonm\VeryBasicAuth\Handlers\ResponseHandler;
use Symfony\Component\HttpFoundation\Response;
class VeryBasicAuth
{
protected ResponseHandler $responseHandler;
public function __construct(ResponseHandler $responseHandler)
{
$this->responseHandler = $responseHandler;
}
/**
* Handle an incoming request
*
* @param mixed $username
* @param mixed $password
*/
public function handle(Request $request, Closure $next, $username = null, $password = null): Response
{
$active = (count(array_intersect([
'*',
app()->environment(),
], config('very_basic_auth.envs'))) > 0);
// Check if middleware is in use in current environment
if ($active) {
$authUsername = $username ?? config('very_basic_auth.user');
$authPassword = $password ?? config('very_basic_auth.password');
if (! $authUsername && ! $authPassword) {
return $next($request);
}
$plainPassword = $request->getPassword();
$isCorrectPassword = $plainPassword === $authPassword;
if (! $isCorrectPassword) {
try {
$isCorrectPassword = Hash::check($plainPassword, $authPassword);
} catch (\Throwable $e) {
// If the password is not hashed, we will just return false
$isCorrectPassword = false;
}
}
if ($request->getUser() !== $authUsername || !$isCorrectPassword) {
return $this->deniedResponse($request);
}
}
return $next($request);
}
/**
* Return a error response
*
* @return \Illuminate\Http\Response|\Illuminate\Http\JsonResponse
*/
private function deniedResponse(Request $request): Response|JsonResponse
{
return ($this->responseHandler)($request);
}
}
================================================
FILE: src/VeryBasicAuthServiceProvider.php
================================================
<?php
namespace Olssonm\VeryBasicAuth;
use Illuminate\Support\ServiceProvider;
use Olssonm\VeryBasicAuth\Console\GeneratePassword;
use Olssonm\VeryBasicAuth\Handlers\DefaultResponseHandler;
use Olssonm\VeryBasicAuth\Handlers\ResponseHandler;
class VeryBasicAuthServiceProvider extends ServiceProvider
{
/**
* Path to config-file
*
* @var string
*/
protected $config;
/**
* Path to stub
*
* @var string
*/
protected $stub;
/**
* Constructor
*
* @param \Illuminate\Contracts\Foundation\Application $app
* @return void
*/
public function __construct($app)
{
$this->config = __DIR__ . '/config.php';
parent::__construct($app);
}
/**
* Perform post-registration booting of services.
*
* @return void
*/
public function boot(\Illuminate\Routing\Router $router)
{
// Publishing of configuration
$this->publishes([
$this->config => config_path('very_basic_auth.php'),
]);
// Load default view/s
$this->loadViewsFrom(__DIR__ . '/resources/views', 'very_basic_auth');
// Register middleware
$router->aliasMiddleware('auth.very_basic', \Olssonm\VeryBasicAuth\Http\Middleware\VeryBasicAuth::class);
// Register commands
if ($this->app->runningInConsole()) {
$this->commands([
GeneratePassword::class,
]);
}
}
/**
* Register any package services.
*
* @return void
*/
public function register()
{
// If the user doesn't set their own config, load default
$this->mergeConfigFrom(
$this->config,
'very_basic_auth'
);
$this->app->bind(
ResponseHandler::class,
config('very_basic_auth.response_handler', DefaultResponseHandler::class)
);
}
}
================================================
FILE: src/config.php
================================================
<?php
/**
* Configuration for the "HTTP Very Basic Auth"-middleware
*/
return [
// Username
'user' => env('BASIC_AUTH_USERNAME', ''),
// Password
'password' => env('BASIC_AUTH_PASSWORD', ''),
// Environments where the middleware is active. Use "*" to protect all envs
'envs' => [
'*',
],
// Response handler for the error responses
'response_handler' => \Olssonm\VeryBasicAuth\Handlers\DefaultResponseHandler::class,
// Message to display if the user "opts out"/clicks "cancel"
'error_message' => 'You have to supply your credentials to access this resource.',
// Message to display in the auth dialog in some browsers (mainly Internet Explorer).
// Realm is also used to define a "space" that should share credentials.
'realm' => 'Basic Auth',
// If you prefer to use a view with your error message you can uncomment "error_view".
// This will supersede your default response message
// 'error_view' => 'very_basic_auth::default'
];
================================================
FILE: src/resources/views/default.blade.php
================================================
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Error</title>
<style media="screen">
html {
font-family: 'helvetica neue', helvetica, arial, sans-serif;
background-color: #ecf0f1;
}
.box {
width: 50%;
min-width: 400px;
margin: 0 auto;
padding: 30px;
background-color: #fff;
}
code {
font-size: 110%;
color: #e74c3c;
background-color: #ecf0f1;
padding: 1px 4px;
}
</style>
</head>
<body style="margin-bottom: 38px;">
<div class="box">
<h3>This is the default view for the olssonm/l5-very-basic-auth-package.</h3>
<p>
To customize this, simply edit your <code>very_basic_auth</code>-configuration file and set
<code>error_view</code> to your own custom blade-template (the default is <code>very_basic_auth::default</code>).
</p>
</div>
</body>
</html>
================================================
FILE: tests/Fixtures/CustomResponseHandler.php
================================================
<?php
namespace Olssonm\VeryBasicAuth\Tests\Fixtures;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Olssonm\VeryBasicAuth\Handlers\ResponseHandler;
class CustomResponseHandler implements ResponseHandler
{
public function __invoke(Request $request): Response|JsonResponse
{
return response('Custom response', 401);
}
}
================================================
FILE: tests/Pest.php
================================================
<?php
use Illuminate\Support\Facades\Route;
use Olssonm\VeryBasicAuth\Http\Middleware\VeryBasicAuth;
use Olssonm\VeryBasicAuth\Tests\TestCase;
uses(TestCase::class)
->beforeEach(function () {
// Set default config for testing
config()->set('very_basic_auth.user', 'test');
config()->set('very_basic_auth.password', 'test');
Route::get('/', fn () => 'ok')->middleware(VeryBasicAuth::class)->name('default');
Route::get('/test', fn () => 'ok')->middleware(VeryBasicAuth::class);
Route::get('/inline', fn () => 'ok')->middleware(
sprintf('auth.very_basic:%s,%s', config('very_basic_auth.user'), config('very_basic_auth.password'))
)->name('inline');
})
->in(__DIR__);
================================================
FILE: tests/TestCase.php
================================================
<?php
namespace Olssonm\VeryBasicAuth\Tests;
use Olssonm\VeryBasicAuth\VeryBasicAuthServiceProvider;
use Orchestra\Testbench\TestCase as OrchestraTestCase;
abstract class TestCase extends OrchestraTestCase
{
protected function setUp(): void
{
parent::setUp();
}
protected function getPackageProviders($app)
{
return [
VeryBasicAuthServiceProvider::class,
];
}
public static function tearDownAfterClass(): void
{
parent::tearDownAfterClass();
}
}
================================================
FILE: tests/VeryBasicAuthTest.php
================================================
<?php
use Illuminate\Support\Str;
use Olssonm\VeryBasicAuth\Handlers\DefaultResponseHandler;
use Olssonm\VeryBasicAuth\Handlers\ResponseHandler;
use Olssonm\VeryBasicAuth\Http\Middleware\VeryBasicAuth;
use Olssonm\VeryBasicAuth\Tests\Fixtures\CustomResponseHandler;
use function Pest\Laravel\get;
use function Pest\Laravel\withHeaders;
test('basic auth filter is set', function () {
expect(in_array(VeryBasicAuth::class, $this->app->router->getMiddleware()))->toBeTrue();
expect(array_key_exists('auth.very_basic', $this->app->router->getMiddleware()));
});
test('config file is installed', function () {
expect(file_exists(__DIR__.'/../src/config.php'))->toBeTrue();
});
test('install package', function () {
$this->artisan('vendor:publish', [
'--provider' => 'Olssonm\VeryBasicAuth\VeryBasicAuthServiceProvider',
])->assertExitCode(0);
expect(file_exists(config_path('very_basic_auth.php')))->toBeTrue();
});
test('request with no credentials and no config passes', function () {
config()->set('very_basic_auth.user', '');
config()->set('very_basic_auth.password', '');
$response = get('/');
expect($response->getStatusCode())->toEqual(200);
expect($response->headers->get('WWW-Authenticate'))->toEqual(null);
});
test('request with no credentials fails', function () {
$response = get('/');
expect($response->getStatusCode())->toEqual(401);
expect($response->headers->get('WWW-Authenticate'))->toEqual(sprintf('Basic realm="%s", charset="UTF-8"', config('very_basic_auth.realm')));
expect($response->getContent())->toEqual(config('very_basic_auth.error_message'));
});
test('request with incorrect credentials fails - text/html', function () {
$response = withHeaders([
'PHP_AUTH_USER' => str_random(20),
'PHP_AUTH_PW' => str_random(20),
])->get('/');
expect($response->getStatusCode())->toEqual(401);
expect(requestHeader($response))->toEqual('text/html; charset=utf-8');
expect($response->headers->get('WWW-Authenticate'))->toEqual(sprintf('Basic realm="%s", charset="UTF-8"', config('very_basic_auth.realm')));
expect($response->getContent())->toEqual(config('very_basic_auth.error_message'));
});
test('request with incorrect credentials fails - hashed password', function () {
config()->set('very_basic_auth.user', 'test');
config()->set('very_basic_auth.password', app()->make('hash')->make('test'));
$response = withHeaders([
'PHP_AUTH_USER' => str_random(20),
'PHP_AUTH_PW' => str_random(20),
])->get('/');
expect($response->getStatusCode())->toEqual(401);
});
test('request with incorrect credentials fails - json', function () {
$response = withHeaders([
'PHP_AUTH_USER' => str_random(20),
'PHP_AUTH_PW' => str_random(20),
'Accept' => 'application/json',
])->get('/');
$content = json_decode($response->getContent());
expect($response->getStatusCode())->toEqual(401);
expect($response->headers->get('content-type'))->toEqual('application/json');
expect(json_last_error())->toEqual(JSON_ERROR_NONE);
expect($content->message)->toEqual(config('very_basic_auth.error_message'));
expect($response->headers->get('WWW-Authenticate'))->toEqual(sprintf('Basic realm="%s", charset="UTF-8"', config('very_basic_auth.realm')));
});
test('request with incorrect credentials fails - view', function () {
config()->set('very_basic_auth.error_view', 'very_basic_auth::default');
$response = withHeaders([
'PHP_AUTH_USER' => str_random(20),
'PHP_AUTH_PW' => str_random(20),
])->get('/');
expect($response->getStatusCode())->toEqual(401);
expect(requestHeader($response))->toEqual('text/html; charset=utf-8');
expect($response->headers->get('WWW-Authenticate'))->toEqual(sprintf('Basic realm="%s", charset="UTF-8"', config('very_basic_auth.realm')));
$this->assertStringContainsStringIgnoringCase('This is the default view for the olssonm/l5-very-basic-auth-package', $response->getContent());
});
test('request with correct credentials passes', function () {
$response = withHeaders([
'PHP_AUTH_USER' => config('very_basic_auth.user'),
'PHP_AUTH_PW' => config('very_basic_auth.password'),
])->get('/');
expect($response->getStatusCode())->toEqual(200);
expect($response->getContent())->toEqual('ok');
});
test('request with correct credentials passes - hashed password', function () {
config()->set('very_basic_auth.user', 'test');
config()->set('very_basic_auth.password', app()->make('hash')->make('test'));
$response = withHeaders([
'PHP_AUTH_USER' => 'test',
'PHP_AUTH_PW' => 'test',
])->get('/');
expect($response->getStatusCode())->toEqual(200);
expect($response->getContent())->toEqual('ok');
});
test('environments', function () {
config()->set('very_basic_auth.envs', ['production']);
get('/')->assertStatus(200);
config()->set('very_basic_auth.envs', ['local']);
get('/')->assertStatus(200);
config()->set('very_basic_auth.envs', ['*']);
get('/')->assertStatus(401);
config()->set('very_basic_auth.envs', ['testing']);
get('/')->assertStatus(401);
});
test('request with incorrect inline credentials fails', function () {
$response = withHeaders([
'PHP_AUTH_USER' => str_random(20),
'PHP_AUTH_PW' => str_random(20),
])->get('/inline');
expect($response->getStatusCode())->toEqual(401);
expect($response->getContent())->toEqual(config('very_basic_auth.error_message'));
});
test('request with correct inline credentials passes', function () {
$response = withHeaders([
'PHP_AUTH_USER' => config('very_basic_auth.user'),
'PHP_AUTH_PW' => config('very_basic_auth.password'),
])->get('/inline');
expect($response->getStatusCode())->toEqual(200);
expect($response->getContent())->toEqual('ok');
});
test('test response handlers', function () {
// Custom response handler
app()->bind(
ResponseHandler::class,
CustomResponseHandler::class
);
$response = get('/test');
expect($response->getStatusCode())->toEqual(401);
expect($response->getContent())->toEqual('Custom response');
// Default response handler
app()->bind(
ResponseHandler::class,
DefaultResponseHandler::class
);
$response = get('/test');
expect($response->getStatusCode())->toEqual(401);
expect($response->getContent())->toEqual(config('very_basic_auth.error_message'));
});
// Test for the console command PasswordGenerateCommand
test('console command sets password in .env file', function () {
$envPath = base_path('.env');
// Clean up any existing .env before the test
if (file_exists($envPath)) {
unlink($envPath);
}
// Create a fresh .env
file_put_contents($envPath, "APP_NAME=Laravel\nBASIC_AUTH_PASSWORD=test");
$password = 'password' . uniqid();
// Simulate user input for the console command
$this->artisan('very-basic-auth:generate-password')
->expectsQuestion('Please enter a password for the very basic auth', $password)
->expectsQuestion('Please confirm your password', $password)
->assertExitCode(0);
// Reload env-variables to make sure the newest value is available
$this->artisan('config:cache');
$hashedPassword = config('very_basic_auth.password');
expect($hashedPassword)->not->toBeNull();
expect(app()->make('hash')->check($password, $hashedPassword))->toBeTrue();
expect(config('app.name'))->toEqual('Laravel');
});
function requestHeader($response): string
{
return Str::lower($response->headers->get('content-type'));
}
gitextract_4ggz17vw/
├── .editorconfig
├── .github/
│ ├── FUNDING.yml
│ └── workflows/
│ └── test.yml
├── .gitignore
├── LICENSE.md
├── README.jp.md
├── README.md
├── composer.json
├── phpstan.neon
├── phpunit.xml
├── src/
│ ├── Console/
│ │ └── GeneratePassword.php
│ ├── Handlers/
│ │ ├── DefaultResponseHandler.php
│ │ └── ResponseHandler.php
│ ├── Http/
│ │ └── Middleware/
│ │ └── VeryBasicAuth.php
│ ├── VeryBasicAuthServiceProvider.php
│ ├── config.php
│ └── resources/
│ └── views/
│ └── default.blade.php
└── tests/
├── Fixtures/
│ └── CustomResponseHandler.php
├── Pest.php
├── TestCase.php
└── VeryBasicAuthTest.php
SYMBOL INDEX (27 symbols across 8 files)
FILE: src/Console/GeneratePassword.php
class GeneratePassword (line 8) | #[AsCommand('very-basic-auth:generate-password')]
method handle (line 30) | public function handle(): int
method promptForValidPassword (line 44) | protected function promptForValidPassword(): string
method isPasswordAccepted (line 66) | protected function isPasswordAccepted(?string $password): bool
method passwordsMatch (line 74) | protected function passwordsMatch(string $password): bool
method hashPassword (line 82) | protected function hashPassword(string $password): string
method writeNewEnvironmentFileWith (line 93) | protected function writeNewEnvironmentFileWith(string $password): bool
method passwordReplacementPattern (line 119) | protected function passwordReplacementPattern(): string
FILE: src/Handlers/DefaultResponseHandler.php
class DefaultResponseHandler (line 9) | class DefaultResponseHandler implements ResponseHandler
method __invoke (line 11) | public function __invoke(Request $request): Response|JsonResponse
FILE: src/Handlers/ResponseHandler.php
type ResponseHandler (line 9) | interface ResponseHandler
method __invoke (line 11) | public function __invoke(Request $request): Response|JsonResponse;
FILE: src/Http/Middleware/VeryBasicAuth.php
class VeryBasicAuth (line 12) | class VeryBasicAuth
method __construct (line 16) | public function __construct(ResponseHandler $responseHandler)
method handle (line 27) | public function handle(Request $request, Closure $next, $username = nu...
method deniedResponse (line 69) | private function deniedResponse(Request $request): Response|JsonResponse
FILE: src/VeryBasicAuthServiceProvider.php
class VeryBasicAuthServiceProvider (line 10) | class VeryBasicAuthServiceProvider extends ServiceProvider
method __construct (line 32) | public function __construct($app)
method boot (line 44) | public function boot(\Illuminate\Routing\Router $router)
method register (line 70) | public function register()
FILE: tests/Fixtures/CustomResponseHandler.php
class CustomResponseHandler (line 10) | class CustomResponseHandler implements ResponseHandler
method __invoke (line 12) | public function __invoke(Request $request): Response|JsonResponse
FILE: tests/TestCase.php
class TestCase (line 8) | abstract class TestCase extends OrchestraTestCase
method setUp (line 10) | protected function setUp(): void
method getPackageProviders (line 15) | protected function getPackageProviders($app)
method tearDownAfterClass (line 22) | public static function tearDownAfterClass(): void
FILE: tests/VeryBasicAuthTest.php
function requestHeader (line 213) | function requestHeader($response): string
Condensed preview — 21 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (42K chars).
[
{
"path": ".editorconfig",
"chars": 344,
"preview": "; This file is for unifying the coding style for different editors and IDEs.\n; More information at http://editorconfig.o"
},
{
"path": ".github/FUNDING.yml",
"chars": 65,
"preview": "# These are supported funding model platforms\n\ngithub: [olssonm]\n"
},
{
"path": ".github/workflows/test.yml",
"chars": 950,
"preview": "name: Run tests\n\non:\n push:\n pull_request:\n\njobs:\n php-tests:\n runs-on: ubuntu-latest\n\n strategy:\n matrix:"
},
{
"path": ".gitignore",
"chars": 84,
"preview": "/vendor\ncomposer.lock\n.DS_Store\n.phpunit.result.cache\n.phpunit.cache\nphpunit-output\n"
},
{
"path": "LICENSE.md",
"chars": 1140,
"preview": "# The MIT License (MIT)\n\nCopyright (c) 2024 Marcus Olsson <contact@marcusolsson.me>\n\n> Permission is hereby granted, fre"
},
{
"path": "README.jp.md",
"chars": 4226,
"preview": "# Laravel Very Basic Auth\n\n[![Latest Version on Packagist][ico-version]][link-packagist]\n[![Total downloads][ico-downloa"
},
{
"path": "README.md",
"chars": 7087,
"preview": "# Laravel Very Basic Auth\n\n[![Latest Version on Packagist][ico-version]][link-packagist]\n[![Total downloads][ico-downloa"
},
{
"path": "composer.json",
"chars": 1882,
"preview": "{\n \"name\": \"olssonm/l5-very-basic-auth\",\n \"description\": \"Laravel stateless HTTP basic auth without the need for a"
},
{
"path": "phpstan.neon",
"chars": 107,
"preview": "parameters:\n level: 8\n paths:\n - src\n ignoreErrors:\n - identifier: missingType.generics\n"
},
{
"path": "phpunit.xml",
"chars": 746,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<phpunit\n xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n xsi:noName"
},
{
"path": "src/Console/GeneratePassword.php",
"chars": 3342,
"preview": "<?php\n\nnamespace Olssonm\\VeryBasicAuth\\Console;\n\nuse Illuminate\\Console\\Command;\nuse Symfony\\Component\\Console\\Attribute"
},
{
"path": "src/Handlers/DefaultResponseHandler.php",
"chars": 1069,
"preview": "<?php\n\nnamespace Olssonm\\VeryBasicAuth\\Handlers;\n\nuse Illuminate\\Http\\JsonResponse;\nuse Illuminate\\Http\\Request;\nuse Ill"
},
{
"path": "src/Handlers/ResponseHandler.php",
"chars": 245,
"preview": "<?php\n\nnamespace Olssonm\\VeryBasicAuth\\Handlers;\n\nuse Illuminate\\Http\\JsonResponse;\nuse Illuminate\\Http\\Request;\nuse Ill"
},
{
"path": "src/Http/Middleware/VeryBasicAuth.php",
"chars": 2144,
"preview": "<?php\n\nnamespace Olssonm\\VeryBasicAuth\\Http\\Middleware;\n\nuse Closure;\nuse Illuminate\\Http\\JsonResponse;\nuse Illuminate\\H"
},
{
"path": "src/VeryBasicAuthServiceProvider.php",
"chars": 1941,
"preview": "<?php\n\nnamespace Olssonm\\VeryBasicAuth;\n\nuse Illuminate\\Support\\ServiceProvider;\nuse Olssonm\\VeryBasicAuth\\Console\\Gener"
},
{
"path": "src/config.php",
"chars": 1027,
"preview": "<?php\n\n/**\n * Configuration for the \"HTTP Very Basic Auth\"-middleware\n */\n\nreturn [\n // Username\n 'user' => env('B"
},
{
"path": "src/resources/views/default.blade.php",
"chars": 1189,
"preview": "<!DOCTYPE html>\n<html>\n <head>\n <meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n <t"
},
{
"path": "tests/Fixtures/CustomResponseHandler.php",
"chars": 392,
"preview": "<?php\n\nnamespace Olssonm\\VeryBasicAuth\\Tests\\Fixtures;\n\nuse Illuminate\\Http\\JsonResponse;\nuse Illuminate\\Http\\Request;\nu"
},
{
"path": "tests/Pest.php",
"chars": 752,
"preview": "<?php\n\nuse Illuminate\\Support\\Facades\\Route;\nuse Olssonm\\VeryBasicAuth\\Http\\Middleware\\VeryBasicAuth;\nuse Olssonm\\VeryBa"
},
{
"path": "tests/TestCase.php",
"chars": 531,
"preview": "<?php\n\nnamespace Olssonm\\VeryBasicAuth\\Tests;\n\nuse Olssonm\\VeryBasicAuth\\VeryBasicAuthServiceProvider;\nuse Orchestra\\Tes"
},
{
"path": "tests/VeryBasicAuthTest.php",
"chars": 7748,
"preview": "<?php\n\nuse Illuminate\\Support\\Str;\nuse Olssonm\\VeryBasicAuth\\Handlers\\DefaultResponseHandler;\nuse Olssonm\\VeryBasicAuth\\"
}
]
About this extraction
This page contains the full source code of the olssonm/l5-very-basic-auth GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 21 files (36.1 KB), approximately 10.1k tokens, and a symbol index with 27 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.