Skip to content
This repository was archived by the owner on Aug 11, 2023. It is now read-only.

Commit 31edc4d

Browse files
committed
Version 1.0
1 parent 99a3582 commit 31edc4d

File tree

5 files changed

+155
-0
lines changed

5 files changed

+155
-0
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
/.idea

composer.json

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
{
2+
"name": "payfast/laravel-validate-pwned-password",
3+
"description": "Adds Laravel validator rule to check if a password has been pwned from https://haveibeenpwned.com/API/v2",
4+
"license": "GPL-3.0-only",
5+
"type": "package",
6+
"authors": [
7+
{
8+
"name": "Charl Retief",
9+
"email": "[email protected]"
10+
}
11+
],
12+
"minimum-stability": "dev",
13+
"require": {
14+
"php": ">=5.6.0"
15+
},
16+
"autoload": {
17+
"psr-4": {
18+
"PayFast\\": "src/"
19+
}
20+
},
21+
"extra": {
22+
"laravel": {
23+
"providers": [
24+
"PayFast\\Providers\\PwnedPasswordServiceProvider"
25+
]
26+
}
27+
}
28+
}

readme.md

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# Laravel Pwned Password Validator
2+
3+
Adds a Laravel validator rule that checks if a password has been pwned in any public data breaches.
4+
This uses Troy Hunt's Pwned Password API https://haveibeenpwned.com/API/v2 to check for pwned passwords.
5+
6+
## Installation
7+
Using composer:
8+
```
9+
composer require "payfast/laravel-validate-pwned-password":"^1.0"
10+
```
11+
12+
For old verions of Laravel (<5.5) and Lumen you may need to manually register the service provider. Add in `bootstrap/app.php`
13+
```php
14+
$app->register('PayFast\\Providers\\PwnedPasswordServiceProvider');
15+
```
16+
17+
## Usage
18+
When using Laravel Validation you can now add a new rule `pwnedpassword` to any field that will contain a password. This rule will fail the input if the supplied value matches a known pwned password.
19+
20+
Example:
21+
22+
```php
23+
return Validator::make($data, [
24+
'password' => 'required|string|min:8|pwnedpassword|confirmed',
25+
]);
26+
```
27+
28+
## Customization
29+
To change the error message add a language string to `resources/lang/en/validation.php`
30+
```php
31+
'pwnedpassword' => 'This :attribute is not secure. It appears :count times in the Pwned Passwords database of security breaches. For more information: https://haveibeenpwned.com/Passwords'
32+
```

src/Lib/PwnedPassword.php

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
<?php
2+
3+
namespace PayFast\Lib;
4+
5+
class PwnedPassword
6+
{
7+
public static $breachCount;
8+
9+
/**
10+
* Validate function called by the validator
11+
*
12+
* @param $attribute
13+
* @param $value
14+
* @param $parameters
15+
* @param $validator
16+
* @return bool
17+
*/
18+
public function validate($attribute, $value, $parameters, $validator)
19+
{
20+
$hash = sha1($value);
21+
22+
$ch = curl_init();
23+
curl_setopt($ch, CURLOPT_URL, 'https://api.pwnedpasswords.com/range/' . substr($hash, 0, 5));
24+
curl_setopt($ch, CURLOPT_USERAGENT, 'PHP - Laravel Pwned Password Validator');
25+
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
26+
$results = curl_exec($ch);
27+
$httpcode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
28+
curl_close($ch);
29+
30+
if (($httpcode !== 200) || empty($results)) {
31+
//hmm if don't get normal 200 response code or empty result then just stop
32+
return true;
33+
}
34+
35+
if (preg_match('/' . preg_quote(substr($hash, 5)) . ':([0-9]+)/ism', $results, $matches) == 1) {
36+
self::$breachCount = $matches[1];
37+
return false;
38+
}
39+
40+
return true;
41+
}
42+
43+
/**
44+
* Generate the error message displayed for a pwned password
45+
*
46+
* @param $message
47+
* @param $attribute
48+
* @param $rule
49+
* @param $parameters
50+
* @return mixed|string
51+
*/
52+
public function message($message, $attribute, $rule, $parameters)
53+
{
54+
if ($message == 'validation.pwnedpassword') {
55+
$message = 'This :attribute is not secure. It appears :count times in the Pwned Passwords database of security breaches. For more information: https://haveibeenpwned.com/Passwords';
56+
}
57+
58+
$message = str_replace(':ATTRIBUTE', strtoupper($attribute), $message);
59+
$message = str_replace(':Attribute', ucwords($attribute), $message);
60+
$message = str_replace(':attribute', $attribute, $message);
61+
$message = str_ireplace(':count', self::$breachCount, $message);
62+
return $message;
63+
}
64+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
<?php
2+
3+
namespace PayFast\Providers;
4+
5+
use Illuminate\Support\ServiceProvider;
6+
use Illuminate\Support\Facades\Validator;
7+
8+
class PwnedPasswordServiceProvider extends ServiceProvider
9+
{
10+
/**
11+
* Boot the application events.
12+
*
13+
* @return void
14+
*/
15+
public function boot()
16+
{
17+
Validator::extend('pwnedpassword', 'PayFast\Lib\PwnedPassword@validate');
18+
Validator::replacer('pwnedpassword', 'PayFast\Lib\PwnedPassword@message');
19+
}
20+
21+
/**
22+
* Get the services provided by the provider.
23+
*
24+
* @return array
25+
*/
26+
public function provides()
27+
{
28+
return ['PayFast\\Providers\\PwnedPasswordServiceProvider'];
29+
}
30+
}

0 commit comments

Comments
 (0)