Integrating Immutable Passport
Estimate time to complete: 15 minutes
A key component of your game integration is to make sure you can onboard users successfully. We’ve created Immutable Passport as the product which provides you with authentication and a web3 wallet out of the box. This tutorial is to set up both the authentication and the wallet component to your game.
Task 1: Install and initialise Passport
Recall your project that you set up in the Immutable Hub from the previous step. Click on this project and go to "Passport" in the left-hand menu.
Once you've set up, you'll be given a list of endpoints and keys for both website and native app projects.
From here, you can create default Passport clients or add a client.
Once you have created a Passport client, you will be given a list of endpoints and keys for both website and native app projects.
Next, we'll need to initialise the Passport client.
Passport - how it works
The Passport constructor accepts a PassportModuleConfiguration
object, which has the following interface. Your key variables here are below. Details on other variables can be found in this article.
clientId
- comes from your Client ID from the Immutable Hub that you just set uplogoutRedirectUri
- must match one of the Logout URLs in the Immutable Hub that you just set upredirectUri
- must match one of the Redirect URLs in the Immutable Hub that you just set up
interface PassportModuleConfiguration {
baseConfig: ImmutableConfiguration;
clientId: string;
logoutRedirectUri?: string; // defaults to first logout redirect URI specified in the Immutable Hub
logoutMode?: 'redirect' | 'silent'; // defaults to 'redirect'
redirectUri: string;
scope?: string;
audience?: string;
}
An instance of an ImmutableConfiguration
, which defines shared configuration across all the Immutable modules, such
as the environment. This can be initialised as follows:
import { config } from '@imtbl/sdk';
const PUBLISHABLE_KEY = 'YOUR_PUBLISHABLE_KEY'; // Replace with your Publishable Key from the Immutable Hub
const baseConfig = {
environment: config.Environment.PRODUCTION,
publishableKey: PUBLISHABLE_KEY,
};
Putting it altogether, you can copy and paste the following code block to initialise Passport. Pay attention to these variables:
clientId
- comes from your Client ID from the Immutable Hub that you just set uplogoutRedirectUri
- must match one of the Logout URLs in the Immutable Hub that you just set upredirectUri
- must match one of the Redirect URLs in the Immutable Hub that you just set up
import { config, passport } from '@imtbl/sdk';
const passportInstance = new passport.Passport({
baseConfig: {
environment: config.Environment.SANDBOX, // or Environment.PRODUCTION
publishableKey: '<YOUR_PUBLISHABLE_KEY>', // replace with your publishable API key from Hub
},
clientId: '<YOUR_CLIENT_ID>', // replace with your client ID from Hub
redirectUri: 'https://localhost:3000/redirect', // replace with one of your redirect URIs from Hub
logoutRedirectUri: 'https://localhost:3000/logout', // replace with one of your logout URIs from Hub
audience: 'platform_api',
scope: 'openid offline_access email transact',
popupOverlayOptions: {
disableGenericPopupOverlay: false, // Set to true to disable the generic pop-up overlay
disableBlockedPopupOverlay: false, // Set to true to disable the blocked pop-up overlay
}
});
Task 2: Authenticate users with Passport
This step should take you 5 minutes.
2.1. Initialise the provider
Passport's zkEVM provider implements the Ethereum EIP-1193 standard, which means that you can use the same logic to interact with a user's Passport wallet as you would with any other Ethereum wallet.
As it implements the EIP-1193 standard, you can create a Passport provider and call a range of RPC methods on it directly. Alternatively, you can use the Passport provider in an Ethers.js provider.
- Passport (EIP-1193)
- Ethers.js
Use the eth_requestAccounts
method to login users directly with EIP-1193 provider.
const provider = passportInstance.connectEvm();
const accounts = await provider.request({ method: 'eth_requestAccounts' });
See the full range of supported RPC methods.
Passport is also compatible with existing Ethereum libraries and products.
For example, you may want to use the Passport provider when creating a new provider with Ethers.js, which abstracts the complexity of interacting directly with an EIP-1193 provider. Note that you will still need to call provider.send("eth_requestAccounts", [])
before transacting or signing messages.
const passportProvider = passportInstance.connectEvm();
const web3Provider = new ethers.providers.Web3Provider(passportProvider);
const accounts = await web3Provider.send('eth_requestAccounts', []);
The login flow is triggered by calling the requestAccounts RPC on the Passport provider.
Once the requestAccounts
RPC method has been called, the Passport module will begin the authentication process
if the user is not already logged in. If the user successfully authenticates, then their
wallet will be initialised, and the Promise returned by eth_requestAccounts
will resolve with an array containing
the user's wallet address.
Note: When the requestAccounts
method is called, an iFrame will be appended to the DOM, which is responsible for
securing the user's wallet. Consumers will need to ensure that it is not removed from the DOM by any external process.
For example, if you are using NextJS's Client-side Rendering,
it is recommended that requestAccounts
is not called before Client-side Rendering has finished. This can be achieved by
wrapping the requestAccounts
call with a useEffect
hook.
2.2. Trigger the login process
The login flow is triggered by calling the requestAccounts RPC on the Passport provider:
If you are using an EIP-1193 provider directly, then you can call the requestAccounts
method directly:
const provider = passport.connectEvm();
const accounts = await provider.request({ method: 'eth_requestAccounts' });
import { ethers } from 'ethers';
const passportProvider = passport.connectEvm();
const provider = new ethers.providers.Web3Provider(passportProvider);
const accounts = await provider.send('eth_requestAccounts', []);
Once the requestAccounts
RPC method has been called, the Passport module will begin the authentication process. If the user
successfully authenticates, then the user will be redirected to the Redirect URI
that was set in the
OIDC Configuration
.
2.3. Configure the login callback
At this point, the route that handles requests to the Redirect URI
will need to call the loginCallback
method on
page load. Your specific implementation will vary based on your application's architecture, but a vanilla Javascript
implementation may look as follows:
window.addEventListener('load', function () {
passport.loginCallback();
});
The loginCallback
method will then process the response from the Immutable's auth domain, store the authenticated
user in session storage and close the pop-up. Once the authentication flow is complete, the Promise
returned from
requestAccounts
will also resolve with a single-item array containing the user's address.
You might find these articles useful, but you don't need to set this up now.
Task 3: Implement "Sign-in with Immutable" button
We provide default assets for your front-end in order to give your players access to Immutable Passport. Implemented either the dark or light mode option below. You can right click to download the appropriate SVG file.
When to use | In dark mode situations | In light mode situations |
---|---|---|
Default sign up and sign in experiences | ||
In smaller spaces less than 300px width, you can use the logo lockup in button only however button should be proceded with the words "Sign in with" | Sign in with | Sign in with |
Additional customisation can be found in this article should you need to do so.