TinyCloud uses two distinct types of Decentralized Identifiers (DIDs) for different purposes. Understanding when to use each is critical for successful delegations and correct identity handling.
The Two DID Types
Session Key DID
The Session Key DID is an ephemeral identifier generated fresh for each session. It uses the did:key method:
did:key:z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK#z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK
This DID represents the cryptographic key that signs requests to the TinyCloud server during a single session. It is rotated on each authentication and should never be used for persistent identity.
Access it via .sessionDid:
const sessionDid = tc.sessionDid;
// Returns: did:key:z6Mk...#z6Mk...
Primary DID (User Identity)
The Primary DID represents the user’s persistent identity, derived from the authentication method they used. For Ethereum wallets, this is a did:pkh (Public Key Hash) DID:
did:pkh:eip155:1:0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045
This DID remains constant as long as the user uses the same wallet address. It is the correct identifier for user-to-user relationships and delegations.
The .did Property
The tc.did property returns different values depending on the authentication state:
After signIn()
Before signIn()
After calling signIn(), tc.did returns the primary DID (persistent identity):await tc.signIn();
console.log(tc.did);
// did:pkh:eip155:1:0xd8dA...6045 (primary DID)
console.log(tc.sessionDid);
// did:key:z6Mk...#z6Mk... (session key DID)
In this mode, tc.did and tc.sessionDid return different values. Use tc.did for delegations and identity, and tc.sessionDid for debugging session internals. Before signIn (or in session-only mode with no wallet), tc.did returns the session key DID:// Before signIn or in session-only mode
console.log(tc.did);
// did:key:z6Mk...#z6Mk...
console.log(tc.sessionDid);
// did:key:z6Mk...#z6Mk... (same value)
In this mode, both getters return the same value because there is no authenticated identity available yet.
When to Use Which
| Use Case | What to Use | Returns |
|---|
| User-to-user delegations | tc.did | Primary DID (after signIn) |
| Identifying a user persistently | tc.did | Primary DID (after signIn) |
| Debugging session key issues | tc.sessionDid | Session Key DID |
| Logging internal session state | tc.sessionDid | Session Key DID |
After signIn(), use tc.did for delegations. It returns the primary DID, which is what the server expects. Use tc.sessionDid only when you need to inspect the ephemeral session key for debugging.
The Common Mistake
When Alice wants to delegate capabilities to Bob, developers sometimes use the session DID directly instead of the primary identity:
// WRONG - using sessionDid for delegations will fail server validation
await alice.createDelegation({
delegateDID: bob.sessionDid, // Session key DID - ephemeral!
abilities: ["tinycloud.kv/get", "tinycloud.kv/put"]
});
// Error: "Delegation failed: invalid delegatee"
The correct approach:
// CORRECT - use tc.did (which returns primary DID after signIn)
await alice.createDelegation({
delegateDID: bob.did, // Primary DID after signIn
abilities: ["tinycloud.kv/get", "tinycloud.kv/put"]
});
This is the #1 pitfall in TinyCloud SDK usage.After signIn, the .did property returns your primary DID. This is the DID others should use when creating delegations to you. A delegation targeting a session key DID will always fail because:
- The server expects the primary DID format for the delegatee field
- Session DIDs are ephemeral and rotate on each authentication
- A delegation to Bob’s session DID becomes invalid the moment Bob re-authenticates
Why This Matters
The TinyCloud server performs strict validation on delegation chains:
- Delegatee matching: When Bob uses a delegation from Alice, the server checks that the
delegatee field in Alice’s delegation matches Bob’s identity
- Primary DID expected: The server expects the delegatee to be the primary DID (e.g.,
did:pkh:eip155:... for Ethereum wallets)
- Session DIDs are ephemeral: Bob’s session DID changes with each authentication, so a delegation to
bob.sessionDid would be invalid after Bob re-authenticates
The primary DID remains constant as long as Bob uses the same authentication method (e.g., same wallet address), making it the correct identifier for persistent user-to-user relationships.
Quick Reference
// After signIn():
console.log("User identity (for delegations):", tc.did);
// -> did:pkh:eip155:1:0xabc... (primary DID)
console.log("Session key (for debugging):", tc.sessionDid);
// -> did:key:z6Mk...#z6Mk...
// Summary:
// tc.did = Primary DID after signIn, session DID before signIn
// tc.sessionDid = Always session key DID
If you see the error “Delegation failed: invalid delegatee”, verify that you are using tc.did (after signIn()) rather than tc.sessionDid when specifying the delegate.