Skip to main content

Read Access Control

In this tutorial, we will cover how to authenticate a user to enforce read access control. This tutorial expands on the schema created in the Write Access Control tutorial.

In Kwil, data is primarily read with view actions. For executing view actions, the same general access control rules are available as for write actions. However, because data stored on nodes are default public, Kwil networks running in permissioned or federated environments can use the Kwil Gateway to enforce user authentication and stronger read access control.

tip

Setting view action privacy is done using the Kwil Gateway. The gateway is still in private beta. If you would like access, please contact our team.

Overview

The Kwil Gateway requires a user to sign a message with their account keys. Once the signature is verified, the gateway will return the user a cookie to be passed with all subsequent requests.

KGW cookies are partitioned by origin. This means that multiple users can be authenticated at the same time, and users authenticated from one origin (e.g., https://website1.com) will not be authenticated on another origin (e.g., https://website2.com).

Require Authentication in Kuneiform

To signal to the Kwil Gateway that an action requires authentication, add an annotation before the action. The @kgw(authn='true') annotation will require the user to authenticate via a signature before executing the action.

social_media.kf
// authentication required view action to reveal a user profile
@kgw(authn='true')
action get_profile () public view {
SELECT *
FROM users
WHERE address = @caller;
}
danger

The @kgw(authn='true') annotation will only require the user to authenticate IF the Kwil Gateway is enabled. If the gateway is not enabled, the annotation will be ignored.

Authenticating a User

Using the JavaScript SDK and the KwilSigner, a user can authenticate with the Kwil Gateway (KGW). When calling the call method, the Kwil SDK will check if the gateway is enforcing authentication. If authentication is enforced, the gateway will prompt the user to sign a message with their account keys. Once the signature is verified, the SDK will include a cookie to be passed with all subsequent requests.

tip

When multiple users are authenticated, the current user is the signer passed to the call method.

import { WebKwil, KwilSigner } from '@kwilteam/kwil-js';
import { BrowserProvider } from 'ethers';

const kwil = new WebKwil({
kwilProvider: "https://longhorn.kwil.com",
chainId: "longhorn",
});

async function getSigner() {
const provider = new BrowserProvider(window.ethereum);
const ethSigner = await provider.getSigner();
const ethAddress = await ethSigner.getAddress();
return new KwilSigner(ethSigner, ethAddress);
}

async function authenticatedAction() {
const kwilSigner = await getSigner();

const payload = {
action: "get_profile",
dbid: 'x123abc...'
}

return await kwil.call(payload, kwilSigner); // user will be prompted to authenticate
}

Logging Out a User

Logging out a user invalidates the cookie from the requesting origin. This means that the user will need to re-authenticate to access any actions that require authentication.

Log out all users

To logout all users, call the logout method with no arguments.

async function logout() {
await kwil.auth.logout();
}

Log out a specific user

To logout a specific user, pass the signer to the logout method.

async function logoutUser() {
const kwilSigner = await getSigner();
await kwil.auth.logout(kwilSigner);
}

Advanced Usage

Disable Auto Authentication

By default, the Kwil SDK will automatically prompt the user to authenticate when calling an action that requires authentication. To disable this behavior, set the autoAuthenticate option to false.

const kwil = new WebKwil({
kwilProvider: "https://longhorn.kwil.com",
chainId: "longhorn",
autoAuthenticate: false,
});

Manually Authenticate

To manually authenticate a user, call the authenticate method. Kwil-JS will automatically include the cookie with all subsequent requests.

async function manualAuthenticate() {
await kwil.auth.authenticate(kwilSigner);
}

In NodeJS, you can optionally set the cookie manually. This is useful when you want to implement additional logic around the authentication process.

note

You should not pass the cookie if in browser (WebKwil). The SDK relies on the browser's cookie jar to store the cookie.

async function authenticatedAction() {
const auth = await kwil.auth.authenticate(kwilSigner);

const cookie = auth.data?.cookie;

const payload = {
action: "get_profile",
dbid: 'x123abc...',
cookie
}

return await kwil.call(payload); // user will not be prompted to authenticate
}