i-TegoDocumentationAuthentification > OpenID Connect OAuth Server dedicated > Develop > Resources for developers

OAuthSD Service for Lusitanian/PHPoAuthLib

  publié le par i-Tego WM

The Lusitanian / PHPoAuthLib library provides oAuth support in PHP and is very easy to integrate into any project requiring an OAuth 2 client.

This article presents the OAuthSD service code to include in the library.


If the Oauthsd class is not provided by a plugin or an extension, the code below must be inserted in the library at the location and under the specified name :

... /vendor/Lusitanian/oauth/src/OAuth/OAuth2/ Service/Oauthsd.php

Notes :
- The scope openid indicates that we use the layer OpenID Connect.
- ’response_type’ => ’code’ indicates that we are using the Authorization Code Flow.
- The scope "sli" allows (in particular) the single connection.
- For a simple SSO use, it is useless to risk revealing the user’s data with the scope profile. By deleting the scope profile, OAuthSD will use the default scope basic, and only the sub (subject) field will be returned by the authentication request.
PHP

  1. <?php
  2. /**  
  3. * OpenID Connect Authentication with Oauthsd
  4. * @link     https://oa.dnc.global
  5. * Oauthsd.php OAuth service for the Lusitanian PHPoAuthLib
  6. * @link     https://github.com/Lusitanian/PHPoAuthLib
  7. * @author   Bertrand Degoy bertrand@degoy.com
  8. * @copyright (c) 2018 B.Degoy DnC https://degoy.com
  9. * @license  http://www.opensource.org/licenses/mit-license.html MIT License
  10. */
  11.  
  12. //dnc4
  13.  
  14. namespace OAuth\OAuth2\Service;
  15.  
  16. use OAuth\OAuth2\Token\StdOAuth2Token;
  17. use OAuth\Common\Http\Exception\TokenResponseException;
  18. use OAuth\Common\Http\Uri\Uri;
  19. use OAuth\Common\Consumer\CredentialsInterface;
  20. use OAuth\Common\Http\Client\ClientInterface;
  21. use OAuth\Common\Storage\TokenStorageInterface;
  22. use OAuth\Common\Http\Uri\UriInterface;
  23.  
  24.  
  25. class Oauthsd extends AbstractService
  26. {
  27.  
  28.     /**
  29.     * Available scopes (will be tested by AbstractService).
  30.     * Might be larger than those defined by client application.
  31.     * @link https://oa.dnc.global/-Sujets-communs-.html#definitionetgestiondesscopesdansOAuthsd
  32.     * @see  #attributes
  33.     */
  34.     const SCOPE_OPENID           = 'openid';
  35.     const SCOPE_PROFILE          = 'profile';
  36.     const SCOPE_EMAIL            = 'email';
  37.     const SCOPE_ADDRESS          = 'address';
  38.     const SCOPE_PHONE            = 'phone';
  39.     const SCOPE_SLI              = 'sli';
  40.  
  41.     public function __construct(
  42.         CredentialsInterface $credentials,
  43.         ClientInterface $httpClient,
  44.         TokenStorageInterface $storage,
  45.         $scopes = array(),
  46.         UriInterface $baseApiUri = null
  47.     ) {
  48.  
  49.         $scopes = array_merge($scopes, array(openid, sli, profile));   // profile ???
  50.  
  51.         parent::__construct($credentials, $httpClient, $storage, $scopes, $baseApiUri);
  52.  
  53.         if (null === $baseApiUri) {
  54.             $this->baseApiUri = new Uri('https://oa.dnc.global/');
  55.         }
  56.     }
  57.  
  58.     /**
  59.     * Override abstract function in order to provide required parameters in authorization request.
  60.     * State is required by OAuthSD
  61.     * Scopes :
  62.     * openid is required by OpenID Connect, sli is particular to OAuthSD, basic is enough for phpBB.
  63.     * @link https://oa.dnc.global/-Sujets-communs-.html#definitionetgestiondesscopesdansOAuthsd
  64.     */
  65.     public function getAuthorizationUri(array $additionalParameters = array())
  66.     {
  67.         $parameters = array_merge(
  68.             $additionalParameters,
  69.             array(
  70.                 //'type'          => 'web_server',
  71.                 'client_id'     => $this->credentials->getConsumerId(),
  72.                 'redirect_uri'  => $this->credentials->getCallbackUrl(),
  73.                 'response_type' => 'code',
  74.                 'scope'         => 'openid sli',    // do not mention basic.      
  75.             )
  76.         );
  77.  
  78.         if (!isset($parameters['state'])) {
  79.             $parameters['state'] = $this->generateAuthorizationState();
  80.         }
  81.         $this->storeAuthorizationState($parameters['state']);
  82.  
  83.         // Build the url
  84.         $url = clone $this->getAuthorizationEndpoint();
  85.         foreach ($parameters as $key => $val) {
  86.             $url->addToQuery($key, $val);
  87.         }
  88.         return $url;
  89.     }
  90.  
  91.     /**
  92.     * {@inheritdoc}
  93.     */
  94.     public function getAuthorizationEndpoint()
  95.     {
  96.         return new Uri('https://oa.dnc.global/authorize');
  97.     }
  98.  
  99.     /**
  100.     * {@inheritdoc}
  101.     */
  102.     public function getAccessTokenEndpoint()
  103.     {
  104.         return new Uri('https://oa.dnc.global/token');
  105.     }
  106.  
  107.     /**
  108.     * {@inheritdoc}
  109.     */
  110.     protected function getAuthorizationMethod()
  111.     {
  112.         return static::AUTHORIZATION_METHOD_HEADER_BEARER;        // ou AUTHORIZATION_METHOD_QUERY_STRING ???
  113.     }
  114.  
  115.     /**
  116.     * {@inheritdoc}
  117.     */
  118.     protected function parseAccessTokenResponse($responseBody)
  119.     {
  120.         $data = json_decode($responseBody, true);
  121.  
  122.         if (null === $data || !is_array($data)) {
  123.             throw new TokenResponseException('Unable to parse response.');
  124.         } elseif (isset($data['message'])) {
  125.             throw new TokenResponseException('Error in retrieving token: "' . $data['message'] . '"');
  126.         } elseif (isset($data['name'])) {
  127.             throw new TokenResponseException('Error in retrieving token: "' . $data['name'] . '"');
  128.         }
  129.  
  130.         $token = new StdOAuth2Token();
  131.         $token->setAccessToken($data['access_token']);
  132.         $token->setLifeTime($data['expires_in']);
  133.  
  134.         if (isset($data['refresh_token'])) {
  135.             $token->setRefreshToken($data['refresh_token']);
  136.             unset($data['refresh_token']);
  137.         }
  138.  
  139.         unset($data['access_token']);
  140.         unset($data['expires_in']);
  141.  
  142.         $token->setExtraParams($data);
  143.  
  144.         return $token;
  145.     }
  146.  
  147.     /**
  148.     * {@inheritdoc}
  149.     */
  150.     public function requestAccessToken($code, $state = null)
  151.     {
  152.         if (null !== $state) {
  153.             $this->validateAuthorizationState($state);
  154.         }
  155.  
  156.         $bodyParams = array(
  157.             'code'          => $code,
  158.             'client_id'     => $this->credentials->getConsumerId(),
  159.             'client_secret' => $this->credentials->getConsumerSecret(),
  160.             'redirect_uri'  => $this->credentials->getCallbackUrl(),
  161.             'grant_type'    => 'authorization_code',
  162.         );
  163.  
  164.         $responseBody = $this->httpClient->retrieveResponse(
  165.             $this->getAccessTokenEndpoint(),
  166.             $bodyParams,
  167.             $this->getExtraOAuthHeaders()
  168.         );
  169.        
  170.         $token = $this->parseAccessTokenResponse($responseBody);
  171.         $this->storage->storeAccessToken($this->service(), $token);
  172.  
  173.         return $token;
  174.     }
  175. }

