In this article, we will cover the required steps to add a custom OAuth2/OpenID Connect provider to Strapi 4.
First things first, what are OAuth2 and OpenID Connect?
OAuth2 handles authorization whereas OpenID Connect handles authentication. What’s the difference you may ask, well, OAuth2 is built to manage authorization access to APIs with scopes, and OpenID Connect is built on top of OAuth2 to manage authentication of users.
Strapi actually relies on OpenID Connect protocol to retrieve user info and create the internal Strapi user upon provider account connection.
If you want more details on what are those and the differences, I can only recommend the OAuth2 and OpenID Connect: The Professional Guide ebook by the guys behind Auth0 by Okta.
Prerequisites
Before you can jump into this content, you need to have a basic understanding of the following.
- Basic knowledge of JavaScript
- A Node.js ready environment
- Basic understanding of Strapi - get started here ## What is Strapi
Strapi is an open-source headless CMS based on Node.js that is used to develop and manage content using a Restful API and/or GraphQL.
With Strapi, we can scaffold our API faster and consume the content via APIs using any HTTP client or GraphQL enabled frontend.
Scaffolding a Strapi project
To scaffold a new Strapi project is very simple and works precisely as installing a new frontend framework.
We are going to start by running the following commands and testing them out in our default browser.
npx create-strapi-app strapi-api --quickstart
# OR
yarn create strapi-app strapi-api --quick start
The command above will scaffold a new strapi project in the directory you specified.
Next, run yarn build
to build your app and yarn develop
to run the new project if it doesn't start automatically.
The last command will open a new tab with a page to register your new admin of the system. Go ahead and fill out the form and click on the submit button to create a new Admin.
Patch Package
What is it?
patch-package
lets app authors instantly make and keep fixes to npm dependencies. It's a vital band-aid for those of us living on the bleeding edge.
Head over to its GitHub repo if you want to know more.
Why do we need it?
Well, Strapi manages OAuth2/OpenID Connect through a dependency, Grant. It then uses Purest to make some API calls to retrieve User information.
In order to have our OAuth2/OpenID Connect Provider to work with Strapi, we then have 2 options:
- Get those dependencies to add our Provider (good luck with that if it is not something mainstream) and then have Strapi to use them
- Patch those dependencies and add our own
I guess you figured we will go with the second option ;)
Set it up in your project
Simply follow its setup instructions
Grant
What is it?
Grant is an OAuth2/OpenID Connect proxy for Node.js with 200+ preconfigured providers.
More information in its GitHub repo
Which changes are needed?
First, we need to check if the provider you want to use already exists in grant in the oauth.json file
- It’s already there
- No patch required, you’re good to proceed to the next package
- It’s not listed
- That’s the case in which we need to patch it ## Prepare the changes
- Add the OAuth2/OpenId Connect provider to the
node_modules/grant/config/oauth.json
file
"trackmania": {
"authorize_url": "https://api.trackmania.com/oauth/authorize",
"access_url": "https://api.trackmania.com/api/access_token",
"oauth": 2,
"scope_delimiter": " "
}
- Add the OAuth2/OpenId Connect provider to the
node_modules/grant/config/profile.json
file
"trackmania": {
"profile_url": "https://api.trackmania.com/api/user"
}
Make it a patch
Execute the following command
npm patch-package grant
# OR
yarn patch-package grant
This will create the patches/grant+VERSION.patch
file where VERSION is the one you have currently installed
Purest
What is it?
Purest is a REST API client library with embeded providers, think of it as an axios with preconfigured base urls and endpoints for each provider.
More information on its GitHub repo
Which changes are needed?
Same first step than Grant: Is your provider already listed in Purest?
- Yep!
- No patch required, you’re good to proceed to the next package
- Nope
- Let’s patch it! ## Prepare the changes
- Add the OAuth2/OpenID Connect provider to the
node_modules/purest/config/providers.json
file
"trackmania": {
"default": {
"origin": "https://api.trackmania.com",
"path": "api/{path}",
"headers": {
"authorization": "Bearer {auth}"
}
},
"oauth": {
"origin": "https://api.trackmania.com",
"path": "oauth/{path}"
}
Make it a patch
Execute the following command
npm patch-package purest
# OR
yarn patch-package purest
This will create the patches/purest+VERSION.patch
file where VERSION is the one you have currently installed
Strapi Plugin Users Permissions
What is it?
This is the Strapi’s internal way of handling Users and Permissions, in which the supported OAuth2/OpenID Connect providers are implemented
Which changes are needed?
We will need to edit multiple files for the provider to work, just follow along ;)
Prepare the changes
- Add grant cofig in
node_modules/@strapi/plugin-users-permissions/server/bootstrap/grant-config.js
file
trackmania: {
enabled: true,
icon: 'trackmania',
key: '',
secret: '',
basicHeader: '',
openPlanetSecret: '',
callback: `${baseURL}/trackmania/callback`,
scope:[]
}
- Add implementation in
node_modules/@strapi/plugin-users-permissions/server/services/providers-registry.js
file
async trackmania({ accessToken }) {
const trackmania = purest({ provider: 'trackmania' });
const { body: userBody } = await trackmania.get('user').auth(accessToken).request();
// The userBody may differ from provider to provider, refer to the provider documentation for details
return {
username: userBody.displayName,
email: userBody.email
};
}
Make it a patch
Execute the following command
npm patch-package @strapi/plugin-users-permissions
# OR
yarn patch-package @strapi/plugin-users-permissions
This will create the patches/@strapi/plugin-users-permissions+VERSION.patch
file where VERSION is the one you have currently installed
Conclusion
This article demonstrated how to add a custom Login Provider to Strapi 4.
Here is a demo repo where you’ll find an example implemetation.
Let me know if you have any question/suggestion, I’d love to hear your feedback ;)