This server acts as middleware between web applications built using the Verida Datastore and the underlying databases storing user data.
Key features:
- Ensuring all API requests come from verified Verida network users (via user signed messages)
- Managing database users, linking them to valid DID's
- Managing permissions for individual databases
- Adding a second layer of security by managing per-database ACL validation rules
- Providing applications with user's database connection strings
This is the login flow:
- The Verida Account makes a request to the storage node API to obtain an auth JWT to be signed (
/auth/generateAuthJwt
). This prevents replay attacks. - The Verida Account signs a consent message using their private key. This consent message proves the user wants to unlock a specific application context
- The Verida Account submits the signed authorization request (
/auth/authenticate
). Assuming the signed AuthJWT is valid, the storage node returns a refresh token and an access token - The Verida Account can then use the access token to either; 1) make storage node requests (ie: create database) or 2) directly access CouchDB as an authenticated user (using
Bearer
token auth) - When the access token expires, the Verida Account can use the refresh token to request a new access token (
/auth/connect
) - If a refresh token is close to expiry, the Verida Account can use the active refresh token to obtain a new refresh token (
/auth/regenerateRefreshToken
)
When a Verida Account authenticates, it can designate an authenticate
requst to be linked to a particular device by specifying the deviceId
in the request.
This allows a specific device to be linked to a refresh token. A call to /auth/invalidateDeviceId
can be used to invalidate any refresh tokens linked to the specified deviceId
. This allows the Verida Vault to remotely log out an application that previously logged in.
Note: This only invalidates the refresh token. The access token will remain valid until it expires. It's for this reason that access tokens are configured to have a short expiry (5 minutes by default). CouchDB does not support manually invalidating access tokens, so we have to take this timeout approach to invalidation.
yarn install
yarn build
yarn serve
Note: You may need to update .env
to point to the appropriate Verida DID Server endpoint to use. By default it points to testnet
, but you can point to a localhost instance for development purposes (http://localhost:5001) -- note, there is no trailing /
This server is running on the Verida Testnet and is accessible by any application built on the Verida network during the pre-launch phase.
A sample.env
is included. Copy this to .env
and update the configuration:
DID_SERVER_URL
: URL of a Verida DID Server endpoint.DB_PROTOCOL
: Protocol to use when connecting to CouchDB (http
orhttps
).DB_USER
: Username of CouchDB Admin (has access to create users and databases).DB_PASS
: Password of CouchDB Admin.DB_HOST
: Hostname of CouchDB Admin.DB_PORT
: Port of CouchDB server (5984
).DB_REJECT_UNAUTHORIZED_SSL
: Boolean indicating if unauthorized SSL certificates should be rejected (true
orfalse
). Defaults tofalse
for development testing. Must betrue
for production environments otherwise SSL certificates won't be verified.DB_PUBLIC_USER
: Alphanumeric string for a public database user. These credentials can be requested by anyone and provide access to all databases where the permissions have been set topublic
.DB_PUBLIC_PASS
: Alphanumeric string for a public database password.ACCESS_TOKEN_EXPIRY
: Number of seconds before an access token expires. The protocol will use the refresh token to obtain a new access token. CouchDB does not support a way to force the expiry of an issued token, so the access token expiry should always be set to 5 minutes (300)REFRESH_TOKEN_EXPIRY
: Number of seconds before a refresh token expires. Users will be forced to re-login once this time limit is reached. This should be set to 7 days (604800).ACCESS_JWT_SIGN_PK
: The access token private key. The base64 version of this must be specified in the CouchDB configuration underjwt_keys/hmac:_default
REFRESH_JWT_SIGN_PK
: The refresh token private key
- On a powershell execute the following ( replica of
.env
)
$env:DID_SERVER_URL="https://dids.testnet.verida.io:5001"
$env:DID_CACHE_DURATION=3600
$env:DB_PROTOCOL="http"
$env:DB_USER="admin"
$env:DB_PASS="admin"
$env:DB_HOST="localhost"
$env:DB_PORT=5984
$env:DB_REJECT_UNAUTHORIZED_SSL=false
$env:DB_PUBLIC_USER="784c2n780c9cn0789"
$env:DB_PUBLIC_PASS="784c2n780c9cn0789"
- CORS must be enabled so that database requests can come from any domain name
- A valid user must be enforced for security reasons
[couchdb]
single_node=true
[chttpd]
authentication_handlers = {chttpd_auth, jwt_authentication_handler}, {chttpd_auth, cookie_authentication_handler}, {chttpd_auth, default_authentication_handler}
enable_cors = true
[chttpd_auth]
require_valid_user = true
[jwt_auth]
required_claims = exp
[jwt_keys]
hmac:_default = <base64 secret key>
[cors]
origins = *
credentials = true
methods = GET, PUT, POST, HEAD, DELETE
headers = accept, authorization, content-type, origin, referer, x-csrf-token
The hmac:_default
key is a base64 encoded representation of the access token JWT private key
Note: A secret key (string) suitable for jwt_keys
can be base64 encoded with the following:
const secretKey = 'secretKey'
const encodedKey = Buffer.from(secretKey).toString('base64')
This can be tested via curl:
curl -H "Host: localhost:5984" \
-H "accept: application/json, text/plain, */*" \
-H "authorization: Bearer <bearer_token>" \
"http://localhost:5984/_session"
Where:
bearer_token
- A bearer token generated via thetest/jwt
unit testlocalhost
- Replace this with the hostname of the server being tested
You can spin up storage node API on your machine with Docker:
docker run --init --env-file=.env verida/storage-node:latest
Note that this uses the experimental buildx
command to build both AMD64 (Intel/AMD servers) and ARM64 (Mac) images.
- Login (details in BitWarden)
docker buildx build --platform linux/amd64,linux/arm64 --push -t verida/storage-node:latest .
Run tests with yarn run tests
Common issues when running tests:
Bad key
: The key in CouchDB configuration forjwt_keys/hmac:_default
is not a valid Base64 encoded keyHMAC error
: The key in CouchDB configuration forjwt_keys/hmac:_default
does not matchACCESS_JWT_SIGN_PK
in.env
To test a deployed node, do the following
- Modify
tests/config.js
with the correct endpoint URLs - Run
yarn test tests/server.js