Home

Using session keys

Learn how to create a popup-less self-custodial experience.

Openfort's session keys feature is designed to enhance the security and user experience of player accounts within a gaming environment. By utilizing session keys, developers can provide a seamless, popup-less, self-custodial experience to players, while maintaining robust security measures. Session keys serve as a medium to authenticate players, authorize their actions in the game, and grant limited permissions to their web3 accounts.

Overview#

Typically, a web3 account is associated with a single private key which is crucial for signing transactions. However, Openfort introduces a mechanism where the account is separated from the key, allowing players to generate session keys for transaction authorization. Once a player is authenticated, a session key is created on the client-side, which is then registered on the blockchain via Openfort's system. Post registration, the player's account owner needs to authorize the session key, which can then be used for player requests authentication.

Notably, the private key never leaves the player's device, ensuring a secure gaming experience. Moreover, session keys can have set permissions and validity duration, offering more control and security.

Openfort has developed a robust internal infrastructure for handling session keys, ensuring secure and seamless player authentication. Moreover, you can find client libraries for all major game development platforms to help you manage the session keys.

How session keys work#

To delve deeper into the mechanics of session keys, refer to our Technical Dive: Session Keys.Here’s a simplified flow of how session keys operate within Openfort:

  1. Player authentication.
  2. Client-side session key creation.
  3. Session key registration on blockchain through Openfort.
  4. Session key authorization by player's account owner.
  5. Usage of session key for player requests authentication.
session-registration-sign

After this initial flow, the session key can be used to authenticate requests from the player.

Quickstart: Registering and Using a Session Key#

This section will guide you through the process of registering a session key and using it to mint an asset with a player's web3 account. Although this example demonstrates the process in a browser, the same steps are applicable to other client-side applications.

1. Create a session key - Client side#

After you have authenticated your user with your regular authentication system, you can create a session key for them. To create a session key, you need to generate a key pair on the client-side and send the address computed from the public key to your server.

Using one of the official Openfort client libraries everything is handled for you.

Install Openfort.js


_10
npm install @openfort/openfort-js --save

Initialize Openfort


_10
import { Openfort } from '@openfort/openfort-js'
_10
const openfort = new Openfort('pk_test_...')
_10
openfort.createSessionKey()
_10
await openfort.saveSessionKey()

After creating and storing the session key, you can go ahead and register it.

2. Register a session key - Server side Client side#

To register a session key, first send the address from the session key to your server. You can get the address from the session key object created above like this:

Get address from session key


_10
const address = openfort.sessionKey.address;

Then, from your server you can make a request to the Openfort API or use one of our server libraries to register the session key.

Install Openfort


_10
npm install @openfort/openfort-node --save

Initialize '@openfort/openfort-node' wih your secret key


_10
import Openfort from '@openfort/openfort-node'
_10
const openfort = new Openfort('sk_test_...');

The created session key would be valid since the 25th of May 2023 at 7:50 GMT (timestamp 1685001000) and last for 1 hour (timestamp 1685001000). For a useful resource to calculate timestamps online, visit UNIX Timestamp.

Note how the externalOwnerAddress parameter is used to indicate the address of owner of the account that will be created under the specified player. It's only necessary to specify this parameter when the player is doesn't yet have an account in that chain.

Also, note how a policy is used to indicate the policy that will be used to sponsor the gas fees of the transaction to register the session key.

In this example externalOwnerAddress is used to indicate the address of the owner of the account that will be created under the specified player.

Register the session key using Openfort:


_17
const sessionKeyAddress = '0x76e6...9341'
_17
const policyId = 'pol_...'
_17
const playerId = 'pla_...'
_17
const validUntil = 1685001000
_17
const validAfter = 1685001000
_17
const chainId = 80001
_17
const externalOwnerAddress = '0x41e6...9341'
_17
_17
const playerSession = await openfort.sessions.create({
_17
player: playerId,
_17
address: sessionKeyAddress,
_17
chainId: chainId,
_17
validUntil: validUntil,
_17
validAfter: validAfter,
_17
policy: policyId,
_17
externalOwnerAddress: externalOwnerAddress,
_17
})