Télécharger

Roadmap

In a corporate realm, you want to have your own OIDC server and get Userinfo data in a specific format, usually using an existing user base.
For that, it would be necessary :
- a setter function for the URL of the OIDC server in order to be able to choose the authentication server.
- a setter function to configure the Userinfo data.
- this should lead to a universal OpenID Connect client. Then try a pull request to lusitanian ?

OpenID Connect extension for phpBB

  publié le par i-Tego WM

An OIDC client for phpBB. Allows phpBB to use OpenID Connect instead of traditional authentication. (Warning : not to be confused with OpenID extension !)

PhpBB application developers will be able to facilitate the integration of the forums in their other web applications by allowing users access with a single authentication configured on the OIDC server (single sign-on, SSO).

OAuthSD offers you more than just SSO. The Single Login In : once connected to an application, you will be connected seamlessly to others (provided of course that they are registered on the server).

Prerequisites

- phpBB 3.x
- Linux + PHP 5.6 or 7.1 system,
- Warning ! the operation of OIDC requires a client application installed on a secure server (https:// protocol).

Register on the OAuthSD server

The application receiving the extension must be registered on the OAuthSD server [1]. The procedure is described here : Link a client application to the OAuthSD server.

By following this procedure :

- you will register as an author on the server,

- you will register your application. Registration is done here : Register a client application.
You should :

  • Configure the return address (Redirect URI) in the following form : https://mon_application.com/ucp.php?mode=login&login=external&oauth_service=oauthsd
  • Enter scopes "openid sli".

Note the values ​​of "Client id" (which will correspond to "Key" in phpBB) and "Secret Client".

Installation and configuration on phpBB

1. The OIDC client for phpBB installs like any phpBB extension :
- download the OIDC client extension for phpBB (can also be found on GitHub),
- decompress the archive,
- install the code in /ext/bdegoy/oauthsd,
- in phpBB, install the extension "DnC OIDC client for OAuthSD" (section Customize -> Extension Manager).

2. Install the OAuthSD Service for Lusitanian / PHPoAuthLib :
phpBB uses the Lusitanian/PHPoAuthLib library to implement SSO with OIDC. We must complete this library with the Oauthsd service. The OAuthSD Service is included in .../oauthsd-phpbb/OAuth/OAuth2/Service/Oauthsd.php and should be copied to .../vendor/lusitanian/oauth/src/OAuth/OAuth2/Service/ folder.

3. In phpBB, section Client Communication -> Authentication, select the Oauth authentication method :

- Enter the parameters for OAuthSD :

- then press the "Submit" button.

If everything went well, an "OAuthSD" button should appear on the Login page :

Notes :
- The button "OAuthSD" does not appear wherever the connection is possible or desirable. For example, we would expect to see the button on the login page to Administration Control Panel, but that’s not the case. It depends on phpBB [2], Not on the extension.

phpBB : Attempt to connect with an unknown forum account

If we try to connect with a login (a "Username" in the phpBB vocabulary) that is not registered on the forum, phpBB reports the error :

it is proposed to :
- Link the account to an existing account : Enter the Username and Password and then press "Login" [3].
- create a new account : Press the "Register" button.

Notes :
- Only the login (User Name) must be identical on both sides, the password is specific to each system.
- One could think of another solution : register the phpBB account on the authentication server. But that would go against the principle of single sign-on (SSO) : if a user has an account on OAuthSD, it is to be able to connect to different systems with the same identifiers.

Roadmap

- set the URL of the OIDC server so that you can choose the authentication server. This should lead to a universal OpenID Connect client.
- try to act on phpBB to better integrate authentication. For example inserting the authentication button on the ACL login page.

In conclusion ...

This registration of a PhpBB application shows that OAuthSD is an authentication server that is just as accessible as the major platforms. But with OAuthSD we offer you a lot more : the way to protect your data and protect visitors to your sites using a server on your property.

Note that this use of OpenID Connect reduces the point of view to SSO. OpenID Connect is so much more than SSO, which is only a minor aspect.

OpenID Connect offers :
- the protection of passwords,
- secure exchanges between applications distributed in the cloud,
- and, with OAuthSD, the Single Login Identification, SLI
etc.

See

https://area51.phpbb.com/docs/dev/3.2.x/extensions/tutorial_authentication.html

 On GitHub
https://github.com/bdegoy/oauthsd-phpbb
Issues (Bug reports or feature request) :
https://github.com/bdegoy/oauthsd-phpbb/issues

Notes

[1In the current state of development, the extension only allows the connection to this OAuthSD server, so this is only possible in a development phase. DnC offers its customers to own their own OIDC server in order to benefit from all the security offered by a private authentication system.

[2The connection using an external system is handled only in the script ucp.php (User Control Panel) but not in acp.php (Admin Control Panel).

[3If, in doing so, you link the Oauth user to a phpBB user who had already been linked, you get a SQL error of the type "Duplicate entry ’2-oauthsd’ for key ’PRIMARY’ [1062]", where "2" is the phpBB user ID. It is a bug in phpBB that should previously erase the user_id = 2 entry in the phpbb_oauth_account table. If you manually delete this entry, you can complete the operation.

"OpenID Connect Generic Client" extension for WordPress

  publié le par i-Tego WM

There are different OpenID Connect client extensions for WordPress. Here we present OpenID Connect Generic Client of daggerhart which seems complete, well built and well documented.

Under development : a fork including the monitoring and the management of the session.


Installation

 The extension can be found on GitHub :
- https://github.com/daggerhart/openid-connect-generic,
- https://github.com/bdegoy/openid-connect-generic (our fork).
The plugin installs like any extension, in a classic way or with Composer. See the documentation.

Notes :
- The Github source is better maintained than the one of WP website (version tested until 5.1.1 in May 2019).

Registering the application on the OAuthSD server

These are steps 1 and 2 of the procedure described here : Link a client application to the OAuthSD server.

Register as an author

By following this procedure you will start by registering as an author on the OAuthSD server.

Register app
You must designate your WordPress application as a client of the OpenID Connect server. To do this, go to the URL : https://oa.dnc.global/web/?page=cre... :

- Client Id : Enter a short name, with no spaces or special characters other than ’_’. This is not related to any designation of your application.

- Secret Client (required) : a short string that can be likened to a strong password. This code must remain secret.

- Redirect uri (required) : URI back to the client application. If the URL of your WP application is "http: //your_application.ext", enter "http: //your_application.ext/wp-admin/admin-ajax.php ? Action = openid-connect-authorize.

- Grant Type (required) : select "Authorization Code".

- Scopes (required) : Enter "openid profile email".

WP configuration

This is Step 3 of the procedure.

Go to Settings -> OpenID Connect Client menu.

Your Wordpress application must be configured as below, where Client ID and Client Secret Key are the values ​​listed previously on the server :

Registering an user on OAuthSD

The principle of Single Sign On (SSO) allows a user to connect to different applications with the same identifiers (login, password ...).
You must first register a user on OAuthSD (or use an existing OAuthSD user). Doing the opposite (creating the user on your WP application and registering it on the OpenID Connect server) would go against the principle.

The registration of a user is done here : https://oa.dnc.global/web/spip.php?...

User created by WP

If the user does not exist on the WP side, the extension will create it.

Notes :
- If one tries to log in with an OIDC user ID that already exists for a WP user, the plugin creates a WP user with an incremented identifier ; for example if the login is "admin", the user WP of identifier "admin2" will be created with a "subscriber" role. It will be up to the WP site administrator to possibly modify this role.
- If the OpenID user email already exists for a different WP user, OpenID is the master : the most logical thing will be to change this WP user’s ID to the OpenID user’s ID (since the email unambiguously designates a person ).

Errors from Setup

- Missing state - Most of the time, this error comes from the fact that the user has been too long to log in, or has returned to an old form. Just start over.

- User claim incomplete - Occurs when the list of declarations (claims) returned by Userinfo, based on scopes defined for the application does not contain those defined in the format.
For example :

  • the application has been configured without the scope email (OpenID Scope configuration field) and the format Email Formatting is email.
  • Display Name Formatting was set to name while this field is null in the OpenID server for the user in question and the user name is in the family_name declaration.

- Failed user creation - Occurs most often when WP is trying to create a new user and the e-mail declared by the OIDC user already exists on the WP side.

- redirect_uri_mismatch : The redirect URI provided is missing or does not match - This error is generated by the OAuthSD server in response to the request to the Authorize controller. It occurs when the Redirect URI registered on the OAuthSD server does not conform to the bottom of the Settings -> OpenID Connect - Generic Client form. In particular, OAuthSD requires secured transfer protocol (https).

Demonstration

https://wp.dnc.global/2019/05/11/ex... is a demonstrator of a WP application linked to OAuthSD with this extension.

Monitoring : development in progress

We are developing a fork that includes monitoring.
 The code is visible here : https://github.com/bdegoy/openid-co....Operation is similar to what has been described for Plugin OpenID Connect Client pour SPIP.