Potential use cases include:
- Authenticate 3rd party services like Zapier
- Grant access to REST resources, only to verified consumers
- Release subscription resources only to verified subscribers
- Trigger actions on integrated platforms using authenticated REST hooks
The OAuth2Server Extra doesn't grant any permissions whatsoever, on its own. It only provides a way to grant, manage, revoke and verify access tokens. Call the Snippet [[!verifyOAuth2]]
in your Resource/Template, and the Resource will return an unauthorized or error response, if the request isn't accompanied by a valid access token. You can choose to do whatever you like, with the verified request—the possibilities are endless.
The instructions below assume the default configuration for the OAuth2Server Extra.
-
Install the OAuth2Server Extra via the Extras Installer in MODX Revolution. Hard-refresh your manager window after installing, as with any Extra. NOTE: It's highly recommended to disable the
compress_js
andcompress_css
System Settings, and enable Friendly URLs, for the most reliable performance of this Extra. -
Navigate to the OAuth2Server Custom Manager Page (CMP) via the Extras » Oauth2Server main menu item. You should see a page like this:
-
Fill in the details for "Client ID" and "Redirect URI" (the two required fields). The 3rd party application (3PA) to which you want to grant access, should provide you with a Redirect URI, to which to send the authorization code. Enter that Redirect URI here, so the 3PA can receive the authorization code, and use it to gain an access token. You can leave the "Client Secret" field blank, and a hashed key will be generated for you. Click the "Save" button. NOTE: at this time, on version 0.7.x, the "Grant Types" and "Scope" features are un-tested. Specifying those values may cause unexpected issues.
-
Provide the "Client ID" and "Client Secret" to your 3PA, along with the URL for your "Authorization Endpoint" and your "Token Controller". The OAuth2Server install process should have created two Resources, with the aliases "auth" and "tokens", respectively, for this purpose: Please ensure that the "Token Controller" uses a blank, or "(empty)" Template, and that the "Content Type" is set to "JSON". You can test this by viewing the Resource on the front-end. The extension should be ".json" and you should see nothing but a JSON response body. At version 0.7.x this was not reliably set on all test installations.
-
When the 3PA sends you to the Authorization Endpoint, you must be logged in to MODX as a member of the "Administrator" User Group, and if the correct URL parameters have been sent, you will see a form that looks like this: NOTE: when requesting authorization, the 3PA must pass two URL parameters:
client_id
, which must match a "Client ID" in your site, andresponse_type
, which must equalcode
. -
Clicking "Yes" in the authorization form will send the authorization code to your 3PA. Your 3PA should then make a POST request to the "Token Controller", in order to exchange the authorization code for an access token. NOTE: when requesting an access token, the 3PA must pass four key-value-pairs in the POST request:
client_id
, which must match a "Client ID" in your site,client_secret
, which must match the "Client Secret" for the "Client ID" provided,grant_type
, which must equalauthorization_code
, andcode
, which would have been sent to the 3PA during step 6 above. -
If everything has gone to plan, your 3PA should have received an access token. You can verify that an access token has been generated, by navigating to the "Access Tokens" tab of the OAuth2Server CMP:
Call the [[!verifyOAuth2]]
Snippet in any Resource/Template, to which you want to restrict access to verified requests only. The Snippet accepts four properties:
-
redirectUnauthorized
defaults to1
, which returns either an "unauthorized", or an "error", response and exits the current process. -
redirectTo
defaults to"unauthorized"
, and allows you to choose the type of response, for unverified requests. -
returnOnUnauthorized
defaults to0
, which is what the Snippet will return if the request is unverified. -
returnOnSuccess
defaults to1
, which is what the Snippet will return if the request is verified.
There are countless design patterns with which you can use this Snippet. Here are a few examples:
[[[[!verifyOAuth2:is=`1`:then=`$secret_content`:else=`-`]]]]
NOTE: the "four bracket" syntax, which ensures the "then" result will not be processed erroneously. The conditional returns a string, which either forms a Chunk tag or a MODX comment tag, which returns nothing. In this case, the default redirectUnauthorized
action will also occur.
[[!verifyOAuth2]][[!myJsonResponse]]
This could be used in a Resource, with "Content Type" set to "JSON". If the request is unverified, the default action will be to send an "Unauthorized" response and exit the current process. If verified, page rendering would continue and the next Snippet would execute.
[[!verifyOAuth2? &redirectUnauthorized=`0` &returnOnUnauthorized=`{"success":false}` &returnOnSuccess=`{"success":true}`]]
This overrides much of the default behaviour. In this usage, page rendering will continue regardless of verification! The snippet will return the values passed to the return...
properties. This may be an uncommon pattern, but it's there if you need it.
Version 0.9.x adds a Plugin that verifies all requests to a specified Context. This makes it easy to structure your API endpoint Resources in a similar fashion to "standard" or "real" APIs. For example, a Context might have the key 'api' and your Resources might be under a container with the alias 'v1', making your token controller's URI '/api/v1/tokens.json'. Note: the token controller and authorization endpoint must be excluded using the excludeUris
property if they're to be accessed as intended, while belonging to the restricted Context.
Handing out access tokens is tricky business. As Jason Coward warned me, there are a lot of moving parts.
One issue I ran into, is when the consuming 3PA sends the access token in the header, instead of or in addition to the URL parameter, OAuth2Server will not verify the request, even if a valid access token is provided. This behaviour is determined in the underlying library. Hopefully in a future release I can figure out a workaround.
As I continue to find gotchas, both in the code and in the usage, I'll document them here—front and centre—and hopefully be able to apply fixes.
- Brent Shaffer's oauth2-server-php library is the heart of this Extra.
- Jason Coward provided his usual prudent, insightful guidance.
- The impeccable organization of John Peca's CMP code made it easy for me to steal, resulting in my first CMP. (ExtJS is hard!).
- Ryan Thrash is always incredibly supportive.