SilverStripe OAuth2 authentication, based on the PHP League's OAuth2 client.
Please note that this module is still in early development and should not be used in a production environment. It has not been fully tested, and may undergo significant changes before a stable release.
This module includes the base functionality for fetching access tokens and associating them with members. It provides methods for creating requests to OAuth providers, fetching access tokens with varyious scopes/permissions, and storing them in the database.
This module does not provide “Log in with <provider>” buttons, “Fetch contacts from <provider>” buttons, or any other functionality for actually interacting with providers - it only fetches and stores tokens that will allow you to do that. It’s up to you to install the appropriate packages for third-party providers, and to implement functionality that makes use of the access tokens to fetch data from those providers.
If you’re looking for “Log in with <provider>” functionality, take a look at the add-on for this module: SilverStripe OAuth Login.
This module must be installed with composer. Run composer require bigfork/silverstripe-oauth:*
from the command line, and then run a dev/build
.
Providers are registered as Injector
services using SilverStripe’s YAML configuration. This allows you to specify an “internal” name (passed around in URLs and stored in the database), a PHP class for the provider (that extends League\OAuth2\Client\Provider\AbstractProvider
), and constructor parameters & class properties.
For example, to setup Facebook as a provider, first install the Facebook OAuth2 package, and then add the following to your YAML config:
Injector:
ProviderFactory:
properties:
providers:
'Facebook': '%$FacebookProvider'
FacebookProvider:
class: 'League\OAuth2\Client\Provider\Facebook'
constructor:
Options:
clientId: '12345678987654321'
clientSecret: 'geisjgoesingoi3h1521onnro12rin'
graphApiVersion: 'v2.6'
Note that in the above example, the required redirectUri
constructor argument is missing. This module will automatically update the service configuration to add this argument to all providers, to save having to update the URL when moving between environments/domain names. If the redirectUri
argument is present, it will not be overridden.
This module adds two new models:
A single OAuth access token, belonging to a Member
. Fields include:
Token
- the access token itselfProvider
- the provider name (“internal” name - see Configuration)RefreshToken
- the refresh token (optional)Expires
- the token expiry date (optional)ResourceOwnerID
- the resource owner ID (optional)
This model also has a many_many
relation to OAuthScope
.
A scope (or “permission”) that a token has. This is simply a one-column table (Name
) that stores a list of scopes that all providers may share. Note that scopes in this table are not unique to each provider (for example, Facebook 'email' and Google 'email' scopes will share the same database record).
Has a belongs_many_many
relation to OAuthAccessToken
.
The module includes one extra controller, Bigfork\SilverStripeOAuth\Client\Control\Controller
. This controller is responsible for setting up authentication requests, redirecting users to the third-party providers, and checking/handling tokens & redirections when the user returns to the site from the provider.
A simple class to help build an authentication request URL to create an access token. Also responsible for ensuring the redirectUri
option is set in each provider’s service configuration.
Below are a few examples of how to perform common actions with fetching/using tokens:
$member = Member::currentUser();
$facebookToken = $member->AccessTokens()->filter(['Provider', 'Facebook'])->first();
if (!$facebookToken->includesScope('user_friends')) {
echo 'Unable to access friends list';
}
use Bigfork\SilverStripeOAuth\Client\Helper\Helper;
// Build a URL for fetching a Facebook access token with the 'email' and 'user_friends' permissions
// Will return a URL like: http://mysite.com/oauth/authenticate/?provider=Facebook&scope%5B0%5D=email&scope%5B2%5D=user_friends
$url = Helper::buildAuthorisationUrl('Facebook', ['email', 'user_friends']);
echo "<a href=" . $url . ">Connect to Facebook</a>";
$member = Member::currentUser();
$facebookToken = $member->AccessTokens()->filter(['Provider', 'Facebook'])->first();
if ($facebookToken->isExpired()) {
echo 'Oh no, the Facebook token has expired!';
}
$member = Member::currentUser();
$facebookToken = $member->AccessTokens()->filter(['Provider', 'Facebook'])->first();
if ($facebookToken->isExpired()) {
$facebookToken->refresh();
echo 'Token refreshed successfully';
}
- Tidy Controller - just look at the tests to see why
- Make the default behaviour of only allowing one access token per provider on each member optional, or just remove it
- Allow controller extensions to better influence request/response flow?