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
procedures. For executing view
procedures, the same general access control rules are available as for write procedures. 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.
Setting view procedure 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 a procedure requires authentication, add an annotation before the procedure. The @kgw(authn='true')
annotation will require the user to authenticate via a signature before executing the procedure.
// authentication required view procedure to reveal a user profile
@kgw(authn='true')
procedure get_profile () public view returns table(id int, username text, age int) {
return SELECT id, username, age
FROM users
WHERE address = @caller;
}
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.
When multiple users are authenticated, the current user is the signer passed to the call
method.
- Browser
- NodeJs
import { WebKwil, KwilSigner } from '@kwilteam/kwil-js';
import { BrowserProvider } from 'ethers';
const kwil = new WebKwil({
kwilProvider: "https://longhorn.kwil.com",
chainId: "longhorn-2",
});
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 authenticatedProcedure() {
const kwilSigner = await getSigner();
const payload = {
name: "get_profile",
dbid: 'x123abc...'
}
return await kwil.call(payload, kwilSigner); // user will be prompted to authenticate
}
import { NodeKwil } from '@kwilteam/kwil-js';
const kwil = new NodeKwil({
kwilProvider: "https://longhorn.kwil.com",
chainId: "longhorn-2",
});
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 authenticatedProcedure() {
const kwilSigner = await getSigner();
const payload = {
name: "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 procedures that require authentication.
Log out all signers
To log out all signers that a user has authenticated with, call the logout
method with no arguments.
async function logout() {
await kwil.auth.logout();
}
Log out a specific signer
To log out a specific signer, 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 a procedure that requires authentication. To disable this behavior, set the autoAuthenticate
option to false
.
const kwil = new WebKwil({
kwilProvider: "https://longhorn.kwil.com",
chainId: "longhorn-2",
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);
}
NodeJS: Manually Pass Cookie
In NodeJS, you can optionally set the cookie manually. This is useful when you want to implement additional logic around the authentication process.
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 authenticatedProcedure() {
const auth = await kwil.auth.authenticate(kwilSigner);
const cookie = auth.data?.cookie;
const payload = {
name: "get_profile",
dbid: 'x123abc...',
cookie
}
return await kwil.call(payload); // user will not be prompted to authenticate
}