The reason for Keyring’s existence is to make it easier for developers to work with services which require authentication of some sort. Here’s a quick primer on how to do that.
Core Methods
There are a few core methods (contained in the Keyring
class, in /keyring.php
) which you are most likely to interact with:
Keyring::init()
should be used if you’d like to access the global instance of Keyring, assign it to a variable, or whatever. You should never callnew Keyring();
Keyring::get_registered_services()
will give you an array containing all of Keyring’s currently registered Services. The array is keyed off the slug/name of the service, and the elements are usable instances of the class for a Service.Keyring::get_service_by_name( $name )
returns a single Service, based on its slug/name.Keyring::get_token_store()
will return a reference to the Token Store in use by Keyring. If required, it will initiate the Token Store first.
Keyring Utils
In addition to the core methods above, there are some utility methods provided, within the Keyring_Util
class.
Keyring_Util::debug( $string, $level )
will output a string to the debug log. The default$level
isKEYRING__DEBUG_NOTICE
which will just output into the error log. If you passKEYRING__DEBUG_WARN
then it will also echo the message to the user, andKEYRING__DEBUG_ERROR
will force awp_die()
and output the message to the user.Keyring_Util::is_service( $object )
checks an object to see if it appears to be aKeyring_Service
.Keyring_Util::has_custom_ui( $service, $action )
just checks to see if a Service has registered a custom UI for a specific action, based on the specific Keyring action hook.Keyring_Util::admin_url( $service, $params )
generates a URL for use within Keyring, based on the admin UI being enabled. Note that this does not automatically add thekr_nonce
parameter required for most internal links, but that can be passed in via the$params
array.Keyring_Util::connect_to( $service, $for )
starts the connection process for the specified$service
and flags the connection so that once complete, you can grab it based on the$for
value, which can be retrieved from the meta of$keyring_request_token
after a Token is verified.Keyring_Util::token_select_box( $tokens, $name, $create )
creates a simple HTMLselect
box which allows a user to pick from a list of existing Tokens. It uses theget_display()
method of each Token to render something for the user to see, and the unique id of the Token as thevalue
. If you set$create
totrue
then an additional option will be added to the top of the list, allowing the user to create a new connection (which will pass the stringnew
as the value when submitted).
Interfacing with Keyring/Getting a Connection
If you’re just using an existing Service, and just need a connection, then you should be able to interact with Keyring pretty easily. You can do things like:
Check if a user is connected to a service already
$service->is_connected();
Load an existing Token when you know its unique id
Keyring::get_token_store()->get_token( array( 'service' => $service_name, 'id' => $unique_id ) );
Use a Token to make authenticated requests against a Service
$service = Keyring::get_service_by_name( $service );
$service->set_token( $token );
print_r( $service->request( $url, $params ) );
Extending Keyring Services
One way to build a plugin which uses Keyring is to extend the Keyring Service classes directly. This can make things easier to work with (less objects to juggle), you just need to make sure you don’t overwrite/redefine any of the core methods and properties in your plugin.
To do this, you’d want to make sure that your plugin loads after Keyring is already loaded, and then you’d do something like class MyPlugin_Facebook extends Keyring_Service_Facebook
. At this point, your inheritance tree would be Keyring_Service > Keyring_Service_OAuth1 > Keyring_Service_OAuth2 > Keyring_Service_Facebook > MyPlugin_Facebook
. Depending on the architecture and complexity of your plugin, this might be a good option.
Customizing Tokens
Mainly through the use of filters, you can manipulate what is stored for Tokens, and especially what meta data is stored along with them. This can be very handy in cases where you need some global information stored with Tokens, or where you want to pass data through the auth flow to maintain some sort of state. You can also use metadata in Tokens to hint to your custom Token Store what to do with a Token, how to store it, etc.
The filters you want to look at for modifying Tokens are below, see the Actions, Filters and Constants Index for more information about them.
keyring_request_token_meta keyring_request_token keyring_{$service}_request_token_params keyring_{$service}_verify_token_params keyring_access_token keyring_access_token_meta
Could you provide a one page example with a connection to say Facebook ( assuming the user has authorized Facebook via the admin already )
The examples above are somewhat confusing if one isn’t sure where to get $service or $unique_id from.
Have a look at https://github.com/beaulebens/keyring-social-importers for some examples on how you can use Keyring to talk to services. At some point I’d like to get some tutorials/better examples up, but for now looking at working code is the best way to get a feel for how it works.
Hmm again, that code doesn’t really illuminate much,
“
$service = \Keyring_Service_Facebook::init(); // good
$service->get_tokens() // cool, gives me an array
$service->get_token() // no dice, and jezz that example code doesn’t show a clear path here.
So this seems to work, but the call to set token seems a bit clunky.
$service = Keyring_Service_Facebook::init();
echo $service->is_connected() ? ‘true’ : ‘false’;
$token = current($service->get_tokens());
$service->set_token( $token );
$res = $service->request(‘https://graph.facebook.com/me?fields=id,name’);
print_r($res);
That’s expected/correct; setting the token like that is definitely something you’ll need to do before using it to make authenticated calls.
Here’s a quick reference on how to have Keyring register a service defined in another plugin, since it’s not immediate from the documentation:
1. Define your service in a
keyring-service-foobar.php
file in your plugin directory as follows:class Keyring_Service_FooBar extends Keyring_Service {
…
}
add_action(‘keyring_load_services’, array(‘Keyring_Service_FooBar’, ‘init’));
2. Add the following to your plugin file:
function register_foobar_service($keyring_services) {
array_push($keyring_services, __DIR__ . ‘/keyring-service-foobar.php’);
return $keyring_services;
}
add_filter(‘keyring_services’, ‘register_foobar_service’);
I hope that’s useful.