Can not verify signature for commit...not a valid verificationMethod for issuer

Just FYI, if you are trying to give multiple users access to publish data to the same stream, make sure you understand the implications of the Late Publishing Attack on the security properties of your system: Consensus | Ceramic documentation


Hi @mpatel31, sorry you’re still having trouble with this.

I haven’t been keeping up with the latest state of our samples :face_with_peeking_eye: so I’m tagging @Justina and @mzk here.

Justina or Mark, would either of you be able to point @mpatel31 to sample code for delegating permissions from one did:key to another?

1 Like

Hi @mpatel31

There’s a few repos and guides that walk through did authorization and key delegation.

For example, our walletconnect tutorial is a recent one we published. You can look at the section that starts with Integrating ComposeDB with Our Application - this is where I discuss how the application can be contextually wrapped and allow sub-components the ability to access the authorized session

1 Like

Thanks @mzk!!

@mpatel31 please note that this example and others will be for using the did-session library to delegate permissions from a did:pkh (generated from a wallet address) to a did-key.

That is the typical way for delegating permissions in Ceramic.

1 Like

After taking a look at this and some other documents, I have seen people mention “TileDocuments” is that relevant in this conversation? Or is that something that I won’t need to use? I haven’t seen it used in examples, but it sounds like something I should be doing/using.

TileDocument used to be the main way data was stored on Ceramic, but it’s been replaced with the newer Model and ModelInstanceDocument streamtypes which are used by ComposeDB. TileDocument is deprecated and will be removed entirely in an upcoming version of Ceramic. See IMPORTANT: We are deprecating IDX suite:, glaze, DID DataStore, 3ID, 3id-datastore, TileDocuments and Caip10Link for more details


I am so sorry for still not having this figured out.

I decided to restart my project and start from scratch. I am trying to use Ethereum. I am at the part of User Sessions. I have never used Ethereum and am super unfamiliar with how to get the ‘web3 eth provider.’ Is there any recommendation for where I should look on how to retrieve the provider? I created a MetaMask account, have created a API endpoint, but I get this error each time:

(node:91233) ExperimentalWarning: Importing JSON modules is an experimental feature and might change at any time
(Use `node --trace-warnings ...` to show where the warning was created)
response: { data: [Object: null prototype] { viewer: null } }
const addresses = await ethProvider.request({ method: "eth_requestAccounts" });

TypeError: ethProvider.request is not a function
    at file:///Users/mitpatel/Development/backend-ceramic/backend-ceramic/ethereumWallet.mjs:10:37

Node.js v21.5.0

This is the provider I use:

const ethProvider = ethers.getDefaultProvider(

The rest of the code is the same block shown on the User Session Documents.


This is the update on where I am, I have run into a different error. I created a front end that allows me to get the provider through ethers:

export function useTest() {
  const { provider, userAddress } = useEthereum();
  const [sessionDid, setSessionDid] = useState("");

  useEffect(() => {
    async function establishSession() {
      if (!provider || !userAddress) return;

      try {
        const authMethod = await EthereumWebAuth.getAuthMethod(

        const session = await DIDSession.get(userAddress, authMethod, {
          resources: compose.resources,

        const sessionDid = compose.setDID(session.did);

      } catch (error) {
        console.error("Failed to establish session:", error);
  }, [provider, userAddress]);

  return sessionDid;

I store the provider and userAddress in Context that is created:

const EthereumContext = createContext();

export const useEthereum = () => useContext(EthereumContext);

export const EthereumProvider = ({ children }) => {
  const [provider, setProvider] = useState(null);
  const [userAddress, setUserAddress] = useState("");

  return (
      value={{ provider, setProvider, userAddress, setUserAddress }}

I’m getting the userAddress and the provider when the user logs into their Ethereum Account through MetaMask. This is the code for that:

const ConnectWalletButton = () => {
  const { setProvider, setUserAddress, userAddress } = useEthereum();

  const connectWalletHandler = async () => {
    if (window.ethereum) {
      try {
        await window.ethereum.request({
          method: "wallet_requestPermissions",
          params: [{ eth_accounts: {} }],
        const accounts = await window.ethereum.request({
          method: "eth_requestAccounts",
        const account = ethers.getAddress(accounts[0]);
        await setUserAddress(account);
        const provider = new ethers.BrowserProvider(window.ethereum, "any");
        await setProvider(provider);

I am running into this error that I have not been able to figure out. The documentation does not help me with this error. I think I need to start with the accountId but I’m not sure.

ethereumWallet.mjs:35 Failed to establish session: TypeError: Cannot read properties of undefined (reading 'toLowerCase')
    at normalizeAccountId (utils.js:43:1)
    at createCACAO (authmethod.js:47:1)
    at authmethod.js:22:1
    at DIDSession.get (index.js:283:1)
    at async establishSession (ethereumWallet.mjs:27:1)
establishSession	@	ethereumWallet.mjs:35
await in establishSession (async)		
(anonymous)	@	ethereumWallet.mjs:41```

I have figure this part out on my own, closing the ticket