Custom providers
Overview
If you can't find a provider in the built-in list, you can add your own custom implementation as shown below.
If you think that SuperTokens should support this provider by default, make sure to let the team know on GitHub.
Create a custom provider
1. Render the authentication method in the authentication UI
What type of UI are you using?
Include the provider in the providers
array in the frontend SDK.
import React from "react";
import SuperTokens from "supertokens-auth-react";
import ThirdParty from "supertokens-auth-react/recipe/thirdparty";
SuperTokens.init({
appInfo: {
apiDomain: "...",
appName: "...",
websiteDomain: "..."
},
recipeList: [
ThirdParty.init({
signInAndUpFeature: {
providers: [
{
id: "custom",
name: "X", // Will display "Continue with X"
// optional
// you do not need to add a click handler to this as
// we add it for you automatically.
buttonComponent: (props: {name: string}) => <div style={{
cursor: "pointer",
border: "1",
paddingTop: "5px",
paddingBottom: "5px",
borderRadius: "5px",
borderStyle: "solid"
}}>{"Login with " + props.name}</div>
}
],
// ...
},
// ...
}),
// ...
]
});
2. Configure the credentials
You can define a custom provider in a couple of ways. The simplest method is to provide the configuration for the AuthorizationEndpoint
, TokenEndpoint
, and the mapping for how the user's ID and email from the provider's profile information endpoint. This appears below:
import SuperTokens from "supertokens-node";
import ThirdParty from "supertokens-node/recipe/thirdparty";
SuperTokens.init({
appInfo: {
appName: "...",
apiDomain: "...",
websiteDomain: "...",
},
recipeList: [
ThirdParty.init({
signInAndUpFeature: {
providers: [{
config: {
thirdPartyId: "custom",
name: "Custom provider",
clients: [{
clientId: "...",
clientSecret: "...",
scope: ["profile", "email"]
}],
authorizationEndpoint: "https://example.com/oauth/authorize",
authorizationEndpointQueryParams: {
"someKey1": "value1",
"someKey2": null
},
tokenEndpoint: "https://example.com/oauth/token",
tokenEndpointBodyParams: {
"someKey1": "value1",
},
userInfoEndpoint: "https://example.com/oauth/userinfo",
userInfoMap: {
fromUserInfoAPI: {
userId: "id",
email: "email",
emailVerified: "email_verified",
}
}
}
}]
}
})
]
})
Handle non standard providers.
Sometimes, one of the steps in the providers interaction may not be per a standard. Therefore, providing the configuration like shown above may not work. To handle this case, you can override any of the steps that happen during the OAuth exchange.
For example, the API call made to get the user's profile info makes a GET
call to the UserInfoEndpoint
with the user's access token. If your provider requires a different method or requires multiple calls to different endpoints to get the profile info, then you can override the default implementation as shown below:
import SuperTokens from "supertokens-node";
import ThirdParty from "supertokens-node/recipe/thirdparty";
SuperTokens.init({
appInfo: {
appName: "...",
apiDomain: "...",
websiteDomain: "...",
},
recipeList: [
ThirdParty.init({
signInAndUpFeature: {
providers: [{
config: {
thirdPartyId: "custom",
name: "Custom provider",
clients: [{
clientId: "...",
clientSecret: "...",
scope: ["profile", "email"]
}],
authorizationEndpoint: "https://example.com/oauth/authorize",
authorizationEndpointQueryParams: {
"response_type": "token", // Changing an existing parameter
"response_mode": "form", // Adding a new parameter
"scope": null, // Removing a parameter
},
tokenEndpoint: "https://example.com/oauth/token"
},
override: (originalImplementation) => {
return {
...originalImplementation,
getUserInfo: async function (input) {
// Call provider's APIs to get profile info
// ...
return {
thirdPartyUserId: "...",
email: {
id: "...",
isVerified: true
},
rawUserInfoFromProvider: {
fromUserInfoAPI: {
"first_name": "...",
"last_name": "..."
},
}
}
}
}
}
}]
}
})
]
})
The original implementation has 4 functions which can be overridden:
-
GetConfigForClientType
Selects the client configuration from the list of clients provided and returns the complete provider configuration. This is a good place to override configuration dynamically. For example, if
login_hint
appears in the request, you can add it to theAuthorizationEndpointQueryParams
by overriding this function. -
GetAuthorisationRedirectURL
This function returns the full URL (along with query params) to which the user needs to navigate to log in.
-
ExchangeAuthCodeForOAuthTokens
This function is responsible for exchanging one time use
Authorization Code
with the user's tokens, such asAccess Token
,ID Token
, etc. -
GetUserInfo
This function is responsible for fetching the user information such as
UserId
,Email
andEmailVerified
using the tokens returned from the previous function.