Custom providers
If SuperTokens doesn't support a provider out of the box, you can use custom providers to add a new third party provider to your application.
note
If you think that this provider should be supported by SuperTokens by default, make sure to let us know here.
#
Step 1: Front End- ReactJS
- Angular
- Vue
- Plain JavaScript
- React Native
Note
You can use the
You can refer to this example app as a reference for using the
supertokens-web-js
SDK which exposes several helper functions that query the APIs exposed by the SuperTokens backend SDK.You can refer to this example app as a reference for using the
supertokens-web-js
SDK.Note
To use SuperTokens with React Native you need to use the
To add login functionality, you need to build your own UI and call the APIs exposed by the backend SDKs. You can find the API spec here
supertokens-react-native
SDK. The SDK provides session management features.To add login functionality, you need to build your own UI and call the APIs exposed by the backend SDKs. You can find the API spec here
What type of UI are you using?
Prebuilt UICustom UI
What type of UI are you using?
Prebuilt UICustom UI
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: <div style={{ cursor: "pointer", border: "1", paddingTop: "5px", paddingBottom: "5px", borderRadius: "5px", borderStyle: "solid" }}>Login with Custom</div> } ], // ... }, // ... }), // ... ]});
#
Step 2: Back Endnote
The OAuth callback URL for your custom provider will be {websiteDomain}{websiteBasePath}/callback/{customId}
, where customId
is the id
given in the config below (the value below is "custom"
).
- NodeJS
- GoLang
- Python
import SuperTokens from "supertokens-node";import Session from "supertokens-node/recipe/session";import ThirdParty from "supertokens-node/recipe/thirdparty";
SuperTokens.init({ appInfo: { apiDomain: "...", appName: "...", websiteDomain: "..." }, supertokens: { connectionURI: "...", }, recipeList: [ ThirdParty.init({ signInAndUpFeature: { providers: [ { id: "custom", get: (redirectURI, authCodeFromRequest) => { return { accessTokenAPI: { // this contains info about the token endpoint which exchanges the auth code with the access token and profile info. url: "https://oauth.example.com/token", params: { // example post params client_id: "<CLIENT ID>", client_secret: "<CLIENT SECRET>", grant_type: "authorization_code", redirect_uri: redirectURI || "", code: authCodeFromRequest || "", //... } }, authorisationRedirect: { // this contains info about forming the authorisation redirect URL without the state params and without the redirect_uri param url: "https://oauth.example.com", params: { client_id: "<CLIENT ID>", scope: "<SCOPES>", response_type: "code", //... } }, getClientId: () => { return "<CLIENT ID>"; }, getProfileInfo: async (accessTokenAPIResponse) => { /* accessTokenAPIResponse is the JSON response from the accessTokenAPI POST call. Using this, you need to return an object of the following type: { id: string, // user ID as provided by the third party provider email?: { // optional id: string, // emailID isVerified: boolean // true if the email is verified already } } */ return { id: "..." }; } } } } ] } }), Session.init({}) ]});
info
To see example implementations for popular third party providers like Google or Facebook, please see our Github repo.
import ( "github.com/supertokens/supertokens-golang/recipe/thirdparty" "github.com/supertokens/supertokens-golang/recipe/thirdparty/tpmodels" "github.com/supertokens/supertokens-golang/supertokens")
func main() { supertokens.Init(supertokens.TypeInput{ RecipeList: []supertokens.Recipe{ thirdparty.Init(&tpmodels.TypeInput{ SignInAndUpFeature: tpmodels.TypeInputSignInAndUp{ Providers: []tpmodels.TypeProvider{ { ID: "custom", Get: func(redirectURI, authCodeFromRequest *string, userContext supertokens.UserContext) tpmodels.TypeProviderGetResponse {
if redirectURI == nil { temp := "" redirectURI = &temp }
if authCodeFromRequest == nil { temp := "" authCodeFromRequest = &temp }
return tpmodels.TypeProviderGetResponse{ AccessTokenAPI: tpmodels.AccessTokenAPI{ // this contains info about the token endpoint which exchanges the auth code with the access token and profile info. URL: "https://oauth.example.com/token", Params: map[string]string{ // example post params "client_id": "<CLIENT ID>", "client_secret": "<CLIENT SECRET>", "grant_type": "authorization_code", "redirect_uri": *redirectURI, "code": *authCodeFromRequest, //... }, }, AuthorisationRedirect: tpmodels.AuthorisationRedirect{ // this contains info about forming the authorisation redirect URL without the state params and without the redirect_uri param URL: "https://oauth.example.com", Params: map[string]interface{}{ "client_id": "<CLIENT ID>", "scope": "<SCOPES>", "response_type": "code", }, }, GetClientId: func(userContext supertokens.UserContext) string { return "<CLIENT ID>" }, GetProfileInfo: func(authCodeResponse interface{}, userContext supertokens.UserContext) (tpmodels.UserInfo, error) { /* authCodeResponse is the JSON response from the AccessTokenAPI POST call. Using this, you need to return an object of the following type:*/ return tpmodels.UserInfo{ ID: "userId from Auth provider", Email: &tpmodels.EmailStruct{ ID: "email of user", IsVerified: true, // true if email is verified already }, }, nil }, } }, }, }, }, }), }, })}
info
To see example implementations for popular third party providers like Google or Facebook, please see our Github repo.
from supertokens_python import init, InputAppInfofrom supertokens_python.recipe import thirdpartyfrom supertokens_python.recipe.thirdparty.provider import Providerfrom supertokens_python.recipe.thirdparty.types import UserInfo, AccessTokenAPI, AuthorisationRedirectAPIfrom typing import Dict, Union, Anyfrom supertokens_python.recipe.thirdparty.types import UserInfo, UserInfoEmail
class CustomProvider(Provider): def __init__(self): super().__init__('<PROVIDER_ID>', False)
async def get_profile_info(self, auth_code_response: Dict[str, Any], user_context: Dict[str, Any]) -> UserInfo: # TODO: fetch user info from provider based on auth_code_response return UserInfo(user_id="...", email=UserInfoEmail(email="..", email_verified=True))
def get_authorisation_redirect_api_info(self, user_context: Dict[str, Any]) -> AuthorisationRedirectAPI: params: Dict[str, Any] = { 'scope': '<SCOPES>', 'response_type': 'code', 'client_id': "<CLIENT ID>", } return AuthorisationRedirectAPI(url="https://oauth.example.com", params=params)
def get_access_token_api_info( self, redirect_uri: str, auth_code_from_request: str, user_context: Dict[str, Any]) -> AccessTokenAPI: params = { 'client_id': "<CLIENT ID>", 'client_secret': "<CLIENT SECRET>", 'grant_type': 'authorization_code', 'code': auth_code_from_request, 'redirect_uri': redirect_uri } return AccessTokenAPI(url="https://oauth.example.com/token", params=params)
def get_redirect_uri(self, user_context: Dict[str, Any]) -> Union[None, str]: return None def get_client_id(self, user_context: Dict[str, Any]) -> str: return "<CLIENT ID>"
init( app_info=InputAppInfo(api_domain="...", app_name="...", website_domain="..."), framework='...', recipe_list=[ thirdparty.init( sign_in_and_up_feature=thirdparty.SignInAndUpFeature(providers=[ CustomProvider() ]) ) ])