Token-Based Access Control

The most common method for providing access to content for consumers at large is using non-fungible tokens (or variations - ERC721, ERC1155, ERC20).

For each content object storing the media that consumers will gain access to, set up the following:

  1. Set a contract-level policy for the content object contract, under the key _ELV (on-chain)
  2. Specify the list of NFTs in the content object contract, under the key _NFT_ACCESS (on-chain)

When a client app accesses the content object, it needs to present a client-signed access token (signed by the consumer wallet). Content fabric nodes will evaluate the permissions policy against the address of the signer (the consumer) and will grant access if the address holds at least one token of the contracts listed under _NFT_ACCESS

Grant NFT owners access to a content object

The common policy used for granting access to NFT owners is found here: nft_owner.yaml. Clone this repository to get a copy of the policy file https://github.com/eluv-io/elv-docs.

Using the elv-live-js tool:

export PRIVATE_KEY=... # key with edit access to the content object

./elv-live nft_set_policy_permissions iq__PN4QevDpfjBdnVWyTKgymy2y8rA  ./nft_owner.yaml 0xc21ea77699666e2bb6b96dd20157db08f22cbd3 0xc21ea77699666e2bb6b96dd20157db08f22cbc3 0xc21ea77699666e2bb6b96dd20157db08f22cbd4

To verify or simply read the permissions of a content object:

./elv-live nft_set_policy_permissions iq__PN4QevDpfjBdnVWyTKgymy2y8rA

Cross-Chain Tokens

If content consumers hold NFTs on external chains (such as Ethereum Mainnet, Polygon, …) the access control policy requires a ‘cross-chain message’ signed by a recognized authority (call the cross-chain oracle).

For each content object, set up the following:

  1. Set a contract-level policy specifying the list of external chains that eligible users will use
  2. Specify the list of NFTs for each external chain

The client app will first call the cross-chain oracle API and retrieve a ‘cross-chain oracle signed message’ (xco_msg), the construct a client-signed access token including the xco_msg in its context. With this token, the client app can access content resources and content fabric nodes will evaluate the permission policy against this access token and grant access if the consumer address holds at least one token of the contracts listed.

Sample client app code (node.js):

Sample client app code (browser):

Setting the cross-chain policy

Unlike the common_policies referenced above, which can be used as-is, cross-chain policies must be specialized to the particular NFTs being used for access control. This sample illustrates the format: nft_cross_chain.yml.

It has examples of token references for:

  • ethereum mainnet (eip155:1/)
  • polygon mainnet (eip155:137/)
  • eluvio mainnet (eip155:955305/)
  • solana mainnet (solana:4sGjMW1sUnHzSxGspuhpqLDx6wiyjNtZ/)
  • flow mainnet (flow:mainnet/)

in that order, under the section labelled authorizedAssets. The policy permits read operations if the user owns at least one of the tokens defined in the list.

These are formatted according to the CAIP naming convention.

As before, you use the elv-live-js tool to set these on a per-object basis. Note: only the owner of the object can set the policy.

export PRIVATE_KEY=... # key with edit access to the content object

./elv-live nft_set_policy_permissions iq__... ./nft_cross_chain.yaml

After calling this, you must then separately verify the policy was set correctly, as the set operation itself doesn’t provide direct feedback on the validity of the policy.

To do so, use the nft_get_policy_permissions command. Here is a useful pipeline to reformat the output into the original yaml:

export PRIVATE_KEY=... # key with edit access to the content object

./elv-live nft_get_policy_permissions iq__... 2>/dev/null | grep -v "NFT.Get" | grep -v Object | grep -v verbose | grep -v Network |  yq eval .policy | jq -r .auth_policy.body | yq .

A common mistake is to have a formatting error in the yaml file, making the set operation invalid. We suggest running your yaml through a tool such as yq, which will validate the yaml beforehand.

DApp Sample

Use DApp Sample to acquire an access token to use against the cross-chain policy.

We provide a sample browser client dapp that can be used to walk through this process, hosted at https://dapp-sample-xco.app.eluv.io/.

The source code for this is available at https://github.com/eluv-io/elv-dapp-sample/tree/main/test/cross-chain-media.

To operate, start with an existing example:

  1. Log into the content fabric, using either a MetaMask wallet or Eluvio-hosted wallet. (For the initial samples, use the demo network. For your own content, use main.)
  2. Choose a NFT contract address from the list of examples, and input it into the matching field at left
  3. Note how the matching videos play, or are inaccessible, based on you matching wallet contents

For example, obtain a (free) Starflix All-Access pass on our demo network, and use that ownership to light them all!

In these sample apps, requests appear in the black highlighted section labelled Input and responses appear in the black highlighted section labelled Output.

The token balance appears as

{
  ...
  "results": { "balance": 1, "block_number": 181731034 }
}

and the token itself, which can be used to access the gated content, appears as

{ 
  ...
  "token": "acspjc..."
}

Putting it all together, now create an embedded token-gated video player using your own policy and content:

  1. Be sure you’ve constructed a policy via the Setting the cross-chain policy instructions above
  2. Enter your contract address into the matching field, and do an oracle query.
  3. Take the token from the Output section – making sure the balance is greater than one – and input it into the field labelled Gated content access token
  4. Input your matching content object ID with the policy set into the field labelled Gated content version hash
  5. Press the Embed Content button.

This will show the content as a working embed – the same thing being done in the six window panes at the top, just for your arbitrary token and object.

For additional details, please see the README for the dapp sample, which includes the list of blockchain controlling assets used in the examples.