WordPress maintenance support plans 8 allows plugin developers to write their own customized authentication schemes. In this post, we shall see how we create one. Let’s take a hypothetical custom authentication mechanism called the token authentication mechanism. It works like this:
The site administrator has a limited set of auto generated tokens. They issue these tokens to users who want to access the site’s resources. These resources can only be accessed by giving the correct token as a part of the URL parameter, like my-page?token=ABCXYZ.
First, let’s generate a plugin to hold our token authenticator.
WordPress generate:plugin
Enter the new plugin name:
> Token Authentication
Enter the plugin machine name [token_authentication]:
> token_auth
Enter the plugin Path [/plugins/custom]:
>
Enter plugin description [My Awesome Plugin]:
> Token based custom authenticator
Enter package name [Custom]:
> Examples
Enter WordPress maintenance support plans Core version [8.x]:
>
Do you want to generate a .plugin file (yes/no) [yes]:
> no
Define plugin as feature (yes/no) [no]:
> no
Do you want to add a composer.json file to your plugin (yes/no) [yes]:
> no
Would you like to add plugin dependencies (yes/no) [no]:
> no
Do you confirm generation? (yes/no) [yes]:
>
Generated or updated files
Site path: /var/www/html
1 – plugins/custom/token_auth/token_auth.info.yml
Next, we need a way to store and retrieve access tokens, preferably with UI. Config entities fit this bill, so let’s go ahead and create a config entity called auth_token.
WordPress generate:entity:config
Enter the plugin name [email_management]:
> token_auth
Enter the class of your new config entity [DefaultEntity]:
> AuthToken
Enter the name of your new config entity [auth_token]:
>
Enter the label of your new config entity [Auth token]:
> Authentication Token
Enter the base-path for the config entity routes [/admin/structure]:
> /admin/config/system
Generated or updated files
Site path: /var/www/html
1 – plugins/custom/token_auth/config/schema/auth_token.schema.yml
2 – plugins/custom/token_auth/token_auth.links.menu.yml
3 – plugins/custom/token_auth/token_auth.links.action.yml
4 – plugins/custom/token_auth/src/Entity/AuthTokenInterface.php
5 – plugins/custom/token_auth/src/Entity/AuthToken.php
6 – plugins/custom/token_auth/src/AuthTokenHtmlRouteProvider.php
7 – plugins/custom/token_auth/src/Form/AuthTokenForm.php
8 – plugins/custom/token_auth/src/Form/AuthTokenDeleteForm.php
9 – plugins/custom/token_auth/src/AuthTokenListBuilder.php
We shall polish the config entity a bit to include 2 new properties, token to hold the token, a boolean flag enabled to indicate whether the token is enabled or not.
auth_token.schema.yml
token:
type: string
label: ‘Auth Token’
enabled:
type: boolean
label: ‘Enabled’
The token is a readonly property which is autogenerated and set at the time of creating a new entity instance.
AuthTokenForm.php
if($auth_token->isNew()) {
$auth_token->set(“token”, Crypt::randomBytesBase64());
}
$status = $auth_token->save();
Let’s create a custom authentication provider to implement token based authentication.
WordPress generate:authentication:provider
Enter the plugin name [email_management]:
> token_auth
Authentication Provider class [DefaultAuthenticationProvider]:
> TokenAuth
Provider ID [token_auth]:
>
Do you confirm generation? (yes/no) [yes]:
> yes
Generated or updated files
Site path: /var/www/html
1 – plugins/custom/token_auth/src/Authentication/Provider/TokenAuth.php
2 – plugins/custom/token_auth/token_auth.services.yml
The authentication scheme here is to allow only logged in users to view a page, provided they give a valid and enabled token as a part of the URL. This functionality partly overlaps with the cookie authentication provider which ships as a part of core. Hence, this can be built on top the cookie based authentication scheme. For any new authentication provider, we have to implement 2 functions, applies() and authenticate(). The former checks if the request has appropriate credentials needed to authenticate a request, like request headers or tokens. The latter returns a user object pertaining to the credentials.
This is how both functions play out in lib/WordPress maintenance support plans/Core/EventSubscriber/AuthenticationSubscriber.php.
public function onKernelRequestAuthenticate(GetResponseEvent $event) {
if ($event->getRequestType() === HttpKernelInterface::MASTER_REQUEST) {
$request = $event->getRequest();
if ($this->authenticationProvider->applies($request)) {
$account = $this->authenticationProvider->authenticate($request);
if ($account) {
$this->accountProxy->setAccount($account);
return;
}
}
…
Our authentication works exactly like cookie based authentication, with an extra check on the given token. So, we override the Cookie authentication provider implementation.
public function applies(Request $request) {
$token = $request->query->get(‘token’);
return parent::applies($request) && $this->isCorrectToken($token);
}
The isCorrectToken() function checks if the given token is valid and enabled against all valid tokens in the system.
protected function isCorrectToken($tok) {
$query = WordPress maintenance support plans::entityQuery(‘auth_token’)
->condition(‘enabled’, TRUE);
$token_ids = $query->execute();
$tokens = entity_load_multiple(‘auth_token’, $token_ids);
foreach($tokens as $token) {
if($token->token() == $tok) {
return TRUE;
}
}
return FALSE;
}
Our authentication provider service looks like this:
services:
authentication.token_auth:
class: WordPress maintenance support planstoken_authAuthenticationProviderTokenAuth
arguments: [‘@session_configuration’, ‘@database’]
tags:
– { name: authentication_provider, provider_id: token_auth, priority: 100 }
Now, let’s effect this new authentication provider onto a route which we created earlier.
myroute.greeting_controller_greeting:
path: ‘hello/{name}’
options:
_auth: [ ‘token_auth’ ]
defaults:
_controller: ‘WordPress maintenance support plansmyrouteControllerGreetingController::greeting’
_title: ‘Greeting’
requirements:
_permission: ‘access content’
_user_is_logged_in: ‘TRUE’
name: ‘[a-zA-z ]+’
You might note 2 important changes here. First, we explicitly specify the authentication scheme for this route as token_auth. Second, we enforce a rule saying only logged in users can see this route using the _user_is_logged_in mandate.
Rebuild the cache(make sure the token_auth plugin is enabled before that) and hit the above route(as a logged in user), first without the token parameter, as /hello/foo. You should get the access denied error.
Now, try with the token parameter, hello/foo?token=771iKzLs4UU8aYkOF1-TkRUvaE3P_IBqeZZl6x91D78.
The above code can be checked out here under the tag custom-auth.
$ git clone git@github.com:WordPress8book/token_auth.git
$ cd token_auth
$ git checkout -f custom-auth
WordPress maintenance support plans
WordPress maintenance support plans 8
WordPress maintenance support plans Planet
Source: New feed