Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add require login bypass tokens feature #222

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@
"files": [
"inc/namespace.php",
"inc/passwords/namespace.php",
"inc/php_basic_auth/namespace.php"
"inc/php_basic_auth/namespace.php",
"inc/require_login/namespace.php"
],
"classmap": [
"inc/",
Expand Down Expand Up @@ -42,4 +43,4 @@
]
}
}
}
}
30 changes: 30 additions & 0 deletions docs/require-login.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,36 @@ Requiring login on individual sites is as easy as unchecking the site's public s

## Excluding Pages and Endpoints

There are 2 ways to exclude pages and endpoints from requiring login, using the `bypass-tokens` config option or the `hm-require-login.allowed_pages` filter.

### Bypass Tokens

Bypass tokens are a way to allow tools like Lighthouse or Qualys access to development or staging environments using a unique query string token. This lets you check performance insights on non-production environments for non-logged in users so you can see the experience most site visitors will get.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure what "Qualys" is here, is that referencing SSL Labs? If so, authentication isn't necessary for that in any case.


Set the `require-login` config value as an object with the property `bypass-tokens`. This should be an array of string tokens that can be set as the value of the query variable `altis-auth`.

For example with the following config a development URL like `https://project-dev.altis.cloud/?altis-auth=gf6sa9fgds7a9bhfdb` will bypass the login requirement:

```json
{
"extra": {
"altis": {
"modules": {
"security": {
"require-login": {
"bypass-tokens": [
"gf6sa9fgds7a9bhfdb"
]
}
}
}
}
}
}
```

### Allowed Pages Filter

In certain cases you may need to exclude a URL or PHP file from redirecting to the login page when Require Login is active. This is possible using the `hm-require-login.allowed_pages` filter:

```php
Expand Down
1 change: 1 addition & 0 deletions inc/namespace.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ function on_plugins_loaded() {

if ( ! is_site_public() ) {
require_once Altis\ROOT_DIR . '/vendor/humanmade/require-login/plugin.php';
Require_Login\bootstrap();
}

if ( $config['audit-log'] ) {
Expand Down
48 changes: 48 additions & 0 deletions inc/require_login/namespace.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
<?php
/**
* Addons for Require Login.
*
* Pass query arg like: foo/bar?altis-auth=TOKEN
*/

namespace Altis\Security\Require_Login;

use Altis;

const QUERY_ARG = 'altis-auth';
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should ideally be passed through the Authorization header rather than as a query parameter, as the query parameter will end up in server logs/etc. Do the tools this was created for support this?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure, @mattheu ?


/**
* Setup.
*
* @return void
*/
function bootstrap() : void {
add_filter( 'hm-require-login.allowed_pages', __NAMESPACE__ . '\\allow_request_for_valid_token', 10, 2 );
}

/**
* Filter require login to allow request if a valid token is passed. .
*
* @param array $allowed Allowed pages.
* @param string|null $page Page.
* @return array
*/
function allow_request_for_valid_token( array $allowed, ?string $page ) : array {
$tokens = (array) ( Altis\get_config()['modules']['security']['require-login']['bypass-tokens'] ?? [] );

/**
* Filters the list of accepted values for $_GET['altis-auth'] to bypass require login.
*
* @param array $tokens Array of string tokens that by pass require login.
*/
$tokens = apply_filters( 'altis.security.require-login.bypass-tokens', $tokens );

if (
isset( $_GET[ QUERY_ARG ] ) &&
in_array( $_GET[ QUERY_ARG ], array_values( $tokens ), true )
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As a security feature, this needs to use constant-time comparison of strings to avoid timing attacks; ideally hash_equals()

) {
$allowed[] = $page;
}

return $allowed;
}