Overview
Guide on integrating with the DeSo Identity Window API
Last updated
Guide on integrating with the DeSo Identity Window API
Last updated
In this guide, we will explain how to integrate the DeSo Identity window API into your application.
When developing applications that handle user authentication, there are always some actions that require user interaction.
In traditional Web2 applications, this often involves the user having to type information such as username and password, or the user clicking on a third-party login such as Google or Apple.
On the other hand, decentralized Web3 applications are powered by blockchains and consequently, they rely on public and private keys.
The underlying mathematics of blockchains can often appear complicated, both for the user and for the developer.
To solve these issues, we designed the DeSo Identity Service which hides the cryptographic complexities of user authentication underneath a simple window API.
With DeSo Identity Service you don't need to worry about implementing any HTML forms or input validation, you just need to make correct calls to the window API.
The window API is responsible for opening Identity either as a pop-up window or as a new tab. Opening Identity in a window context is as simple as launching a window.open
.
Here are examples of some calls that can be made to Identity:
And here's an example user interface after launching the log-in
endpoint with a couple of URL parameters, in this case, accessLevelRequest=4
You might remember the accessLevelRequest
URL parameter from the section in our Introduction guide.
There are other URL parameters that you can use and we will explain them in this document.
Once the window context is launched, the user has to perform an action, such as login or signup.
After the user completes the flow, your app will receive either a postMessage
or a callback
containing secure user credentials and payload of the desired API endpoint.
You can then use the user credentials for communicating with the Identity: iFrame API. We recommend the following format for opening the Identity window context:
When we pass the public key to the Identity window API, it should always be in base58check format:
Note: Only one Identity window should be opened at a time.
Normally, the DeSo Identity Service will communicate with your application via postMessage
.
In order to listen to these messages, you have to declare an event handler in the parent window context, as shown below.
The first message sent by Identity is method: "initialize"
, and your application has to send a response.
When the user completes an action within the window context, Identity will send a postMessage
to your application containing the payload corresponding to the launched endpoint.
Messages sent by the window API will also include an id: null
field, which indicates that they do not require a response from your application.
Below is an example event.data
response from the log-in
endpoint.
Most responses from the window context will have the same structure as above.
A typical response will contain the users
object, which reflects all users that have previously logged in to your application.
The users
object is a map of publicKey => userCredentials
where the credentials are used primarily for communicating with the iframe
context.
In such requests, we will be passing the encryptedSeedHex, accessLevel, accessLevelHmac
which are used by DeSo Identity to ensure that the user has been securely authenticated via the window context.
User credentials should be saved in local storage.
You should always overwrite existing credentials whenever you receive a method: "login"
response.
This is because some requests can cause Identity to reauthorize all users and their credentials like encryptedSeedHex
will change.
In the DeSo Protocol implementation, we do this via this.backend.setIdentityServiceUsers()
on line #857 in /src/app/global-vars.service.ts
which uses the localStorage
API to store data.
If you're unfamiliar with localStorage
, below are the three main API calls you'll need.
In the reference implementation, we simply store the entire payload.users
field under a single key called IdentityUsersKey = "identityUsersV2"
Apart from the users
field, the response will contain fields that are specific to the requested API endpoint.
When we called the log-in
endpoint, the response also contained publicKeyAdded
of the logged user and signedUp
indicating that the user has signed up.
If you're building a mobile application, you most likely want to be using callbacks instead of messages.
Launching the window context with a callback
URL causes the Identity window to send the payload via URL parameters rather than a postMessage
.
The callback mechanism works similarly to how OAuth is typically implemented in mobile apps.
Because responses to these endpoints contain sensitive user information, the provided callback
URL should always be a local address.
Below is an example call to the derive
endpoint with a auth://derive
callback URL:
After user finishes the Identity flow the payload will be sent via URL parameters as a GET request to the provided callback like this:
When a user finishes any action in an Identity window, a method: "login"
message is sent or a callback
is called.
After you receive the payload from your desired API endpoint, you should close the Identity window by calling window.close()
on the window object.
When the Identity window is open, you can also communicate with it just like you would with the iframe
API. This is sometimes useful if you want to sign a transaction or generate a JWT.
We explained this mechanism in more detail in our and guides.
These messages will usually contain a method: "login"
field so that it's easier to handle closing the identity window as described in the section.
However, some endpoints will contain a different method, such as the endpoint.
More information on these fields can be found in the section.
Callbacks are intended to be used in combination with derived keys so they currently work for and endpoints.
Where the param1=value1
, param2=value2
fields will match the structure of the response payload of to the /derive
endpoint as explained in the section.