After registering the session key, you can see it in the dashboard under the player's page.

DashboardRegisterSessionKey

3. Sign the session key - Client side#

The owner of the account of the player needs then to authorize the new session key.

To do so, it needs to sign the userOpHash from the nextAction object returned by the API call to register the session key.

nextAction response object from transaction_intents


_10
"nextAction": {
_10
"type": "sign_with_wallet",
_10
"payload": {
_10
"userOp": {
_10
"sender": "0x32a03030Cf534F299492a91cdeef5eD6A98558e2",
_10
...},
_10
"userOpHash": "0x91b4efe3648c79467f7b50aa9bb1b4eae383a52dd6d741d39ece29ed2ef8362d"
_10
}
_10
},

Once the content of the nextAction parameter above is signed by the owner of the account, it has to be sent to Openfort using the endpoint /v1/sessions/:id/signature as shown below:

Sign and send the session key registration:


_10
await openfort.loadSessionKey()
_10
await openfort.sendSignatureSessionRequest(
_10
playerSession.id,
_10
SIGNED_USED_OP_HASH
_10
)

4. Using the session key - Server side Client side#

After the session key is registered, it can be used to authenticate requests from the player. Whenever you create a transaction intent from your backend, a signature will be needed from the session key or owner of the players' web3 account.

Create a transaction intent:


_18
const playerId = 'pla_...'
_18
const policyId = 'pol_...'
_18
const contractId = 'con_...'
_18
const chainId = 80001
_18
const optimistic = true
_18
_18
const interaction: Interaction = {
_18
contract: contractId,
_18
functionName: 'mint',
_18
functionArgs: [playerId],
_18
}
_18
const transactionIntent = await openfort.transactionIntents.create({
_18
player: playerId,
_18
chainId: chainId,
_18
optimistic: optimistic,
_18
interactions: [interaction],
_18
policy: policyId,
_18
})

After creating the transaction intent, the session key will need to sign the nextAction userOpHash and send it to Openfort.

Load session key and sign a transaction intent:


_10
await openfort.loadSessionKey()
_10
const sessionSignedTransaction = openfort.signMessage(
_10
collectResponseJSON.data.nextAction.payload.userOpHash
_10
)
_10
const openfortTransactionResponse =
_10
await openfort.sendSignatureTransactionIntentRequest(
_10
collectResponseJSON.data.id,
_10
sessionSignedTransaction
_10
)

5. Revoke a session key - Client side Server side#

The owner of the account can always revoke the session key.

To do so, it needs to sign the userOpHash from the nextAction object returned by the API call to revoke the session key.

Create a transaction intent:


_12
const playerId = 'pla_...'
_12
const policyId = 'pol_...'
_12
const chainId = 80001
_12
const sessionKeyAddress = '0x76e6...9341'
_12
_12
const revokeSession = await openfort.sessions.revoke({
_12
player: playerId,
_12
address: sessionKeyAddress,
_12
chainId: chainId,
_12
optimistic: true,
_12
policy: policyId,
_12
})

Sign the transaction to revoke the session key and remove from client side:


_10
const revokeResponseJSON = // Response from the server side request.
_10
const sessionSignedTransaction = // sign the userOpHash with the owner of the account
_10
const openfortTransactionResponse =
_10
await openfort.sendSignatureTransactionIntentRequest(
_10
revokeResponseJSON.data.id,
_10
sessionSignedTransaction
_10
);
_10
openfort.removeSessionKey();

6. Conclusion#

We now have a fully working implementation that allows us to perform actions with self-custodial accounts without any pop-ups or browser extensions.

For more information about how to use the sesion key endpoints, you can visit our API documentation.

Check out our working working examples of this quickstart:

  • Sample registering a session key with an account with a self-custodied signer: GitHub source.