Skip to content

Commit 5155349

Browse files
committed
Initial commit
1 parent 3059814 commit 5155349

17 files changed

+442
-2
lines changed

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
.idea/
2+
/config/.env
3+
/vendor
4+
composer.lock

LICENSE

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
MIT License
22

3-
Copyright (c) 2022 Riculum
3+
Copyright (c) 2021 Riculum
44

55
Permission is hereby granted, free of charge, to any person obtaining a copy
66
of this software and associated documentation files (the "Software"), to deal

README.md

Lines changed: 120 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,120 @@
1-
# PHP-Auth
1+
# PHP-Auth
2+
A complete user authentication library written in PHP
3+
4+
## Installation
5+
Use the package manager [composer](https://getcomposer.org) to install the library.
6+
```bash
7+
composer require riculum/php-auth
8+
```
9+
10+
## Initial setup
11+
### Credentials
12+
The basic database settings can be set through environment variables. Add a `.env` file in the root of your project. Make sure the `.env` file is added to your `.gitignore` so it is not checked-in the code. By default, the library looks for the following variables:
13+
14+
* DB_HOST
15+
* DB_NAME
16+
* DB_USERNAME
17+
* DB_PASSWORD
18+
* DB_PREFIX
19+
20+
More information how to use environment variables [here](https://github.com/vlucas/phpdotenv)
21+
22+
### Database
23+
```sql
24+
CREATE TABLE IF NOT EXISTS user (
25+
id INT(11) UNSIGNED AUTO_INCREMENT PRIMARY KEY,
26+
uuid VARCHAR(50) NOT NULL UNIQUE,
27+
firstname VARCHAR(50) NOT NULL,
28+
lastname VARCHAR(50) NOT NULL,
29+
email VARCHAR(100) NOT NULL UNIQUE,
30+
password VARCHAR(255) NOT NULL,
31+
token VARCHAR(255) NOT NULL,
32+
attempts TINYINT NOT NULL DEFAULT 0,
33+
online TINYINT NOT NULL DEFAULT 0,
34+
verified TINYINT NOT NULL DEFAULT 0,
35+
enabled TINYINT NOT NULL DEFAULT 1,
36+
updatedAt TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
37+
createdAt DATETIME DEFAULT CURRENT_TIMESTAMP
38+
)
39+
```
40+
41+
*Note: We recommend to set a database prefix*
42+
43+
### Configuration
44+
Import vendor/autoload.php and load the `.env` settings
45+
```php
46+
require_once 'vendor/autoload.php';
47+
48+
use Auth\Core\Authentication as Auth;
49+
50+
$dotenv = Dotenv\Dotenv::createImmutable(__DIR__);
51+
$dotenv->load();
52+
```
53+
54+
## Usage
55+
### Registration
56+
Use an associative array with user data to register a new user
57+
```php
58+
$user = array(
59+
'firstname' => 'John',
60+
'lastname' => 'Doe',
61+
'email' => '[email protected]', //must be unique
62+
'password' => '$2y$10$jNtkQSKNni2ELyoi9Y/lpedy7v92FYzqz5ePm1M6jPGY9hb8TCmAq',
63+
'token' => md5(uniqid(rand(), true))
64+
);
65+
66+
try {
67+
echo Auth::register($user);
68+
} catch (UserAlreadyExistsException $e) {
69+
echo 'User with the specified email address already exists';
70+
} catch (Exception $e) {
71+
echo "Something went wrong";
72+
}
73+
```
74+
75+
### Login
76+
```php
77+
try {
78+
Auth::login('[email protected]', '123456');
79+
echo 'Login successful';
80+
} catch (InvalidEmailException | InvalidPasswordException $e) {
81+
echo 'Email or Password are wrong';
82+
} catch(UserNotEnabledException $e) {
83+
echo 'User account has been deactivated';
84+
} catch (TooManyAttemptsException $e) {
85+
echo 'Too many failed login attempts';
86+
} catch (Exception $e) {
87+
echo "Something went wrong";
88+
}
89+
```
90+
91+
### Verify
92+
```php
93+
if (Auth::verify()) {
94+
echo "Authorization successful";
95+
} else {
96+
echo "Authorization failed";
97+
}
98+
```
99+
### Logout
100+
```php
101+
try {
102+
Auth::logout();
103+
} catch (Exception $e) {
104+
echo 'Something went wrong';
105+
}
106+
```
107+
108+
## Bugreport & Contribution
109+
If you find a bug, please either create a ticket in github, or initiate a pull request
110+
111+
## Versioning
112+
We adhere to semantic (major.minor.patch) versioning (https://semver.org/). This means that:
113+
114+
* Patch (x.x.patch) versions fix bugs
115+
* Minor (x.minor.x) versions introduce new, backwards compatible features or improve existing code.
116+
* Major (major.x.x) versions introduce radical changes which are not backwards compatible.
117+
118+
In your automation or procedure you can always safely update patch & minor versions without the risk of your application failing.
119+
120+

composer.json

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
{
2+
"name": "riculum/php-auth",
3+
"description": "A complete user authentication library written in PHP",
4+
"type": "library",
5+
"license": "MIT",
6+
"authors": [
7+
{
8+
"name": "Riculum",
9+
"email": "[email protected]"
10+
}
11+
],
12+
"autoload": {
13+
"psr-4": {
14+
"Auth\\" : "./"
15+
}
16+
},
17+
"require": {
18+
"vlucas/phpdotenv": "^5.3",
19+
"riculum/php-pdo": "^1.0"
20+
},
21+
"require-dev": {
22+
"phpunit/phpunit": "^9"
23+
}
24+
}

config/.env.example

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
DB_HOST=
2+
DB_NAME=
3+
DB_USERNAME=
4+
DB_PASSWORD=
5+
DB_PREFIX=

core/Authentication.php

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
<?php
2+
namespace Auth\Core;
3+
4+
use Auth\Exceptions\InvalidEmailException;
5+
use Auth\Exceptions\InvalidPasswordException;
6+
use Auth\Exceptions\TooManyAttemptsException;
7+
use Auth\Exceptions\UserAlreadyExistsException;
8+
use Auth\Exceptions\UserNotEnabledException;
9+
10+
class Authentication
11+
{
12+
private const MAX_LOGIN_ATTEMPTS = 5;
13+
14+
/**
15+
* @throws UserAlreadyExistsException
16+
*/
17+
static function register(array $user): ?int
18+
{
19+
return User::addUser($user);
20+
}
21+
22+
/**
23+
* @throws InvalidEmailException
24+
* @throws InvalidPasswordException
25+
* @throws TooManyAttemptsException
26+
* @throws UserNotEnabledException
27+
*/
28+
static function login(string $email, string $password): bool
29+
{
30+
$currentUser = User::getUserByEmail($email);
31+
32+
if (empty($currentUser)) {
33+
throw new InvalidEmailException('E-Mail address could not be found');
34+
}
35+
36+
if (password_verify($password, $currentUser['password']) && $currentUser['attempts'] < self::MAX_LOGIN_ATTEMPTS && $currentUser['enabled'] == 1) {
37+
User::login($currentUser['id']);
38+
} else if ($currentUser['enabled'] != 1) {
39+
throw new UserNotEnabledException('User account has been deactivated');
40+
} else if ($currentUser['attempts'] >= self::MAX_LOGIN_ATTEMPTS) {
41+
throw new TooManyAttemptsException('Too many failed login attempts');
42+
} else {
43+
User::setUser($currentUser['id'], ['attempts' => $currentUser['attempts'] + 1]);
44+
throw new InvalidPasswordException('Incorrect Password');
45+
}
46+
47+
return true;
48+
}
49+
50+
static function logout()
51+
{
52+
if (!empty(Session::getUserId())) {
53+
User::logout();
54+
}
55+
}
56+
57+
static function verify(): bool
58+
{
59+
$sessionToken = Session::getUserToken();
60+
$sessionUserId = Session::getUserId();
61+
62+
if (empty($sessionUserId) || empty($sessionToken)) {
63+
return false;
64+
}
65+
66+
$userToken = User::getUser($sessionUserId)['token'];
67+
68+
if (empty($userToken)) {
69+
return false;
70+
}
71+
72+
if ($sessionToken === $userToken) {
73+
return true;
74+
}
75+
76+
return false;
77+
}
78+
}

core/Session.php

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
<?php
2+
namespace Auth\Core;
3+
4+
if (session_status() == PHP_SESSION_NONE) {
5+
session_start();
6+
}
7+
8+
class Session {
9+
10+
public static function destroySession()
11+
{
12+
session_destroy();
13+
}
14+
15+
/**
16+
* @return string|null
17+
*/
18+
static function getUserToken(): ?string
19+
{
20+
return $_SESSION['userToken'] ?? null;
21+
}
22+
23+
/**
24+
* @return int|null
25+
*/
26+
static function getUserId(): ?int
27+
{
28+
return $_SESSION['userId'] ?? null;
29+
}
30+
31+
/**
32+
* @param string $token
33+
*/
34+
static function setUserToken(string $token)
35+
{
36+
$_SESSION['userToken'] = $token;
37+
}
38+
39+
40+
static function setUserId(int $id)
41+
{
42+
$_SESSION['userId'] = $id;
43+
}
44+
}

0 commit comments

Comments
 (0)