Custom Authentication with PnP Web No Modal SDK
Custom Authentication is a way to authenticate users with your custom authentication service. For example, while authenticating with Google, you can use your own Google Client ID and Dashboard to authenticate users directly or use aggregator services like Auth0, Firebase, AWS Cognito etc. Additionally, you can make your own JWT token authentication system and pass the ID Token to Web3Auth to generate a private key for them.
To enable this, you need to Create a Verifier from the Custom Authentication tab of your project from the Web3Auth Developer Dashboard with your desired configuration.
This is a paid feature and the minimum pricing plan to use this SDK in a production environment is the Growth Plan. You can use this feature in Web3Auth Sapphire Devnet network for free.
Installing Auth Adapter
Social logins in Web3Auth are enabled by the auth-adapter
. Natively,
it is already present and preconfigured within the Plug and Play SDK, but for custom configurations,
you need to install the adapter package.
- npm
- Yarn
- pnpm
npm install --save @web3auth/auth-adapter
yarn add @web3auth/auth-adapter
pnpm add @web3auth/auth-adapter
Configuring Auth Adapter
While instantiating the Auth Adapter, you can pass some configuration objects to the constructor.
One of these configurations is the adapterSettings
configuration which enables you to make changes
in the adapter, enabling you to do things like Whitelabeling and Custom Authentication among other
things.
Checkout the auth-adapter
SDK Reference for more details on
different configurations you can pass for customizations.
loginConfig
The loginConfig
parameter of adapterSettings
in auth-adapter
contains the following
properties:
- Table
- Type Declarations
loginConfig: { "identifier of social login": { params } }
params
Parameter | Description |
---|---|
verifier | |
typeOfLogin | The type of login. Refer to enum LOGIN_TYPE |
name | Display Name. If not provided, we use the default for auth app |
description | Description for button. If provided, it renders as a full length button. else, icon button |
clientId | Custom client_id. If not provided, we use the default for auth app |
verifierSubIdentifier | The field in JWT token which maps to verifier id. Please make sure you selected correct JWT verifier id in the developer dashboard. It accepts string as a value. |
logoHover | Logo to be shown on mouse hover. If not provided, we use the default for auth app |
logoLight | Logo to be shown on dark background (dark theme). If not provided, we use the default for auth app |
logoDark | Logo to be shown on light background (light theme). If not provided, we use the default for auth app |
mainOption | Show login button on the main list |
showOnModal | Whether to show the login button on modal or not |
showOnDesktop | Whether to show the login button on desktop |
showOnMobile | Whether to show the login button on mobile |
showOnSocialBackupFactor | If we are using social logins as a backup factor, then this option will be used to show the type of social login on the social backup login screen. |
jwtParameters | Custom jwt parameters to configure the login. Useful for Auth0 configuration |
export type LoginConfig = Record<
string,
{
verifier: string;
/**
* The type of login. Refer to enum `LOGIN_TYPE`
*/
typeOfLogin: TypeOfLogin;
/**
* Display Name. If not provided, we use the default for auth app
*/
name?: string;
/**
* Description for button. If provided, it renders as a full length button. else, icon button
*/
description?: string;
/**
* Custom client_id. If not provided, we use the default for auth app
*/
clientId?: string;
verifierSubIdentifier?: string;
/**
* Logo to be shown on mouse hover. If not provided, we use the default for auth app
*/
logoHover?: string;
/**
* Logo to be shown on dark background (dark theme). If not provided, we use the default for auth app
*/
logoLight?: string;
/**
* Logo to be shown on light background (light theme). If not provided, we use the default for auth app
*/
logoDark?: string;
/**
* Show login button on the main list
*/
mainOption?: boolean;
/**
* Whether to show the login button on modal or not
*/
showOnModal?: boolean;
/**
* Whether to show the login button on desktop
*/
showOnDesktop?: boolean;
/**
* Whether to show the login button on mobile
*/
showOnMobile?: boolean;
/**
* If we are using social logins as a backup factor,
* then this option will be used to show the type of social login
* on the social backup login screen.
*/
showOnSocialBackupFactor?: boolean;
/**
* Custom jwt parameters to configure the login. Useful for Auth0 configuration
*/
jwtParameters?: JwtParameters;
}
>;
export type TypeOfLogin =
| "google"
| "facebook"
| "reddit"
| "discord"
| "twitch"
| "apple"
| "github"
| "linkedin"
| "twitter"
| "weibo"
| "line"
| "email_password"
| "passwordless"
| "jwt"
| "passkeys"
| "email_passwordless"
| "sms_passwordless";
Logging In
While using the Web3Auth Plug and Play No Modal SDK, you have the option to use the connectTo
function, which enables you to customize the login process according to the parameters you have for
your custom authentication service.
connectTo()
To log a user in the Web3Auth Plug and Play No Modal SDK, you need to call the connectTo()
function. This function helps you customize the login process according to your own needs, by taking
the following parameters:
- Table
- Function Definition
Variable | Description |
---|---|
walletName | Wallet Adapter you want to use for logging in your user. It accepts WALLET_ADAPTER_TYPE . |
loginParams? | Login parameters specific to your wallet adapter. Although this is defined as a generic type T , you can use AuthLoginParams as a reference for typical parameters. |
connectTo<T>(walletName: WALLET_ADAPTER_TYPE, loginParams?: T): Promise<IProvider | null>;
export declare const WALLET_ADAPTERS: {
AUTH: string;
WALLET_CONNECT_V2: string;
SFA: string;
TORUS_SOLANA: string;
TORUS_EVM: string;
COINBASE: string;
};
export type WALLET_ADAPTER_TYPE = (typeof WALLET_ADAPTERS)[keyof typeof WALLET_ADAPTERS];
export type AuthLoginParams = LoginParams & {
login_hint?: string;
};
export type LoginParams = BaseRedirectParams & {
/**
* loginProvider sets the oauth login method to be used.
* You can use any of the valid loginProvider from the supported list.
*/
loginProvider: LOGIN_PROVIDER_TYPE | CUSTOM_LOGIN_PROVIDER_TYPE;
/**
* You can set the `mfaLevel` to customize when mfa screen should be shown to user.
* It currently accepts 4 values:-
* - `'default'`: Setting mfa level to `default` will present mfa screen to user on every third login.
* - `'optional'`: Setting mfa level to `default` will present mfa screen to user on every login but user can skip it.
* - `'mandatory'`: Setting mfa level to `mandatory` will make it mandatory for user to setup mfa after login.
* - `'none'`: Setting mfa level to `none` will make the user skip the mfa setup screen
*
* Defaults to `none`
* @defaultValue `none`
*/
mfaLevel?: MfaLevelType;
/**
* This option is for internal use only in torus wallet and has no effect
* on user's login on other dapps.
*
* Defaults to false
* @defaultValue false
* @internal
*/
getWalletKey?: boolean;
/**
* extraLoginOptions can be used to pass standard oauth login options to
* loginProvider.
*
* For ex: you will have to pass `login_hint` as user's email and `domain`
* as your app domain in `extraLoginOptions` while using `email_passwordless`
* loginProvider
*/
extraLoginOptions?: ExtraLoginOptions;
/**
* Custom Logins can get a dapp share returned to them post successful login.
* This is useful if the dapps want to use this share to allow users to login seamlessly
* dappShare is a 24 word seed phrase
*/
dappShare?: string;
/**
* This curve will be used to determine the public key encoded in the jwt token which returned in
* `getUserInfo` function after user login.
* You can use that public key from jwt token as a unique user identifier in your backend.
*
* - `'secp256k1'`: secp256k1 based pub key is added as a wallet public key in jwt token to use.
* - `'ed25519'`: ed25519 based pub key is added as a wallet public key in jwt token to use.
*
* Note: This parameter won't change format of private key returned by auth. Private key returned
* by auth is always `secp256k1`.
*
*
* @defaultValue secp256k1
*/
curve?: SUPPORTED_KEY_CURVES_TYPE;
/**
* Allows the dapp to set a custom redirect url for the manage mfa flow.
*
*/
dappUrl?: string;
};
Know more about the connectTo
function in the
Usage SDK Reference
It is mandatory to pass the idToken
parameter in the extraLoginOptions
object when logging in
through your Custom JWT Token
.
Further, to enable Custom Authentication, the loginParams
parameter takes in another object called
extraLoginOptions
which contains the following properties:
- Table
- Interface
ExtraLoginOptions
Parameter | Description |
---|---|
domain | Your Auth0 account domain such as 'example.auth0.com' , 'example.eu.auth0.com' or , 'example.mycompany.com' (when using custom domains) |
client_id | The Client ID found on your Application settings page |
redirect_uri | The default URL where Auth0 will redirect your browser to with the authentication result. It must be whitelisted in the "Allowed Callback URLs" field in your Auth0 Application's settings. If not provided here, it should be provided in the other methods that provide authentication. |
leeway | The value in seconds used to account for clock skew in JWT expirations. Typically, this value is no more than a minute or two at maximum. Defaults to 60s. |
verifierIdField | The field in jwt token which maps to verifier id |
isVerifierIdCaseSensitive | Whether the verifier id field is case sensitive |
additionalParams | If you need to send custom parameters to the Authorization Server, make sure to use the original parameter name. |
display | - 'page' : displays the UI with a full page view - 'popup' : displays the UI with a popup window - 'touch' : displays the UI in a way that leverages a touch interface - 'wap' : displays the UI with a "feature phone" type interface |
prompt | - 'none' : do not prompt user for login or consent on re-authentication - 'login' : prompt user for re-authentication - 'consent' : prompt user for consent before processing request - 'select_account' : prompt user to select an account |
max_age | Maximum allowable elapsed time (in seconds) since authentication. If the last time the user authenticated is greater than this value, the user must be re-authenticated. |
ui_locales | The space-separated list of language tags, ordered by preference. For example: 'fr-CA fr en' . |
id_token_hint | Previously issued ID Token. |
login_hint | The user's email address or other identifier. When your app knows which user is trying to authenticate, you can provide this parameter to pre-fill the email box or select the right session for sign-in. This currently only affects the classic Lock experience. |
acr_values | |
scope | The default scope to be used on authentication requests. The defaultScope defined in the Auth0Client is included along with this scope |
audience | The default audience to be used for requesting API access. |
connection | The name of the connection configured for your application. If null, it will redirect to the Auth0 Login Page and show the Login Widget. |
export interface ExtraLoginOptions extends BaseLoginOptions {
/**
* Your Auth0 account domain such as `'example.auth0.com'`,
* `'example.eu.auth0.com'` or , `'example.mycompany.com'`
* (when using [custom domains](https://auth0.com/docs/custom-domains))
*/
domain?: string;
/**
* The Client ID found on your Application settings page
*/
client_id?: string;
/**
* The default URL where Auth0 will redirect your browser to with
* the authentication result. It must be whitelisted in
* the "Allowed Callback URLs" field in your Auth0 Application's
* settings. If not provided here, it should be provided in the other
* methods that provide authentication.
*/
redirect_uri?: string;
/**
* The value in seconds used to account for clock skew in JWT expirations.
* Typically, this value is no more than a minute or two at maximum.
* Defaults to 60s.
*/
leeway?: number;
/**
* The field in jwt token which maps to verifier id
*/
verifierIdField?: string;
/**
* Whether the verifier id field is case sensitive
* @defaultValue true
*/
isVerifierIdCaseSensitive?: boolean;
}
export interface BaseLoginOptions {
/**
* If you need to send custom parameters to the Authorization Server,
* make sure to use the original parameter name.
*/
[key: string]: unknown;
/**
* - `'page'`: displays the UI with a full page view
* - `'popup'`: displays the UI with a popup window
* - `'touch'`: displays the UI in a way that leverages a touch interface
* - `'wap'`: displays the UI with a "feature phone" type interface
*/
display?: "page" | "popup" | "touch" | "wap" | string;
/**
* - `'none'`: do not prompt user for login or consent on re-authentication
* - `'login'`: prompt user for re-authentication
* - `'consent'`: prompt user for consent before processing request
* - `'select_account'`: prompt user to select an account
*/
prompt?: "none" | "login" | "consent" | "select_account" | string;
/**
* Maximum allowable elapsed time (in seconds) since authentication.
* If the last time the user authenticated is greater than this value,
* the user must be re-authenticated.
*/
max_age?: string | number;
/**
* The space-separated list of language tags, ordered by preference.
* For example: `'fr-CA fr en'`.
*/
ui_locales?: string;
/**
* Previously issued ID Token.
*/
id_token_hint?: string;
/**
* The user's email address or other identifier. When your app knows
* which user is trying to authenticate, you can provide this parameter
* to pre-fill the email box or select the right session for sign-in.
*
* This currently only affects the classic Lock experience.
*/
login_hint?: string;
acr_values?: string;
/**
* The default scope to be used on authentication requests.
* The defaultScope defined in the Auth0Client is included
* along with this scope
*/
scope?: string;
/**
* The default audience to be used for requesting API access.
*/
audience?: string;
/**
* The name of the connection configured for your application.
* If null, it will redirect to the Auth0 Login Page and show
* the Login Widget.
*/
connection?: string;
}
Example
Since we're using the @web3auth/no-modal
, ie. the Plug and Play No Modal SDK, the loginConfig
can include custom JWT-based authentication as well. This way, we can use any of our preferred login
providers and further setup their configs while logging the user in and passing over the
extraLoginOptions
in the connectTo
function.
Single Verifier
import { AuthAdapter } from "@web3auth/auth-adapter";
const authAdapter = new AuthAdapter({
adapterSettings: {
loginConfig: {
jwt: {
verifier: "YOUR-VERIFIER-NAME-ON-WEB3AUTH-DASHBOARD",
typeOfLogin: "jwt",
clientId: "YOUR-CLIENTID-FROM-LOGIN-PROVIDER",
},
},
},
privateKeyProvider,
});
web3auth.configureAdapter(authAdapter);
- Auth0
- Farcaster
- JWT
- Discord
- Email Passwordless
- SMS Passwordless
- Twitch
- Apple
- GitHub
import { WALLET_ADAPTERS } from "@web3auth/base";
// inside your async function with on click handler
const web3authProvider = await web3auth.connectTo(WALLET_ADAPTERS.AUTH, {
loginProvider: "google",
});
const web3authProvider = await web3auth.connectTo(WALLET_ADAPTERS.AUTH, {
loginProvider: "jwt",
extraLoginOptions: {
verifierIdField: "sub", // same as your JWT Verifier ID
domain: "https://YOUR-APPLICATION-DOMAIN", // your service provider domain, e.g. Auth0
},
});
import { WALLET_ADAPTERS } from "@web3auth/base";
// inside your async function with on click handler
const web3authProvider = await web3auth.connectTo(WALLET_ADAPTERS.AUTH, {
loginProvider: "farcaster",
});
// Login using JWT, either obtained from Firebase, Okta, Auth0 or bring your own JWT.
const web3authProvider = await web3auth.connectTo(WALLET_ADAPTERS.AUTH, {
loginProvider: "jwt",
extraLoginOptions: {
id_token: "idToken", // in JWT Format
verifierIdField: "sub", // same as your JWT Verifier ID
},
});
import { WALLET_ADAPTERS } from "@web3auth/base";
const web3authProvider = await web3auth.connectTo(WALLET_ADAPTERS.AUTH, {
loginProvider: "facebook",
});
import { WALLET_ADAPTERS } from "@web3auth/base";
const web3authProvider = await web3auth.connectTo(WALLET_ADAPTERS.AUTH, {
loginProvider: "email_passwordless",
extraLoginOptions: {
login_hint: "hello@web3auth.io", // email to send the OTP to
},
});
import { WALLET_ADAPTERS } from "@web3auth/base";
const web3authProvider = await web3auth.connectTo(WALLET_ADAPTERS.AUTH, {
loginProvider: "sms_passwordless",
extraLoginOptions: {
login_hint: "+65-XXXXXXX",
},
});
import { WALLET_ADAPTERS } from "@web3auth/base";
const web3authProvider = await web3auth.connectTo(WALLET_ADAPTERS.AUTH, {
loginProvider: "discord",
});
import { WALLET_ADAPTERS } from "@web3auth/base";
const web3authProvider = await web3auth.connectTo(WALLET_ADAPTERS.AUTH, {
loginProvider: "twitter",
});
import { WALLET_ADAPTERS } from "@web3auth/base";
const web3authProvider = await web3auth.connectTo(WALLET_ADAPTERS.AUTH, {
loginProvider: "reddit",
});
import { WALLET_ADAPTERS } from "@web3auth/base";
const web3authProvider = await web3auth.connectTo(WALLET_ADAPTERS.AUTH, {
loginProvider: "twitch",
});
import { WALLET_ADAPTERS } from "@web3auth/base";
const web3authProvider = await web3auth.connectTo(WALLET_ADAPTERS.AUTH, {
loginProvider: "apple",
});
import { WALLET_ADAPTERS } from "@web3auth/base";
const web3authProvider = await web3auth.connectTo(WALLET_ADAPTERS.AUTH, {
loginProvider: "github",
});
import { WALLET_ADAPTERS } from "@web3auth/base";
const web3authProvider = await web3auth.connectTo(WALLET_ADAPTERS.AUTH, {
loginProvider: "linkedin",
});
Aggregate Verifier
import { AuthAdapter } from "@web3auth/auth-adapter";
const authAdapter = new AuthAdapter({
adapterSettings: {
loginConfig: {
// Google login
google: {
verifier: "YOUR_AGGREGATE_VERIFIER_NAME", // Please create an aggregate verifier on the developer dashboard and pass the name here
verifierSubIdentifier: "YOUR_SUB_VERIFIER_NAME", // Pass in the sub verifier name here
typeOfLogin: "google", // Pass on the login provider of the verifier you've created
clientId: "YOUR_GOOGLE_CLIENT_ID", // based on sub verifier, pass in the clientId of the login provider here - Please note this differs from the Web3Auth ClientID.
},
github: {
verifier: "YOUR_AGGREGATE_VERIFIER_NAME", // Please create an aggregate verifier on the developer dashboard and pass the name here
verifierSubIdentifier: "YOUR_SUB_VERIFIER_NAME", // Pass in the sub verifier name here
typeOfLogin: "github", // Pass on the login provider of the verifier you've created
clientId: "YOUR_GITHUB_CLIENT_ID", // based on sub verifier, pass in the clientId of the login provider here - Please note this differs from the Web3Auth ClientID.
},
},
},
privateKeyProvider,
});
web3auth.configureAdapter(authAdapter);
// When user clicks Google button, use this to Login with Google
const web3authProvider = await web3auth.connectTo("auth", {
loginProvider: "google",
});
// When user clicks GitHub button, use this to Login with GitHub via Auth0
const web3authProvider = await web3auth.connectTo("auth", {
loginProvider: "github",
extraLoginOptions: {
domain: "YOUR_AUTH0_DOMAIN", // Pass the Auth0 Domain here, eg. https://web3auth.au.auth0.com
// This corresponds to the field inside jwt which must be used to uniquely identify the user.
verifierIdField: "YOUR_AUTH0_VERIFIER_ID_FIELD", // This is mapped b/w google and github logins.
isVerifierIdCaseSensitive: true, // only if the verifier id is case sensitive, else remove this line
},
});