mirror of
https://github.com/delight-im/PHP-Auth.git
synced 2025-08-08 09:06:29 +02:00
Compare commits
34 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
739fa7d574 | ||
|
302feb5da2 | ||
|
2ded232d8e | ||
|
70a905afd7 | ||
|
84f3ad10a9 | ||
|
81091df66b | ||
|
8926e7e708 | ||
|
eec450677f | ||
|
f1360dceba | ||
|
2cf7b27ba3 | ||
|
ecd8015acf | ||
|
1eedfd0e02 | ||
|
757579523c | ||
|
d695328a5a | ||
|
71506eaa05 | ||
|
ce8dbbc436 | ||
|
d181219e40 | ||
|
891cef2511 | ||
|
f70613b2b8 | ||
|
59816d1a40 | ||
|
1284f64f04 | ||
|
8165e8917b | ||
|
a4b68167a1 | ||
|
fc2fb4bb44 | ||
|
b2a3fde696 | ||
|
36880b87c9 | ||
|
4a66965994 | ||
|
e7b590dc80 | ||
|
33d2384c93 | ||
|
1169856217 | ||
|
fa75811679 | ||
|
fa8fa4887e | ||
|
8fecb86f15 | ||
|
04c466b309 |
57
Migration.md
57
Migration.md
@@ -1,6 +1,7 @@
|
|||||||
# Migration
|
# Migration
|
||||||
|
|
||||||
* [General](#general)
|
* [General](#general)
|
||||||
|
* [From `v6.x.x` to `v7.x.x`](#from-v6xx-to-v7xx)
|
||||||
* [From `v5.x.x` to `v6.x.x`](#from-v5xx-to-v6xx)
|
* [From `v5.x.x` to `v6.x.x`](#from-v5xx-to-v6xx)
|
||||||
* [From `v4.x.x` to `v5.x.x`](#from-v4xx-to-v5xx)
|
* [From `v4.x.x` to `v5.x.x`](#from-v4xx-to-v5xx)
|
||||||
* [From `v3.x.x` to `v4.x.x`](#from-v3xx-to-v4xx)
|
* [From `v3.x.x` to `v4.x.x`](#from-v3xx-to-v4xx)
|
||||||
@@ -15,6 +16,62 @@ Update your version of this library via Composer [[?]](https://github.com/deligh
|
|||||||
$ composer update delight-im/auth
|
$ composer update delight-im/auth
|
||||||
```
|
```
|
||||||
|
|
||||||
|
If you want to perform a major version upgrade (e.g. from version `1.x.x` to version `2.x.x`), the version constraints defined in your `composer.json` [[?]](https://github.com/delight-im/Knowledge/blob/master/Composer%20(PHP).md) may not allow this. In that case, just add the dependency again to overwrite it with the latest version (or optionally with a specified version):
|
||||||
|
|
||||||
|
```
|
||||||
|
$ composer require delight-im/auth
|
||||||
|
```
|
||||||
|
|
||||||
|
## From `v6.x.x` to `v7.x.x`
|
||||||
|
|
||||||
|
* The method `logOutButKeepSession` from class `Auth` is now simply called `logOut`. Therefore, the former method `logout` is now called `logOutAndDestroySession`. With both methods, mind the capitalization of the letter “O”.
|
||||||
|
|
||||||
|
* The second argument of the `Auth` constructor, which was named `$useHttps`, has been removed. If you previously had it set to `true`, make sure to set the value of the `session.cookie_secure` directive to `1` now. You may do so either directly in your [PHP configuration](http://php.net/manual/en/configuration.file.php) (`php.ini`), via the `\ini_set` method or via the `\session_set_cookie_params` method. Otherwise, make sure that directive is set to `0`.
|
||||||
|
|
||||||
|
* The third argument of the `Auth` constructor, which was named `$allowCookiesScriptAccess`, has been removed. If you previously had it set to `true`, make sure to set the value of the `session.cookie_httponly` directive to `0` now. You may do so either directly in your [PHP configuration](http://php.net/manual/en/configuration.file.php) (`php.ini`), via the `\ini_set` method or via the `\session_set_cookie_params` method. Otherwise, make sure that directive is set to `1`.
|
||||||
|
|
||||||
|
* Only if *both* of the following two conditions are met:
|
||||||
|
|
||||||
|
* The directive `session.cookie_domain` is set to an empty value. It may have been set directly in your [PHP configuration](http://php.net/manual/en/configuration.file.php) (`php.ini`), via the `\ini_set` method or via the `\session_set_cookie_params` method. You can check the value of that directive by executing the following statement somewhere in your application:
|
||||||
|
|
||||||
|
```php
|
||||||
|
\var_dump(\ini_get('session.cookie_domain'));
|
||||||
|
```
|
||||||
|
|
||||||
|
* Your application is accessed via a registered or registrable *domain name*, either by yourself during development and testing or by your visitors and users in production. That means your application is *not*, or *not only*, accessed via `localhost` or via an IP address.
|
||||||
|
|
||||||
|
Then the domain scope for the [two cookies](README.md#cookies) used by this library has changed. You can handle this change in one of two different ways:
|
||||||
|
|
||||||
|
* Restore the old behavior by placing the following statement as early as possible in your application, and before you create the `Auth` instance:
|
||||||
|
|
||||||
|
```php
|
||||||
|
\ini_set('session.cookie_domain', \preg_replace('/^www\./', '', $_SERVER['HTTP_HOST']));
|
||||||
|
```
|
||||||
|
|
||||||
|
You may also evaluate the complete second parameter and put its value directly into your [PHP configuration](http://php.net/manual/en/configuration.file.php) (`php.ini`).
|
||||||
|
|
||||||
|
* Use the new domain scope for your application. To do so, you only need to [rename the cookies](README.md#renaming-the-librarys-cookies) used by this library in order to prevent conflicts with old cookies that have been created previously. Renaming the cookies is critically important here. We recommend a versioned name such as `session_v1` for the session cookie.
|
||||||
|
|
||||||
|
* Only if *both* of the following two conditions are met:
|
||||||
|
|
||||||
|
* The directive `session.cookie_domain` is set to a value that starts with the `www` subdomain. It may have been set directly in your [PHP configuration](http://php.net/manual/en/configuration.file.php) (`php.ini`), via the `\ini_set` method or via the `\session_set_cookie_params` method. You can check the value of that directive by executing the following statement somewhere in your application:
|
||||||
|
|
||||||
|
```php
|
||||||
|
\var_dump(\ini_get('session.cookie_domain'));
|
||||||
|
```
|
||||||
|
|
||||||
|
* Your application is accessed via a registered or registrable *domain name*, either by yourself during development and testing or by your visitors and users in production. That means your application is *not*, or *not only*, accessed via `localhost` or via an IP address.
|
||||||
|
|
||||||
|
Then the domain scope for [one of the cookies](README.md#cookies) used by this library has changed. To make your application work correctly with the new scope, [rename the cookies](README.md#renaming-the-librarys-cookies) used by this library in order to prevent conflicts with old cookies that have been created previously. Renaming the cookies is critically important here. We recommend a versioned name such as `session_v1` for the session cookie.
|
||||||
|
|
||||||
|
* If the directive `session.cookie_path` is set to an empty value, then the path scope for [one of the cookies](README.md#cookies) used by this library has changed. To make your application work correctly with the new scope, [rename the cookies](README.md#renaming-the-librarys-cookies) used by this library in order to prevent conflicts with old cookies that have been created previously. Renaming the cookies is critically important here. We recommend a versioned name such as `session_v1` for the session cookie.
|
||||||
|
|
||||||
|
The directive may have been set directly in your [PHP configuration](http://php.net/manual/en/configuration.file.php) (`php.ini`), via the `\ini_set` method or via the `\session_set_cookie_params` method. You can check the value of that directive by executing the following statement somewhere in your application:
|
||||||
|
|
||||||
|
```php
|
||||||
|
\var_dump(\ini_get('session.cookie_path'));
|
||||||
|
```
|
||||||
|
|
||||||
## From `v5.x.x` to `v6.x.x`
|
## From `v5.x.x` to `v6.x.x`
|
||||||
|
|
||||||
* The database schema has changed.
|
* The database schema has changed.
|
||||||
|
150
README.md
150
README.md
@@ -79,6 +79,12 @@ Migrating from an earlier version of this project? See our [upgrade guide](Migra
|
|||||||
* [Assigning roles to users](#assigning-roles-to-users)
|
* [Assigning roles to users](#assigning-roles-to-users)
|
||||||
* [Taking roles away from users](#taking-roles-away-from-users)
|
* [Taking roles away from users](#taking-roles-away-from-users)
|
||||||
* [Checking roles](#checking-roles-1)
|
* [Checking roles](#checking-roles-1)
|
||||||
|
* [Cookies](#cookies)
|
||||||
|
* [Renaming the library’s cookies](#renaming-the-librarys-cookies)
|
||||||
|
* [Defining the domain scope for cookies](#defining-the-domain-scope-for-cookies)
|
||||||
|
* [Restricting the path where cookies are available](#restricting-the-path-where-cookies-are-available)
|
||||||
|
* [Controlling client-side script access to cookies](#controlling-client-side-script-access-to-cookies)
|
||||||
|
* [Configuring transport security for cookies](#configuring-transport-security-for-cookies)
|
||||||
* [Utilities](#utilities)
|
* [Utilities](#utilities)
|
||||||
* [Creating a random string](#creating-a-random-string)
|
* [Creating a random string](#creating-a-random-string)
|
||||||
* [Creating a UUID v4 as per RFC 4122](#creating-a-uuid-v4-as-per-rfc-4122)
|
* [Creating a UUID v4 as per RFC 4122](#creating-a-uuid-v4-as-per-rfc-4122)
|
||||||
@@ -102,13 +108,9 @@ $auth = new \Delight\Auth\Auth($db);
|
|||||||
|
|
||||||
If you have an open `PDO` connection already, just re-use it.
|
If you have an open `PDO` connection already, just re-use it.
|
||||||
|
|
||||||
If you do enforce HTTPS on your site, pass `true` as the second parameter to the constructor. This is optional and the default is `false`.
|
If your web server is behind a proxy server and `$_SERVER['REMOTE_ADDR']` only contains the proxy’s IP address, you must pass the user’s real IP address to the constructor in the second argument, which is named `$ipAddress`. The default is `null`.
|
||||||
|
|
||||||
Only in the very rare case that you need access to your cookies from JavaScript, pass `true` as the third argument to the constructor. This is optional and the default is `false`. There is almost always a *better* solution than enabling this, however.
|
Should your database tables for this library need a common prefix, e.g. `my_users` instead of `users` (and likewise for the other tables), pass the prefix (e.g. `my_`) as the third parameter to the constructor, which is named `$dbTablePrefix`. This is optional and the prefix is empty by default.
|
||||||
|
|
||||||
If your web server is behind a proxy server and `$_SERVER['REMOTE_ADDR']` only contains the proxy’s IP address, you must pass the user’s real IP address to the constructor in the fourth argument. The default is `null`.
|
|
||||||
|
|
||||||
Should your database tables for this library need a common prefix, e.g. `my_users` instead of `users` (and likewise for the other tables), pass the prefix (e.g. `my_`) as the fifth parameter to the constructor. This is optional and the prefix is empty by default.
|
|
||||||
|
|
||||||
### Registration (sign up)
|
### Registration (sign up)
|
||||||
|
|
||||||
@@ -405,9 +407,9 @@ $url = 'https://www.example.com/verify_email?selector=' . \urlencode($selector)
|
|||||||
### Logout
|
### Logout
|
||||||
|
|
||||||
```php
|
```php
|
||||||
$auth->logOutButKeepSession();
|
$auth->logOut();
|
||||||
// or
|
// or
|
||||||
$auth->logout();
|
$auth->logOutAndDestroySession();
|
||||||
|
|
||||||
// user has been signed out
|
// user has been signed out
|
||||||
```
|
```
|
||||||
@@ -896,6 +898,138 @@ catch (\Delight\Auth\UnknownIdException $e) {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Cookies
|
||||||
|
|
||||||
|
This library uses two cookies to keep state on the client: The first, whose name you can retrieve using
|
||||||
|
|
||||||
|
```php
|
||||||
|
\session_name();
|
||||||
|
```
|
||||||
|
|
||||||
|
is the general (mandatory) session cookie. The second (optional) cookie is only used for [persistent logins](#keeping-the-user-logged-in) and its name can be retrieved as follows:
|
||||||
|
|
||||||
|
```php
|
||||||
|
\Delight\Auth\Auth::createRememberCookieName();
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Renaming the library’s cookies
|
||||||
|
|
||||||
|
You can rename the session cookie used by this library through one of the following means, in order of recommendation:
|
||||||
|
|
||||||
|
* In the [PHP configuration](http://php.net/manual/en/configuration.file.php) (`php.ini`), find the line with the `session.name` directive and change its value to something like `session_v1`, as in:
|
||||||
|
|
||||||
|
```
|
||||||
|
session.name = session_v1
|
||||||
|
```
|
||||||
|
|
||||||
|
* As early as possible in your application, and before you create the `Auth` instance, call `\ini_set` to change `session.name` to something like `session_v1`, as in:
|
||||||
|
|
||||||
|
```php
|
||||||
|
\ini_set('session.name', 'session_v1');
|
||||||
|
```
|
||||||
|
|
||||||
|
For this to work, `session.auto_start` must be set to `0` in the [PHP configuration](http://php.net/manual/en/configuration.file.php) (`php.ini`).
|
||||||
|
|
||||||
|
* As early as possible in your application, and before you create the `Auth` instance, call `\session_name` with an argument like `session_v1`, as in:
|
||||||
|
|
||||||
|
```php
|
||||||
|
\session_name('session_v1');
|
||||||
|
```
|
||||||
|
|
||||||
|
For this to work, `session.auto_start` must be set to `0` in the [PHP configuration](http://php.net/manual/en/configuration.file.php) (`php.ini`).
|
||||||
|
|
||||||
|
The name of the cookie for [persistent logins](#keeping-the-user-logged-in) will change as well – automatically – following your change of the session cookie’s name.
|
||||||
|
|
||||||
|
#### Defining the domain scope for cookies
|
||||||
|
|
||||||
|
A cookie’s `domain` attribute controls which domain (and which subdomains) the cookie will be valid for, and thus where the user’s session and authentication state will be available.
|
||||||
|
|
||||||
|
The recommended default is an empty string, which means that the cookie will only be valid for the *exact* current host, *excluding* any subdomains that may exist. You should only use a different value if you need to share cookies between different subdomains. Often, you’ll want to share cookies between the bare domain and the `www` subdomain, but you might also want to share them between any other set of subdomains.
|
||||||
|
|
||||||
|
Whatever set of subdomains you choose, you should set the cookie’s attribute to the *most specific* domain name that still includes all your required subdomains. For example, to share cookies between `example.com` and `www.example.com`, you would set the attribute to `example.com`. But if you wanted to share cookies between `sub1.app.example.com` and `sub2.app.example.com`, you should set the attribute to `app.example.com`. Any explicitly specified domain name will always *include* all subdomains that may exist.
|
||||||
|
|
||||||
|
You can change the attribute through one of the following means, in order of recommendation:
|
||||||
|
|
||||||
|
* In the [PHP configuration](http://php.net/manual/en/configuration.file.php) (`php.ini`), find the line with the `session.cookie_domain` directive and change its value as desired, e.g.:
|
||||||
|
|
||||||
|
```
|
||||||
|
session.cookie_domain = example.com
|
||||||
|
```
|
||||||
|
|
||||||
|
* As early as possible in your application, and before you create the `Auth` instance, call `\ini_set` to change the value of the `session.cookie_domain` directive as desired, e.g.:
|
||||||
|
|
||||||
|
```php
|
||||||
|
\ini_set('session.cookie_domain', 'example.com');
|
||||||
|
```
|
||||||
|
|
||||||
|
For this to work, `session.auto_start` must be set to `0` in the [PHP configuration](http://php.net/manual/en/configuration.file.php) (`php.ini`).
|
||||||
|
|
||||||
|
#### Restricting the path where cookies are available
|
||||||
|
|
||||||
|
A cookie’s `path` attribute controls which directories (and subdirectories) the cookie will be valid for, and thus where the user’s session and authentication state will be available.
|
||||||
|
|
||||||
|
In most cases, you’ll want to make cookies available for all paths, i.e. any directory and file, starting in the root directory. That is what a value of `/` for the attribute does, which is also the recommended default. You should only change this attribute to a different value, e.g. `/path/to/subfolder`, if you want to restrict which directories your cookies will be available in, e.g. to host multiple applications side-by-side, in different directories, under the same domain name.
|
||||||
|
|
||||||
|
You can change the attribute through one of the following means, in order of recommendation:
|
||||||
|
|
||||||
|
* In the [PHP configuration](http://php.net/manual/en/configuration.file.php) (`php.ini`), find the line with the `session.cookie_path` directive and change its value as desired, e.g.:
|
||||||
|
|
||||||
|
```
|
||||||
|
session.cookie_path = /
|
||||||
|
```
|
||||||
|
|
||||||
|
* As early as possible in your application, and before you create the `Auth` instance, call `\ini_set` to change the value of the `session.cookie_path` directive as desired, e.g.:
|
||||||
|
|
||||||
|
```php
|
||||||
|
\ini_set('session.cookie_path', '/');
|
||||||
|
```
|
||||||
|
|
||||||
|
For this to work, `session.auto_start` must be set to `0` in the [PHP configuration](http://php.net/manual/en/configuration.file.php) (`php.ini`).
|
||||||
|
|
||||||
|
#### Controlling client-side script access to cookies
|
||||||
|
|
||||||
|
Using the `httponly` attribute, you can control whether client-side scripts, i.e. JavaScript, should be able to access your cookies or not. For security reasons, it is best to *deny* script access to your cookies, which reduces the damage that successful XSS attacks against your application could do, for example.
|
||||||
|
|
||||||
|
Thus, you should always set `httponly` to `1`, except for the rare cases where you really need access to your cookies from JavaScript and can’t find any better solution. In those cases, set the attribute to `0`, but be aware of the consequences.
|
||||||
|
|
||||||
|
You can change the attribute through one of the following means, in order of recommendation:
|
||||||
|
|
||||||
|
* In the [PHP configuration](http://php.net/manual/en/configuration.file.php) (`php.ini`), find the line with the `session.cookie_httponly` directive and change its value as desired, e.g.:
|
||||||
|
|
||||||
|
```
|
||||||
|
session.cookie_httponly = 1
|
||||||
|
```
|
||||||
|
|
||||||
|
* As early as possible in your application, and before you create the `Auth` instance, call `\ini_set` to change the value of the `session.cookie_httponly` directive as desired, e.g.:
|
||||||
|
|
||||||
|
```php
|
||||||
|
\ini_set('session.cookie_httponly', 1);
|
||||||
|
```
|
||||||
|
|
||||||
|
For this to work, `session.auto_start` must be set to `0` in the [PHP configuration](http://php.net/manual/en/configuration.file.php) (`php.ini`).
|
||||||
|
|
||||||
|
#### Configuring transport security for cookies
|
||||||
|
|
||||||
|
Using the `secure` attribute, you can control whether cookies should be sent over *any* connection, including plain HTTP, or whether a secure connection, i.e. HTTPS (with SSL/TLS), should be required. The former (less secure) mode can be chosen by setting the attribute to `0`, and the latter (more secure) mode can be chosen by setting the attribute to `1`.
|
||||||
|
|
||||||
|
Obviously, this solely depends on whether you are able to serve *all* pages exclusively via HTTPS. If you can, you should set the attribute to `1` and possibly combine it with HTTP redirects to the secure protocol and HTTP Strict Transport Security (HSTS). Otherwise, you may have to keep the attribute set to `0`.
|
||||||
|
|
||||||
|
You can change the attribute through one of the following means, in order of recommendation:
|
||||||
|
|
||||||
|
* In the [PHP configuration](http://php.net/manual/en/configuration.file.php) (`php.ini`), find the line with the `session.cookie_secure` directive and change its value as desired, e.g.:
|
||||||
|
|
||||||
|
```
|
||||||
|
session.cookie_secure = 1
|
||||||
|
```
|
||||||
|
|
||||||
|
* As early as possible in your application, and before you create the `Auth` instance, call `\ini_set` to change the value of the `session.cookie_secure` directive as desired, e.g.:
|
||||||
|
|
||||||
|
```php
|
||||||
|
\ini_set('session.cookie_secure', 1);
|
||||||
|
```
|
||||||
|
|
||||||
|
For this to work, `session.auto_start` must be set to `0` in the [PHP configuration](http://php.net/manual/en/configuration.file.php) (`php.ini`).
|
||||||
|
|
||||||
### Utilities
|
### Utilities
|
||||||
|
|
||||||
#### Creating a random string
|
#### Creating a random string
|
||||||
|
@@ -5,7 +5,7 @@
|
|||||||
"php": ">=5.6.0",
|
"php": ">=5.6.0",
|
||||||
"ext-openssl": "*",
|
"ext-openssl": "*",
|
||||||
"delight-im/base64": "^1.0",
|
"delight-im/base64": "^1.0",
|
||||||
"delight-im/cookie": "^2.1",
|
"delight-im/cookie": "^3.1",
|
||||||
"delight-im/db": "^1.2"
|
"delight-im/db": "^1.2"
|
||||||
},
|
},
|
||||||
"type": "library",
|
"type": "library",
|
||||||
|
12
composer.lock
generated
12
composer.lock
generated
@@ -4,7 +4,7 @@
|
|||||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
|
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
|
||||||
"This file is @generated automatically"
|
"This file is @generated automatically"
|
||||||
],
|
],
|
||||||
"content-hash": "8ab7c9ad8ef2bc7d9a6beb27f9bf4df5",
|
"content-hash": "54d541ae3c5ba25b0cc06688d2b65467",
|
||||||
"packages": [
|
"packages": [
|
||||||
{
|
{
|
||||||
"name": "delight-im/base64",
|
"name": "delight-im/base64",
|
||||||
@@ -49,16 +49,16 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "delight-im/cookie",
|
"name": "delight-im/cookie",
|
||||||
"version": "v2.1.3",
|
"version": "v3.1.0",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/delight-im/PHP-Cookie.git",
|
"url": "https://github.com/delight-im/PHP-Cookie.git",
|
||||||
"reference": "a66c8a02aa4776c4b7d3d04c695411f73e04e1eb"
|
"reference": "76ef2a21817cf7a034f85fc3f4d4bfc60f873947"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/delight-im/PHP-Cookie/zipball/a66c8a02aa4776c4b7d3d04c695411f73e04e1eb",
|
"url": "https://api.github.com/repos/delight-im/PHP-Cookie/zipball/76ef2a21817cf7a034f85fc3f4d4bfc60f873947",
|
||||||
"reference": "a66c8a02aa4776c4b7d3d04c695411f73e04e1eb",
|
"reference": "76ef2a21817cf7a034f85fc3f4d4bfc60f873947",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@@ -86,7 +86,7 @@
|
|||||||
"samesite",
|
"samesite",
|
||||||
"xss"
|
"xss"
|
||||||
],
|
],
|
||||||
"time": "2017-07-26T14:03:38+00:00"
|
"time": "2017-10-18T19:48:59+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "delight-im/db",
|
"name": "delight-im/db",
|
||||||
|
@@ -107,7 +107,7 @@ final class Administration extends UserManager {
|
|||||||
*/
|
*/
|
||||||
public function deleteUserByUsername($username) {
|
public function deleteUserByUsername($username) {
|
||||||
$userData = $this->getUserDataByUsername(
|
$userData = $this->getUserDataByUsername(
|
||||||
trim($username),
|
\trim($username),
|
||||||
[ 'id' ]
|
[ 'id' ]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
230
src/Auth.php
230
src/Auth.php
@@ -28,29 +28,24 @@ final class Auth extends UserManager {
|
|||||||
const SESSION_FIELD_STATUS = 'auth_status';
|
const SESSION_FIELD_STATUS = 'auth_status';
|
||||||
const SESSION_FIELD_ROLES = 'auth_roles';
|
const SESSION_FIELD_ROLES = 'auth_roles';
|
||||||
const SESSION_FIELD_REMEMBERED = 'auth_remembered';
|
const SESSION_FIELD_REMEMBERED = 'auth_remembered';
|
||||||
|
const COOKIE_PREFIXES = [ Cookie::PREFIX_SECURE, Cookie::PREFIX_HOST ];
|
||||||
const COOKIE_CONTENT_SEPARATOR = '~';
|
const COOKIE_CONTENT_SEPARATOR = '~';
|
||||||
const COOKIE_NAME_REMEMBER = 'auth_remember';
|
|
||||||
|
|
||||||
/** @var boolean whether HTTPS (TLS/SSL) will be used (recommended) */
|
|
||||||
private $useHttps;
|
|
||||||
/** @var boolean whether cookies should be accessible via client-side scripts (*not* recommended) */
|
|
||||||
private $allowCookiesScriptAccess;
|
|
||||||
/** @var string the user's current IP address */
|
/** @var string the user's current IP address */
|
||||||
private $ipAddress;
|
private $ipAddress;
|
||||||
|
/** @var string the name of the cookie used for the 'remember me' feature */
|
||||||
|
private $rememberCookieName;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param PdoDatabase|PdoDsn|\PDO $databaseConnection the database connection to operate on
|
* @param PdoDatabase|PdoDsn|\PDO $databaseConnection the database connection to operate on
|
||||||
* @param bool $useHttps whether HTTPS (TLS/SSL) will be used (recommended)
|
|
||||||
* @param bool $allowCookiesScriptAccess whether cookies should be accessible via client-side scripts (*not* recommended)
|
|
||||||
* @param string $ipAddress the IP address that should be used instead of the default setting (if any), e.g. when behind a proxy
|
* @param string $ipAddress the IP address that should be used instead of the default setting (if any), e.g. when behind a proxy
|
||||||
* @param string|null $dbTablePrefix (optional) the prefix for the names of all database tables used by this component
|
* @param string|null $dbTablePrefix (optional) the prefix for the names of all database tables used by this component
|
||||||
*/
|
*/
|
||||||
public function __construct($databaseConnection, $useHttps = false, $allowCookiesScriptAccess = false, $ipAddress = null, $dbTablePrefix = null) {
|
public function __construct($databaseConnection, $ipAddress = null, $dbTablePrefix = null) {
|
||||||
parent::__construct($databaseConnection, $dbTablePrefix);
|
parent::__construct($databaseConnection, $dbTablePrefix);
|
||||||
|
|
||||||
$this->useHttps = $useHttps;
|
|
||||||
$this->allowCookiesScriptAccess = $allowCookiesScriptAccess;
|
|
||||||
$this->ipAddress = !empty($ipAddress) ? $ipAddress : (isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : null);
|
$this->ipAddress = !empty($ipAddress) ? $ipAddress : (isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : null);
|
||||||
|
$this->rememberCookieName = self::createRememberCookieName();
|
||||||
|
|
||||||
$this->initSession();
|
$this->initSession();
|
||||||
$this->enhanceHttpSecurity();
|
$this->enhanceHttpSecurity();
|
||||||
@@ -61,37 +56,32 @@ final class Auth extends UserManager {
|
|||||||
/** Initializes the session and sets the correct configuration */
|
/** Initializes the session and sets the correct configuration */
|
||||||
private function initSession() {
|
private function initSession() {
|
||||||
// use cookies to store session IDs
|
// use cookies to store session IDs
|
||||||
ini_set('session.use_cookies', 1);
|
\ini_set('session.use_cookies', 1);
|
||||||
// use cookies only (do not send session IDs in URLs)
|
// use cookies only (do not send session IDs in URLs)
|
||||||
ini_set('session.use_only_cookies', 1);
|
\ini_set('session.use_only_cookies', 1);
|
||||||
// do not send session IDs in URLs
|
// do not send session IDs in URLs
|
||||||
ini_set('session.use_trans_sid', 0);
|
\ini_set('session.use_trans_sid', 0);
|
||||||
|
|
||||||
// get our cookie settings
|
// start the session (requests a cookie to be written on the client)
|
||||||
$params = $this->createCookieSettings();
|
|
||||||
// define our new cookie settings
|
|
||||||
session_set_cookie_params($params['lifetime'], $params['path'], $params['domain'], $params['secure'], $params['httponly']);
|
|
||||||
|
|
||||||
// start the session
|
|
||||||
@Session::start();
|
@Session::start();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Improves the application's security over HTTP(S) by setting specific headers */
|
/** Improves the application's security over HTTP(S) by setting specific headers */
|
||||||
private function enhanceHttpSecurity() {
|
private function enhanceHttpSecurity() {
|
||||||
// remove exposure of PHP version (at least where possible)
|
// remove exposure of PHP version (at least where possible)
|
||||||
header_remove('X-Powered-By');
|
\header_remove('X-Powered-By');
|
||||||
|
|
||||||
// if the user is signed in
|
// if the user is signed in
|
||||||
if ($this->isLoggedIn()) {
|
if ($this->isLoggedIn()) {
|
||||||
// prevent clickjacking
|
// prevent clickjacking
|
||||||
header('X-Frame-Options: sameorigin');
|
\header('X-Frame-Options: sameorigin');
|
||||||
// prevent content sniffing (MIME sniffing)
|
// prevent content sniffing (MIME sniffing)
|
||||||
header('X-Content-Type-Options: nosniff');
|
\header('X-Content-Type-Options: nosniff');
|
||||||
|
|
||||||
// disable caching of potentially sensitive data
|
// disable caching of potentially sensitive data
|
||||||
header('Cache-Control: no-store, no-cache, must-revalidate', true);
|
\header('Cache-Control: no-store, no-cache, must-revalidate', true);
|
||||||
header('Expires: Thu, 19 Nov 1981 00:00:00 GMT', true);
|
\header('Expires: Thu, 19 Nov 1981 00:00:00 GMT', true);
|
||||||
header('Pragma: no-cache', true);
|
\header('Pragma: no-cache', true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -99,12 +89,25 @@ final class Auth extends UserManager {
|
|||||||
private function processRememberDirective() {
|
private function processRememberDirective() {
|
||||||
// if the user is not signed in yet
|
// if the user is not signed in yet
|
||||||
if (!$this->isLoggedIn()) {
|
if (!$this->isLoggedIn()) {
|
||||||
|
// if there is currently no cookie for the 'remember me' feature
|
||||||
|
if (!isset($_COOKIE[$this->rememberCookieName])) {
|
||||||
|
// if an old cookie for that feature from versions v1.x.x to v6.x.x has been found
|
||||||
|
if (isset($_COOKIE['auth_remember'])) {
|
||||||
|
// use the value from that old cookie instead
|
||||||
|
$_COOKIE[$this->rememberCookieName] = $_COOKIE['auth_remember'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// if a remember cookie is set
|
// if a remember cookie is set
|
||||||
if (isset($_COOKIE[self::COOKIE_NAME_REMEMBER])) {
|
if (isset($_COOKIE[$this->rememberCookieName])) {
|
||||||
|
// assume the cookie and its contents to be invalid until proven otherwise
|
||||||
|
$valid = false;
|
||||||
|
|
||||||
// split the cookie's content into selector and token
|
// split the cookie's content into selector and token
|
||||||
$parts = explode(self::COOKIE_CONTENT_SEPARATOR, $_COOKIE[self::COOKIE_NAME_REMEMBER], 2);
|
$parts = \explode(self::COOKIE_CONTENT_SEPARATOR, $_COOKIE[$this->rememberCookieName], 2);
|
||||||
|
|
||||||
// if both selector and token were found
|
// if both selector and token were found
|
||||||
if (isset($parts[0]) && isset($parts[1])) {
|
if (!empty($parts[0]) && !empty($parts[1])) {
|
||||||
try {
|
try {
|
||||||
$rememberData = $this->db->selectRow(
|
$rememberData = $this->db->selectRow(
|
||||||
'SELECT a.user, a.token, a.expires, b.email, b.username, b.status, b.roles_mask FROM ' . $this->dbTablePrefix . 'users_remembered AS a JOIN ' . $this->dbTablePrefix . 'users AS b ON a.user = b.id WHERE a.selector = ?',
|
'SELECT a.user, a.token, a.expires, b.email, b.username, b.status, b.roles_mask FROM ' . $this->dbTablePrefix . 'users_remembered AS a JOIN ' . $this->dbTablePrefix . 'users AS b ON a.user = b.id WHERE a.selector = ?',
|
||||||
@@ -116,13 +119,22 @@ final class Auth extends UserManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!empty($rememberData)) {
|
if (!empty($rememberData)) {
|
||||||
if ($rememberData['expires'] >= time()) {
|
if ($rememberData['expires'] >= \time()) {
|
||||||
if (password_verify($parts[1], $rememberData['token'])) {
|
if (\password_verify($parts[1], $rememberData['token'])) {
|
||||||
|
// the cookie and its contents have now been proven to be valid
|
||||||
|
$valid = true;
|
||||||
|
|
||||||
$this->onLoginSuccessful($rememberData['user'], $rememberData['email'], $rememberData['username'], $rememberData['status'], $rememberData['roles_mask'], true);
|
$this->onLoginSuccessful($rememberData['user'], $rememberData['email'], $rememberData['username'], $rememberData['status'], $rememberData['roles_mask'], true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// if the cookie or its contents have been invalid
|
||||||
|
if (!$valid) {
|
||||||
|
// mark the cookie as such to prevent any further futile attempts
|
||||||
|
$this->setRememberCookie('', '', \time() + 60 * 60 * 24 * 365.25);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -314,7 +326,7 @@ final class Auth extends UserManager {
|
|||||||
*
|
*
|
||||||
* @throws AuthError if an internal problem occurred (do *not* catch)
|
* @throws AuthError if an internal problem occurred (do *not* catch)
|
||||||
*/
|
*/
|
||||||
public function logOutButKeepSession() {
|
public function logOut() {
|
||||||
// if the user has been signed in
|
// if the user has been signed in
|
||||||
if ($this->isLoggedIn()) {
|
if ($this->isLoggedIn()) {
|
||||||
// get the user's ID
|
// get the user's ID
|
||||||
@@ -361,8 +373,8 @@ final class Auth extends UserManager {
|
|||||||
private function createRememberDirective($userId, $duration) {
|
private function createRememberDirective($userId, $duration) {
|
||||||
$selector = self::createRandomString(24);
|
$selector = self::createRandomString(24);
|
||||||
$token = self::createRandomString(32);
|
$token = self::createRandomString(32);
|
||||||
$tokenHashed = password_hash($token, PASSWORD_DEFAULT);
|
$tokenHashed = \password_hash($token, \PASSWORD_DEFAULT);
|
||||||
$expires = time() + ((int) $duration);
|
$expires = \time() + ((int) $duration);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$this->db->insert(
|
$this->db->insert(
|
||||||
@@ -399,20 +411,19 @@ final class Auth extends UserManager {
|
|||||||
throw new DatabaseError();
|
throw new DatabaseError();
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->setRememberCookie(null, null, time() - 3600);
|
$this->setRememberCookie(null, null, \time() - 3600);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets or updates the cookie that manages the "remember me" token
|
* Sets or updates the cookie that manages the "remember me" token
|
||||||
*
|
*
|
||||||
* @param string $selector the selector from the selector/token pair
|
* @param string|null $selector the selector from the selector/token pair
|
||||||
* @param string $token the token from the selector/token pair
|
* @param string|null $token the token from the selector/token pair
|
||||||
* @param int $expires the interval in seconds after which the token should expire
|
* @param int $expires the UNIX time in seconds which the token should expire at
|
||||||
* @throws AuthError if an internal problem occurred (do *not* catch)
|
* @throws AuthError if an internal problem occurred (do *not* catch)
|
||||||
*/
|
*/
|
||||||
private function setRememberCookie($selector, $token, $expires) {
|
private function setRememberCookie($selector, $token, $expires) {
|
||||||
// get our cookie settings
|
$params = \session_get_cookie_params();
|
||||||
$params = $this->createCookieSettings();
|
|
||||||
|
|
||||||
if (isset($selector) && isset($token)) {
|
if (isset($selector) && isset($token)) {
|
||||||
$content = $selector . self::COOKIE_CONTENT_SEPARATOR . $token;
|
$content = $selector . self::COOKIE_CONTENT_SEPARATOR . $token;
|
||||||
@@ -421,29 +432,30 @@ final class Auth extends UserManager {
|
|||||||
$content = '';
|
$content = '';
|
||||||
}
|
}
|
||||||
|
|
||||||
// set the cookie with the selector and token
|
// save the cookie with the selector and token (requests a cookie to be written on the client)
|
||||||
|
$cookie = new Cookie($this->rememberCookieName);
|
||||||
$cookie = new Cookie(self::COOKIE_NAME_REMEMBER);
|
|
||||||
|
|
||||||
$cookie->setValue($content);
|
$cookie->setValue($content);
|
||||||
$cookie->setExpiryTime($expires);
|
$cookie->setExpiryTime($expires);
|
||||||
|
|
||||||
if (!empty($params['path'])) {
|
|
||||||
$cookie->setPath($params['path']);
|
$cookie->setPath($params['path']);
|
||||||
}
|
|
||||||
|
|
||||||
if (!empty($params['domain'])) {
|
|
||||||
$cookie->setDomain($params['domain']);
|
$cookie->setDomain($params['domain']);
|
||||||
}
|
|
||||||
|
|
||||||
$cookie->setHttpOnly($params['httponly']);
|
$cookie->setHttpOnly($params['httponly']);
|
||||||
$cookie->setSecureOnly($params['secure']);
|
$cookie->setSecureOnly($params['secure']);
|
||||||
|
|
||||||
$result = $cookie->save();
|
$result = $cookie->save();
|
||||||
|
|
||||||
if ($result === false) {
|
if ($result === false) {
|
||||||
throw new HeadersAlreadySentError();
|
throw new HeadersAlreadySentError();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// if we've been deleting the cookie above
|
||||||
|
if (!isset($selector) || !isset($token)) {
|
||||||
|
// attempt to delete a potential old cookie from versions v1.x.x to v6.x.x as well (requests a cookie to be written on the client)
|
||||||
|
$cookie = new Cookie('auth_remember');
|
||||||
|
$cookie->setPath((!empty($params['path'])) ? $params['path'] : '/');
|
||||||
|
$cookie->setDomain($params['domain']);
|
||||||
|
$cookie->setHttpOnly($params['httponly']);
|
||||||
|
$cookie->setSecureOnly($params['secure']);
|
||||||
|
$cookie->delete();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -461,7 +473,7 @@ final class Auth extends UserManager {
|
|||||||
try {
|
try {
|
||||||
$this->db->update(
|
$this->db->update(
|
||||||
$this->dbTablePrefix . 'users',
|
$this->dbTablePrefix . 'users',
|
||||||
[ 'last_login' => time() ],
|
[ 'last_login' => \time() ],
|
||||||
[ 'id' => $userId ]
|
[ 'id' => $userId ]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -469,7 +481,7 @@ final class Auth extends UserManager {
|
|||||||
throw new DatabaseError();
|
throw new DatabaseError();
|
||||||
}
|
}
|
||||||
|
|
||||||
// re-generate the session ID to prevent session fixation attacks
|
// re-generate the session ID to prevent session fixation attacks (requests a cookie to be written on the client)
|
||||||
Session::regenerate(true);
|
Session::regenerate(true);
|
||||||
|
|
||||||
// save the user data in the session
|
// save the user data in the session
|
||||||
@@ -487,8 +499,8 @@ final class Auth extends UserManager {
|
|||||||
*
|
*
|
||||||
* @throws AuthError if an internal problem occurred (do *not* catch)
|
* @throws AuthError if an internal problem occurred (do *not* catch)
|
||||||
*/
|
*/
|
||||||
public function logout() {
|
public function logOutAndDestroySession() {
|
||||||
$this->logOutButKeepSession();
|
$this->logOut();
|
||||||
$this->destroySession();
|
$this->destroySession();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -498,17 +510,12 @@ final class Auth extends UserManager {
|
|||||||
* @throws AuthError if an internal problem occurred (do *not* catch)
|
* @throws AuthError if an internal problem occurred (do *not* catch)
|
||||||
*/
|
*/
|
||||||
private function deleteSessionCookie() {
|
private function deleteSessionCookie() {
|
||||||
// get our cookie settings
|
$params = \session_get_cookie_params();
|
||||||
$params = $this->createCookieSettings();
|
|
||||||
|
|
||||||
// cause the session cookie to be deleted
|
// ask for the session cookie to be deleted (requests a cookie to be written on the client)
|
||||||
$cookie = new Cookie(session_name());
|
$cookie = new Cookie(\session_name());
|
||||||
if (!empty($params['path'])) {
|
|
||||||
$cookie->setPath($params['path']);
|
$cookie->setPath($params['path']);
|
||||||
}
|
|
||||||
if (!empty($params['domain'])) {
|
|
||||||
$cookie->setDomain($params['domain']);
|
$cookie->setDomain($params['domain']);
|
||||||
}
|
|
||||||
$cookie->setHttpOnly($params['httponly']);
|
$cookie->setHttpOnly($params['httponly']);
|
||||||
$cookie->setSecureOnly($params['secure']);
|
$cookie->setSecureOnly($params['secure']);
|
||||||
$result = $cookie->delete();
|
$result = $cookie->delete();
|
||||||
@@ -548,8 +555,8 @@ final class Auth extends UserManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!empty($confirmationData)) {
|
if (!empty($confirmationData)) {
|
||||||
if (password_verify($token, $confirmationData['token'])) {
|
if (\password_verify($token, $confirmationData['token'])) {
|
||||||
if ($confirmationData['expires'] >= time()) {
|
if ($confirmationData['expires'] >= \time()) {
|
||||||
// invalidate any potential outstanding password reset requests
|
// invalidate any potential outstanding password reset requests
|
||||||
try {
|
try {
|
||||||
$this->db->delete(
|
$this->db->delete(
|
||||||
@@ -700,7 +707,7 @@ final class Auth extends UserManager {
|
|||||||
* @throws AuthError if an internal problem occurred (do *not* catch)
|
* @throws AuthError if an internal problem occurred (do *not* catch)
|
||||||
*/
|
*/
|
||||||
private function updatePassword($userId, $newPassword) {
|
private function updatePassword($userId, $newPassword) {
|
||||||
$newPassword = password_hash($newPassword, PASSWORD_DEFAULT);
|
$newPassword = \password_hash($newPassword, \PASSWORD_DEFAULT);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$this->db->update(
|
$this->db->update(
|
||||||
@@ -978,7 +985,7 @@ final class Auth extends UserManager {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
elseif ($username !== null) {
|
elseif ($username !== null) {
|
||||||
$username = trim($username);
|
$username = \trim($username);
|
||||||
|
|
||||||
// attempt to look up the account information using the specified username
|
// attempt to look up the account information using the specified username
|
||||||
$userData = $this->getUserDataByUsername(
|
$userData = $this->getUserDataByUsername(
|
||||||
@@ -994,9 +1001,9 @@ final class Auth extends UserManager {
|
|||||||
|
|
||||||
$password = self::validatePassword($password);
|
$password = self::validatePassword($password);
|
||||||
|
|
||||||
if (password_verify($password, $userData['password'])) {
|
if (\password_verify($password, $userData['password'])) {
|
||||||
// if the password needs to be re-hashed to keep up with improving password cracking techniques
|
// if the password needs to be re-hashed to keep up with improving password cracking techniques
|
||||||
if (password_needs_rehash($userData['password'], PASSWORD_DEFAULT)) {
|
if (\password_needs_rehash($userData['password'], \PASSWORD_DEFAULT)) {
|
||||||
// create a new hash from the password and update it in the database
|
// create a new hash from the password and update it in the database
|
||||||
$this->updatePassword($userData['id'], $password);
|
$this->updatePassword($userData['id'], $password);
|
||||||
}
|
}
|
||||||
@@ -1064,7 +1071,7 @@ final class Auth extends UserManager {
|
|||||||
*/
|
*/
|
||||||
private function getUserDataByEmailAddress($email, array $requestedColumns) {
|
private function getUserDataByEmailAddress($email, array $requestedColumns) {
|
||||||
try {
|
try {
|
||||||
$projection = implode(', ', $requestedColumns);
|
$projection = \implode(', ', $requestedColumns);
|
||||||
$userData = $this->db->selectRow(
|
$userData = $this->db->selectRow(
|
||||||
'SELECT ' . $projection . ' FROM ' . $this->dbTablePrefix . 'users WHERE email = ?',
|
'SELECT ' . $projection . ' FROM ' . $this->dbTablePrefix . 'users WHERE email = ?',
|
||||||
[ $email ]
|
[ $email ]
|
||||||
@@ -1095,7 +1102,7 @@ final class Auth extends UserManager {
|
|||||||
'SELECT COUNT(*) FROM ' . $this->dbTablePrefix . 'users_resets WHERE user = ? AND expires > ?',
|
'SELECT COUNT(*) FROM ' . $this->dbTablePrefix . 'users_resets WHERE user = ? AND expires > ?',
|
||||||
[
|
[
|
||||||
$userId,
|
$userId,
|
||||||
time()
|
\time()
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -1130,8 +1137,8 @@ final class Auth extends UserManager {
|
|||||||
private function createPasswordResetRequest($userId, $expiresAfter, callable $callback) {
|
private function createPasswordResetRequest($userId, $expiresAfter, callable $callback) {
|
||||||
$selector = self::createRandomString(20);
|
$selector = self::createRandomString(20);
|
||||||
$token = self::createRandomString(20);
|
$token = self::createRandomString(20);
|
||||||
$tokenHashed = password_hash($token, PASSWORD_DEFAULT);
|
$tokenHashed = \password_hash($token, \PASSWORD_DEFAULT);
|
||||||
$expiresAt = time() + $expiresAfter;
|
$expiresAt = \time() + $expiresAfter;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$this->db->insert(
|
$this->db->insert(
|
||||||
@@ -1148,7 +1155,7 @@ final class Auth extends UserManager {
|
|||||||
throw new DatabaseError();
|
throw new DatabaseError();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isset($callback) && is_callable($callback)) {
|
if (\is_callable($callback)) {
|
||||||
$callback($selector, $token);
|
$callback($selector, $token);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -1188,8 +1195,8 @@ final class Auth extends UserManager {
|
|||||||
|
|
||||||
if (!empty($resetData)) {
|
if (!empty($resetData)) {
|
||||||
if ((int) $resetData['resettable'] === 1) {
|
if ((int) $resetData['resettable'] === 1) {
|
||||||
if (password_verify($token, $resetData['token'])) {
|
if (\password_verify($token, $resetData['token'])) {
|
||||||
if ($resetData['expires'] >= time()) {
|
if ($resetData['expires'] >= \time()) {
|
||||||
$newPassword = self::validatePassword($newPassword);
|
$newPassword = self::validatePassword($newPassword);
|
||||||
|
|
||||||
// update the password in the database
|
// update the password in the database
|
||||||
@@ -1344,7 +1351,7 @@ final class Auth extends UserManager {
|
|||||||
* @param int $userId the user's ID
|
* @param int $userId the user's ID
|
||||||
*/
|
*/
|
||||||
private function setUserId($userId) {
|
private function setUserId($userId) {
|
||||||
$_SESSION[self::SESSION_FIELD_USER_ID] = intval($userId);
|
$_SESSION[self::SESSION_FIELD_USER_ID] = (int) $userId;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1729,24 +1736,6 @@ final class Auth extends UserManager {
|
|||||||
return new Administration($this->db, $this->dbTablePrefix);
|
return new Administration($this->db, $this->dbTablePrefix);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates the cookie settings that will be used to create and update cookies on the client
|
|
||||||
*
|
|
||||||
* @return array the cookie settings
|
|
||||||
*/
|
|
||||||
private function createCookieSettings() {
|
|
||||||
// get the default cookie settings
|
|
||||||
$params = session_get_cookie_params();
|
|
||||||
|
|
||||||
// check if we want to send cookies via SSL/TLS only
|
|
||||||
$params['secure'] = $params['secure'] || $this->useHttps;
|
|
||||||
// check if we want to send cookies via HTTP(S) only
|
|
||||||
$params['httponly'] = $params['httponly'] || !$this->allowCookiesScriptAccess;
|
|
||||||
|
|
||||||
// return the modified settings
|
|
||||||
return $params;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a UUID v4 as per RFC 4122
|
* Creates a UUID v4 as per RFC 4122
|
||||||
*
|
*
|
||||||
@@ -1756,14 +1745,57 @@ final class Auth extends UserManager {
|
|||||||
* @author Jack @ Stack Overflow
|
* @author Jack @ Stack Overflow
|
||||||
*/
|
*/
|
||||||
public static function createUuid() {
|
public static function createUuid() {
|
||||||
$data = openssl_random_pseudo_bytes(16);
|
$data = \openssl_random_pseudo_bytes(16);
|
||||||
|
|
||||||
// set the version to 0100
|
// set the version to 0100
|
||||||
$data[6] = chr(ord($data[6]) & 0x0f | 0x40);
|
$data[6] = \chr(\ord($data[6]) & 0x0f | 0x40);
|
||||||
// set bits 6-7 to 10
|
// set bits 6-7 to 10
|
||||||
$data[8] = chr(ord($data[8]) & 0x3f | 0x80);
|
$data[8] = \chr(\ord($data[8]) & 0x3f | 0x80);
|
||||||
|
|
||||||
return vsprintf('%s%s-%s-%s-%s-%s%s%s', str_split(bin2hex($data), 4));
|
return \vsprintf('%s%s-%s-%s-%s-%s%s%s', \str_split(\bin2hex($data), 4));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates a unique cookie name for the given descriptor based on the supplied seed
|
||||||
|
*
|
||||||
|
* @param string $descriptor a short label describing the purpose of the cookie, e.g. 'session'
|
||||||
|
* @param string|null $seed (optional) the data to deterministically generate the name from
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public static function createCookieName($descriptor, $seed = null) {
|
||||||
|
// use the supplied seed or the current UNIX time in seconds
|
||||||
|
$seed = ($seed !== null) ? $seed : \time();
|
||||||
|
|
||||||
|
foreach (self::COOKIE_PREFIXES as $cookiePrefix) {
|
||||||
|
// if the seed contains a certain cookie prefix
|
||||||
|
if (\strpos($seed, $cookiePrefix) === 0) {
|
||||||
|
// prepend the same prefix to the descriptor
|
||||||
|
$descriptor = $cookiePrefix . $descriptor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// generate a unique token based on the name(space) of this library and on the seed
|
||||||
|
$token = Base64::encodeUrlSafeWithoutPadding(
|
||||||
|
\md5(
|
||||||
|
__NAMESPACE__ . "\n" . $seed,
|
||||||
|
true
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
return $descriptor . '_' . $token;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates a unique cookie name for the 'remember me' feature
|
||||||
|
*
|
||||||
|
* @param string|null $sessionName (optional) the session name that the output should be based on
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public static function createRememberCookieName($sessionName = null) {
|
||||||
|
return self::createCookieName(
|
||||||
|
'remember',
|
||||||
|
($sessionName !== null) ? $sessionName : \session_name()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -40,10 +40,10 @@ abstract class UserManager {
|
|||||||
*/
|
*/
|
||||||
public static function createRandomString($maxLength = 24) {
|
public static function createRandomString($maxLength = 24) {
|
||||||
// calculate how many bytes of randomness we need for the specified string length
|
// calculate how many bytes of randomness we need for the specified string length
|
||||||
$bytes = floor(intval($maxLength) / 4) * 3;
|
$bytes = \floor((int) $maxLength / 4) * 3;
|
||||||
|
|
||||||
// get random data
|
// get random data
|
||||||
$data = openssl_random_pseudo_bytes($bytes);
|
$data = \openssl_random_pseudo_bytes($bytes);
|
||||||
|
|
||||||
// return the Base64-encoded result
|
// return the Base64-encoded result
|
||||||
return Base64::encodeUrlSafe($data);
|
return Base64::encodeUrlSafe($data);
|
||||||
@@ -103,12 +103,12 @@ abstract class UserManager {
|
|||||||
* @see confirmEmailAndSignIn
|
* @see confirmEmailAndSignIn
|
||||||
*/
|
*/
|
||||||
protected function createUserInternal($requireUniqueUsername, $email, $password, $username = null, callable $callback = null) {
|
protected function createUserInternal($requireUniqueUsername, $email, $password, $username = null, callable $callback = null) {
|
||||||
ignore_user_abort(true);
|
\ignore_user_abort(true);
|
||||||
|
|
||||||
$email = self::validateEmailAddress($email);
|
$email = self::validateEmailAddress($email);
|
||||||
$password = self::validatePassword($password);
|
$password = self::validatePassword($password);
|
||||||
|
|
||||||
$username = isset($username) ? trim($username) : null;
|
$username = isset($username) ? \trim($username) : null;
|
||||||
|
|
||||||
// if the supplied username is the empty string or has consisted of whitespace only
|
// if the supplied username is the empty string or has consisted of whitespace only
|
||||||
if ($username === '') {
|
if ($username === '') {
|
||||||
@@ -134,8 +134,8 @@ abstract class UserManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$password = password_hash($password, PASSWORD_DEFAULT);
|
$password = \password_hash($password, \PASSWORD_DEFAULT);
|
||||||
$verified = isset($callback) && is_callable($callback) ? 0 : 1;
|
$verified = \is_callable($callback) ? 0 : 1;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$this->db->insert(
|
$this->db->insert(
|
||||||
@@ -145,7 +145,7 @@ abstract class UserManager {
|
|||||||
'password' => $password,
|
'password' => $password,
|
||||||
'username' => $username,
|
'username' => $username,
|
||||||
'verified' => $verified,
|
'verified' => $verified,
|
||||||
'registered' => time()
|
'registered' => \time()
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -180,7 +180,7 @@ abstract class UserManager {
|
|||||||
*/
|
*/
|
||||||
protected function getUserDataByUsername($username, array $requestedColumns) {
|
protected function getUserDataByUsername($username, array $requestedColumns) {
|
||||||
try {
|
try {
|
||||||
$projection = implode(', ', $requestedColumns);
|
$projection = \implode(', ', $requestedColumns);
|
||||||
|
|
||||||
$users = $this->db->select(
|
$users = $this->db->select(
|
||||||
'SELECT ' . $projection . ' FROM ' . $this->dbTablePrefix . 'users WHERE username = ? LIMIT 2 OFFSET 0',
|
'SELECT ' . $projection . ' FROM ' . $this->dbTablePrefix . 'users WHERE username = ? LIMIT 2 OFFSET 0',
|
||||||
@@ -195,7 +195,7 @@ abstract class UserManager {
|
|||||||
throw new UnknownUsernameException();
|
throw new UnknownUsernameException();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (count($users) === 1) {
|
if (\count($users) === 1) {
|
||||||
return $users[0];
|
return $users[0];
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -216,9 +216,9 @@ abstract class UserManager {
|
|||||||
throw new InvalidEmailException();
|
throw new InvalidEmailException();
|
||||||
}
|
}
|
||||||
|
|
||||||
$email = trim($email);
|
$email = \trim($email);
|
||||||
|
|
||||||
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
|
if (!\filter_var($email, \FILTER_VALIDATE_EMAIL)) {
|
||||||
throw new InvalidEmailException();
|
throw new InvalidEmailException();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -237,9 +237,9 @@ abstract class UserManager {
|
|||||||
throw new InvalidPasswordException();
|
throw new InvalidPasswordException();
|
||||||
}
|
}
|
||||||
|
|
||||||
$password = trim($password);
|
$password = \trim($password);
|
||||||
|
|
||||||
if (strlen($password) < 1) {
|
if (\strlen($password) < 1) {
|
||||||
throw new InvalidPasswordException();
|
throw new InvalidPasswordException();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -265,10 +265,10 @@ abstract class UserManager {
|
|||||||
protected function createConfirmationRequest($userId, $email, callable $callback) {
|
protected function createConfirmationRequest($userId, $email, callable $callback) {
|
||||||
$selector = self::createRandomString(16);
|
$selector = self::createRandomString(16);
|
||||||
$token = self::createRandomString(16);
|
$token = self::createRandomString(16);
|
||||||
$tokenHashed = password_hash($token, PASSWORD_DEFAULT);
|
$tokenHashed = \password_hash($token, \PASSWORD_DEFAULT);
|
||||||
|
|
||||||
// the request shall be valid for one day
|
// the request shall be valid for one day
|
||||||
$expires = time() + self::CONFIRMATION_REQUESTS_TTL_IN_SECONDS;
|
$expires = \time() + self::CONFIRMATION_REQUESTS_TTL_IN_SECONDS;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$this->db->insert(
|
$this->db->insert(
|
||||||
@@ -286,7 +286,7 @@ abstract class UserManager {
|
|||||||
throw new DatabaseError();
|
throw new DatabaseError();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isset($callback) && is_callable($callback)) {
|
if (\is_callable($callback)) {
|
||||||
$callback($selector, $token);
|
$callback($selector, $token);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
125
tests/index.php
125
tests/index.php
@@ -15,33 +15,34 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
// enable error reporting
|
// enable error reporting
|
||||||
error_reporting(E_ALL);
|
\error_reporting(\E_ALL);
|
||||||
ini_set('display_errors', 'stdout');
|
\ini_set('display_errors', 'stdout');
|
||||||
|
|
||||||
// enable assertions
|
// enable assertions
|
||||||
ini_set('assert.active', 1);
|
\ini_set('assert.active', 1);
|
||||||
@ini_set('zend.assertions', 1);
|
@\ini_set('zend.assertions', 1);
|
||||||
ini_set('assert.exception', 1);
|
\ini_set('assert.exception', 1);
|
||||||
|
|
||||||
header('Content-type: text/html; charset=utf-8');
|
\header('Content-type: text/html; charset=utf-8');
|
||||||
|
|
||||||
require __DIR__.'/../vendor/autoload.php';
|
require __DIR__.'/../vendor/autoload.php';
|
||||||
|
|
||||||
$db = new PDO('mysql:dbname=php_auth;host=127.0.0.1;charset=utf8mb4', 'root', 'monkey');
|
$db = new \PDO('mysql:dbname=php_auth;host=127.0.0.1;charset=utf8mb4', 'root', 'monkey');
|
||||||
// or
|
// or
|
||||||
// $db = new PDO('sqlite:../Databases/php_auth.sqlite');
|
// $db = new \PDO('sqlite:../Databases/php_auth.sqlite');
|
||||||
|
|
||||||
$auth = new \Delight\Auth\Auth($db);
|
$auth = new \Delight\Auth\Auth($db);
|
||||||
|
|
||||||
$result = processRequestData($auth);
|
$result = \processRequestData($auth);
|
||||||
|
|
||||||
showDebugData($auth, $result);
|
\showGeneralForm();
|
||||||
|
\showDebugData($auth, $result);
|
||||||
|
|
||||||
if ($auth->check()) {
|
if ($auth->check()) {
|
||||||
showAuthenticatedUserForm($auth);
|
\showAuthenticatedUserForm($auth);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
showGuestUserForm();
|
\showGuestUserForm();
|
||||||
}
|
}
|
||||||
|
|
||||||
function processRequestData(\Delight\Auth\Auth $auth) {
|
function processRequestData(\Delight\Auth\Auth $auth) {
|
||||||
@@ -98,11 +99,11 @@ function processRequestData(\Delight\Auth\Auth $auth) {
|
|||||||
echo "\n";
|
echo "\n";
|
||||||
echo ' > Selector';
|
echo ' > Selector';
|
||||||
echo "\t\t\t\t";
|
echo "\t\t\t\t";
|
||||||
echo htmlspecialchars($selector);
|
echo \htmlspecialchars($selector);
|
||||||
echo "\n";
|
echo "\n";
|
||||||
echo ' > Token';
|
echo ' > Token';
|
||||||
echo "\t\t\t\t";
|
echo "\t\t\t\t";
|
||||||
echo htmlspecialchars($token);
|
echo \htmlspecialchars($token);
|
||||||
echo '</pre>';
|
echo '</pre>';
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -177,11 +178,11 @@ function processRequestData(\Delight\Auth\Auth $auth) {
|
|||||||
echo "\n";
|
echo "\n";
|
||||||
echo ' > Selector';
|
echo ' > Selector';
|
||||||
echo "\t\t\t\t";
|
echo "\t\t\t\t";
|
||||||
echo htmlspecialchars($selector);
|
echo \htmlspecialchars($selector);
|
||||||
echo "\n";
|
echo "\n";
|
||||||
echo ' > Token';
|
echo ' > Token';
|
||||||
echo "\t\t\t\t";
|
echo "\t\t\t\t";
|
||||||
echo htmlspecialchars($token);
|
echo \htmlspecialchars($token);
|
||||||
echo '</pre>';
|
echo '</pre>';
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -202,11 +203,11 @@ function processRequestData(\Delight\Auth\Auth $auth) {
|
|||||||
echo "\n";
|
echo "\n";
|
||||||
echo ' > Selector';
|
echo ' > Selector';
|
||||||
echo "\t\t\t\t";
|
echo "\t\t\t\t";
|
||||||
echo htmlspecialchars($selector);
|
echo \htmlspecialchars($selector);
|
||||||
echo "\n";
|
echo "\n";
|
||||||
echo ' > Token';
|
echo ' > Token';
|
||||||
echo "\t\t\t\t";
|
echo "\t\t\t\t";
|
||||||
echo htmlspecialchars($token);
|
echo \htmlspecialchars($token);
|
||||||
echo '</pre>';
|
echo '</pre>';
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -227,11 +228,11 @@ function processRequestData(\Delight\Auth\Auth $auth) {
|
|||||||
echo "\n";
|
echo "\n";
|
||||||
echo ' > Selector';
|
echo ' > Selector';
|
||||||
echo "\t\t\t\t";
|
echo "\t\t\t\t";
|
||||||
echo htmlspecialchars($selector);
|
echo \htmlspecialchars($selector);
|
||||||
echo "\n";
|
echo "\n";
|
||||||
echo ' > Token';
|
echo ' > Token';
|
||||||
echo "\t\t\t\t";
|
echo "\t\t\t\t";
|
||||||
echo htmlspecialchars($token);
|
echo \htmlspecialchars($token);
|
||||||
echo '</pre>';
|
echo '</pre>';
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -320,11 +321,11 @@ function processRequestData(\Delight\Auth\Auth $auth) {
|
|||||||
echo "\n";
|
echo "\n";
|
||||||
echo ' > Selector';
|
echo ' > Selector';
|
||||||
echo "\t\t\t\t";
|
echo "\t\t\t\t";
|
||||||
echo htmlspecialchars($selector);
|
echo \htmlspecialchars($selector);
|
||||||
echo "\n";
|
echo "\n";
|
||||||
echo ' > Token';
|
echo ' > Token';
|
||||||
echo "\t\t\t\t";
|
echo "\t\t\t\t";
|
||||||
echo htmlspecialchars($token);
|
echo \htmlspecialchars($token);
|
||||||
echo '</pre>';
|
echo '</pre>';
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -356,13 +357,13 @@ function processRequestData(\Delight\Auth\Auth $auth) {
|
|||||||
return 'not logged in';
|
return 'not logged in';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if ($_POST['action'] === 'logOutButKeepSession') {
|
else if ($_POST['action'] === 'logOut') {
|
||||||
$auth->logOutButKeepSession();
|
$auth->logOut();
|
||||||
|
|
||||||
return 'ok';
|
return 'ok';
|
||||||
}
|
}
|
||||||
else if ($_POST['action'] === 'logout') {
|
else if ($_POST['action'] === 'logOutAndDestroySession') {
|
||||||
$auth->logout();
|
$auth->logOutAndDestroySession();
|
||||||
|
|
||||||
return 'ok';
|
return 'ok';
|
||||||
}
|
}
|
||||||
@@ -535,56 +536,64 @@ function showDebugData(\Delight\Auth\Auth $auth, $result) {
|
|||||||
echo '<pre>';
|
echo '<pre>';
|
||||||
|
|
||||||
echo 'Last operation' . "\t\t\t\t";
|
echo 'Last operation' . "\t\t\t\t";
|
||||||
var_dump($result);
|
\var_dump($result);
|
||||||
echo 'Session ID' . "\t\t\t\t";
|
echo 'Session ID' . "\t\t\t\t";
|
||||||
var_dump(session_id());
|
\var_dump(\session_id());
|
||||||
echo "\n";
|
echo "\n";
|
||||||
|
|
||||||
echo '$auth->isLoggedIn()' . "\t\t\t";
|
echo '$auth->isLoggedIn()' . "\t\t\t";
|
||||||
var_dump($auth->isLoggedIn());
|
\var_dump($auth->isLoggedIn());
|
||||||
echo '$auth->check()' . "\t\t\t\t";
|
echo '$auth->check()' . "\t\t\t\t";
|
||||||
var_dump($auth->check());
|
\var_dump($auth->check());
|
||||||
echo "\n";
|
echo "\n";
|
||||||
|
|
||||||
echo '$auth->getUserId()' . "\t\t\t";
|
echo '$auth->getUserId()' . "\t\t\t";
|
||||||
var_dump($auth->getUserId());
|
\var_dump($auth->getUserId());
|
||||||
echo '$auth->id()' . "\t\t\t\t";
|
echo '$auth->id()' . "\t\t\t\t";
|
||||||
var_dump($auth->id());
|
\var_dump($auth->id());
|
||||||
echo "\n";
|
echo "\n";
|
||||||
|
|
||||||
echo '$auth->getEmail()' . "\t\t\t";
|
echo '$auth->getEmail()' . "\t\t\t";
|
||||||
var_dump($auth->getEmail());
|
\var_dump($auth->getEmail());
|
||||||
echo '$auth->getUsername()' . "\t\t\t";
|
echo '$auth->getUsername()' . "\t\t\t";
|
||||||
var_dump($auth->getUsername());
|
\var_dump($auth->getUsername());
|
||||||
|
|
||||||
echo '$auth->getStatus()' . "\t\t\t";
|
echo '$auth->getStatus()' . "\t\t\t";
|
||||||
echo convertStatusToText($auth);
|
echo \convertStatusToText($auth);
|
||||||
echo ' / ';
|
echo ' / ';
|
||||||
var_dump($auth->getStatus());
|
\var_dump($auth->getStatus());
|
||||||
|
|
||||||
echo "\n";
|
echo "\n";
|
||||||
|
|
||||||
echo 'Roles (super moderator)' . "\t\t\t";
|
echo 'Roles (super moderator)' . "\t\t\t";
|
||||||
var_dump($auth->hasRole(\Delight\Auth\Role::SUPER_MODERATOR));
|
\var_dump($auth->hasRole(\Delight\Auth\Role::SUPER_MODERATOR));
|
||||||
|
|
||||||
echo 'Roles (developer *or* manager)' . "\t\t";
|
echo 'Roles (developer *or* manager)' . "\t\t";
|
||||||
var_dump($auth->hasAnyRole(\Delight\Auth\Role::DEVELOPER, \Delight\Auth\Role::MANAGER));
|
\var_dump($auth->hasAnyRole(\Delight\Auth\Role::DEVELOPER, \Delight\Auth\Role::MANAGER));
|
||||||
|
|
||||||
echo 'Roles (developer *and* manager)' . "\t\t";
|
echo 'Roles (developer *and* manager)' . "\t\t";
|
||||||
var_dump($auth->hasAllRoles(\Delight\Auth\Role::DEVELOPER, \Delight\Auth\Role::MANAGER));
|
\var_dump($auth->hasAllRoles(\Delight\Auth\Role::DEVELOPER, \Delight\Auth\Role::MANAGER));
|
||||||
|
|
||||||
echo "\n";
|
echo "\n";
|
||||||
|
|
||||||
echo '$auth->isRemembered()' . "\t\t\t";
|
echo '$auth->isRemembered()' . "\t\t\t";
|
||||||
var_dump($auth->isRemembered());
|
\var_dump($auth->isRemembered());
|
||||||
echo '$auth->getIpAddress()' . "\t\t\t";
|
echo '$auth->getIpAddress()' . "\t\t\t";
|
||||||
var_dump($auth->getIpAddress());
|
\var_dump($auth->getIpAddress());
|
||||||
echo "\n";
|
echo "\n";
|
||||||
|
|
||||||
|
echo 'Session name' . "\t\t\t\t";
|
||||||
|
\var_dump(\session_name());
|
||||||
|
echo 'Auth::createRememberCookieName()' . "\t";
|
||||||
|
\var_dump(\Delight\Auth\Auth::createRememberCookieName());
|
||||||
|
echo "\n";
|
||||||
|
|
||||||
|
echo 'Auth::createCookieName(\'session\')' . "\t";
|
||||||
|
\var_dump(\Delight\Auth\Auth::createCookieName('session'));
|
||||||
echo 'Auth::createRandomString()' . "\t\t";
|
echo 'Auth::createRandomString()' . "\t\t";
|
||||||
var_dump(\Delight\Auth\Auth::createRandomString());
|
\var_dump(\Delight\Auth\Auth::createRandomString());
|
||||||
echo 'Auth::createUuid()' . "\t\t\t";
|
echo 'Auth::createUuid()' . "\t\t\t";
|
||||||
var_dump(\Delight\Auth\Auth::createUuid());
|
\var_dump(\Delight\Auth\Auth::createUuid());
|
||||||
|
|
||||||
echo '</pre>';
|
echo '</pre>';
|
||||||
}
|
}
|
||||||
@@ -626,8 +635,6 @@ function showGeneralForm() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function showAuthenticatedUserForm(\Delight\Auth\Auth $auth) {
|
function showAuthenticatedUserForm(\Delight\Auth\Auth $auth) {
|
||||||
showGeneralForm();
|
|
||||||
|
|
||||||
echo '<form action="" method="post" accept-charset="utf-8">';
|
echo '<form action="" method="post" accept-charset="utf-8">';
|
||||||
echo '<input type="hidden" name="action" value="reconfirmPassword" />';
|
echo '<input type="hidden" name="action" value="reconfirmPassword" />';
|
||||||
echo '<input type="text" name="password" placeholder="Password" /> ';
|
echo '<input type="text" name="password" placeholder="Password" /> ';
|
||||||
@@ -653,7 +660,7 @@ function showAuthenticatedUserForm(\Delight\Auth\Auth $auth) {
|
|||||||
echo '<button type="submit">Change email address</button>';
|
echo '<button type="submit">Change email address</button>';
|
||||||
echo '</form>';
|
echo '</form>';
|
||||||
|
|
||||||
showConfirmEmailForm();
|
\showConfirmEmailForm();
|
||||||
|
|
||||||
echo '<form action="" method="post" accept-charset="utf-8">';
|
echo '<form action="" method="post" accept-charset="utf-8">';
|
||||||
echo '<input type="hidden" name="action" value="setPasswordResetEnabled" />';
|
echo '<input type="hidden" name="action" value="setPasswordResetEnabled" />';
|
||||||
@@ -665,19 +672,17 @@ function showAuthenticatedUserForm(\Delight\Auth\Auth $auth) {
|
|||||||
echo '</form>';
|
echo '</form>';
|
||||||
|
|
||||||
echo '<form action="" method="post" accept-charset="utf-8">';
|
echo '<form action="" method="post" accept-charset="utf-8">';
|
||||||
echo '<input type="hidden" name="action" value="logOutButKeepSession" />';
|
echo '<input type="hidden" name="action" value="logOut" />';
|
||||||
echo '<button type="submit">Log out but keep session</button>';
|
echo '<button type="submit">Log out</button>';
|
||||||
echo '</form>';
|
echo '</form>';
|
||||||
|
|
||||||
echo '<form action="" method="post" accept-charset="utf-8">';
|
echo '<form action="" method="post" accept-charset="utf-8">';
|
||||||
echo '<input type="hidden" name="action" value="logout" />';
|
echo '<input type="hidden" name="action" value="logOutAndDestroySession" />';
|
||||||
echo '<button type="submit">Log out</button>';
|
echo '<button type="submit">Log out and destroy session</button>';
|
||||||
echo '</form>';
|
echo '</form>';
|
||||||
}
|
}
|
||||||
|
|
||||||
function showGuestUserForm() {
|
function showGuestUserForm() {
|
||||||
showGeneralForm();
|
|
||||||
|
|
||||||
echo '<h1>Public</h1>';
|
echo '<h1>Public</h1>';
|
||||||
|
|
||||||
echo '<form action="" method="post" accept-charset="utf-8">';
|
echo '<form action="" method="post" accept-charset="utf-8">';
|
||||||
@@ -718,7 +723,7 @@ function showGuestUserForm() {
|
|||||||
echo '<button type="submit">Register</button>';
|
echo '<button type="submit">Register</button>';
|
||||||
echo '</form>';
|
echo '</form>';
|
||||||
|
|
||||||
showConfirmEmailForm();
|
\showConfirmEmailForm();
|
||||||
|
|
||||||
echo '<form action="" method="post" accept-charset="utf-8">';
|
echo '<form action="" method="post" accept-charset="utf-8">';
|
||||||
echo '<input type="hidden" name="action" value="forgotPassword" />';
|
echo '<input type="hidden" name="action" value="forgotPassword" />';
|
||||||
@@ -769,49 +774,49 @@ function showGuestUserForm() {
|
|||||||
echo '<form action="" method="post" accept-charset="utf-8">';
|
echo '<form action="" method="post" accept-charset="utf-8">';
|
||||||
echo '<input type="hidden" name="action" value="admin.addRole" />';
|
echo '<input type="hidden" name="action" value="admin.addRole" />';
|
||||||
echo '<input type="text" name="id" placeholder="ID" /> ';
|
echo '<input type="text" name="id" placeholder="ID" /> ';
|
||||||
echo '<select name="role">' . createRolesOptions() . '</select>';
|
echo '<select name="role">' . \createRolesOptions() . '</select>';
|
||||||
echo '<button type="submit">Add role for user by ID</button>';
|
echo '<button type="submit">Add role for user by ID</button>';
|
||||||
echo '</form>';
|
echo '</form>';
|
||||||
|
|
||||||
echo '<form action="" method="post" accept-charset="utf-8">';
|
echo '<form action="" method="post" accept-charset="utf-8">';
|
||||||
echo '<input type="hidden" name="action" value="admin.addRole" />';
|
echo '<input type="hidden" name="action" value="admin.addRole" />';
|
||||||
echo '<input type="text" name="email" placeholder="Email" /> ';
|
echo '<input type="text" name="email" placeholder="Email" /> ';
|
||||||
echo '<select name="role">' . createRolesOptions() . '</select>';
|
echo '<select name="role">' . \createRolesOptions() . '</select>';
|
||||||
echo '<button type="submit">Add role for user by email</button>';
|
echo '<button type="submit">Add role for user by email</button>';
|
||||||
echo '</form>';
|
echo '</form>';
|
||||||
|
|
||||||
echo '<form action="" method="post" accept-charset="utf-8">';
|
echo '<form action="" method="post" accept-charset="utf-8">';
|
||||||
echo '<input type="hidden" name="action" value="admin.addRole" />';
|
echo '<input type="hidden" name="action" value="admin.addRole" />';
|
||||||
echo '<input type="text" name="username" placeholder="Username" /> ';
|
echo '<input type="text" name="username" placeholder="Username" /> ';
|
||||||
echo '<select name="role">' . createRolesOptions() . '</select>';
|
echo '<select name="role">' . \createRolesOptions() . '</select>';
|
||||||
echo '<button type="submit">Add role for user by username</button>';
|
echo '<button type="submit">Add role for user by username</button>';
|
||||||
echo '</form>';
|
echo '</form>';
|
||||||
|
|
||||||
echo '<form action="" method="post" accept-charset="utf-8">';
|
echo '<form action="" method="post" accept-charset="utf-8">';
|
||||||
echo '<input type="hidden" name="action" value="admin.removeRole" />';
|
echo '<input type="hidden" name="action" value="admin.removeRole" />';
|
||||||
echo '<input type="text" name="id" placeholder="ID" /> ';
|
echo '<input type="text" name="id" placeholder="ID" /> ';
|
||||||
echo '<select name="role">' . createRolesOptions() . '</select>';
|
echo '<select name="role">' . \createRolesOptions() . '</select>';
|
||||||
echo '<button type="submit">Remove role for user by ID</button>';
|
echo '<button type="submit">Remove role for user by ID</button>';
|
||||||
echo '</form>';
|
echo '</form>';
|
||||||
|
|
||||||
echo '<form action="" method="post" accept-charset="utf-8">';
|
echo '<form action="" method="post" accept-charset="utf-8">';
|
||||||
echo '<input type="hidden" name="action" value="admin.removeRole" />';
|
echo '<input type="hidden" name="action" value="admin.removeRole" />';
|
||||||
echo '<input type="text" name="email" placeholder="Email" /> ';
|
echo '<input type="text" name="email" placeholder="Email" /> ';
|
||||||
echo '<select name="role">' . createRolesOptions() . '</select>';
|
echo '<select name="role">' . \createRolesOptions() . '</select>';
|
||||||
echo '<button type="submit">Remove role for user by email</button>';
|
echo '<button type="submit">Remove role for user by email</button>';
|
||||||
echo '</form>';
|
echo '</form>';
|
||||||
|
|
||||||
echo '<form action="" method="post" accept-charset="utf-8">';
|
echo '<form action="" method="post" accept-charset="utf-8">';
|
||||||
echo '<input type="hidden" name="action" value="admin.removeRole" />';
|
echo '<input type="hidden" name="action" value="admin.removeRole" />';
|
||||||
echo '<input type="text" name="username" placeholder="Username" /> ';
|
echo '<input type="text" name="username" placeholder="Username" /> ';
|
||||||
echo '<select name="role">' . createRolesOptions() . '</select>';
|
echo '<select name="role">' . \createRolesOptions() . '</select>';
|
||||||
echo '<button type="submit">Remove role for user by username</button>';
|
echo '<button type="submit">Remove role for user by username</button>';
|
||||||
echo '</form>';
|
echo '</form>';
|
||||||
|
|
||||||
echo '<form action="" method="post" accept-charset="utf-8">';
|
echo '<form action="" method="post" accept-charset="utf-8">';
|
||||||
echo '<input type="hidden" name="action" value="admin.hasRole" />';
|
echo '<input type="hidden" name="action" value="admin.hasRole" />';
|
||||||
echo '<input type="text" name="id" placeholder="ID" /> ';
|
echo '<input type="text" name="id" placeholder="ID" /> ';
|
||||||
echo '<select name="role">' . createRolesOptions() . '</select>';
|
echo '<select name="role">' . \createRolesOptions() . '</select>';
|
||||||
echo '<button type="submit">Does user have role?</button>';
|
echo '<button type="submit">Does user have role?</button>';
|
||||||
echo '</form>';
|
echo '</form>';
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user