Skip to content

Adopt alsoKnownAs for identity verification via DID documents #2

@ngerakines

Description

@ngerakines

If Keytrace's goal is being "keybase on atproto", then it should use and incorporate the existing alsoKnownAs field of DID documents.

In addition to storing identity proofs as records in a user's repository, keytrace could use the alsoKnownAs field that's already part of every DID document. The W3C DID Core spec (§5.1.1) defines alsoKnownAs as an ordered set of URIs by which the DID subject can also be identified. Notably, these can be any valid URI, not just at:// handles, but also HTTPS URLs, other DIDs, dns: identifiers, etc.

Example

For example, my DID document has several entries. I have my primary handle "ngerakines.me" as well as the handles "nick.gerakines.net" and "nick.thegem.city". All three can be used to reference me in posts on the Bluesky AppView and all three formally resolve with _atproto DNS records. Then I reference my GitHub account, website, and domain.

The DID document for did:plc:cbkjy5n7bk3ax2wplmtjofq2 contains:

{
  "@context": [ ... ],
  "alsoKnownAs": [
    "at://ngerakines.me",
    "at://nick.gerakines.net",
    "at://nick.thegem.city",
    "https://github.com/ngerakines",
    "https://ngerakines.me/",
    "dns:ngerakines.me"
  ],
  "id": "did:plc:cbkjy5n7bk3ax2wplmtjofq2",
  "service": [ ... ],
  "verificationMethod": [ ... ]
}

Per the DID Core spec, each value in alsoKnownAs is a URI (RFC 3986) that identifies the same subject as the DID. Breaking down each entry:

  • at://ngerakines.meat scheme. Asserts this DID is the ATProto identity behind the handle ngerakines.me. Verified through ATProtocol handle resolution with the resolved DID string matching the document's "id" field. The Bluesky AppView uses the first as the "primary" handle for display purposes.

  • at://nick.gerakines.netat scheme. Same DID, additional ATProto handle. Same handle resolution check for nick.gerakines.net.

  • at://nick.thegem.cityat scheme. Same DID, additional ATProto handle. Same handle resolution check for nick.thegem.city.

  • https://github.com/ngerakineshttps scheme. Asserts this DID subject controls the GitHub account ngerakines. Verified via GitHub's social identities API, which exposes linked Bluesky handles that can be resolved back to the DID.

    $ curl -L \
      -H "Accept: application/vnd.github+json" \
      -H "X-GitHub-Api-Version: 2022-11-28" \
      https://api.github.com/users/ngerakines/social_accounts
    [
      {
        "provider": "bluesky",
        "url": "https://bsky.app/profile/ngerakines.me"
      }
    ]
  • https://ngerakines.me/https scheme. Asserts this DID subject controls the website at ngerakines.me. Verified by checking for a <link rel="did" href="did:plc:cbkjy5n7bk3ax2wplmtjofq2"> element in the page HTML. the rel="did" value is technically invalid and should probably be rel="alternative me" and reference an AT-URI of just the authority like "did:plc:cbkjy5n7bk3ax2wplmtjofq2".

    $ curl --silent https://ngerakines.me/ | htmlq 'link'
    ...
    <link href="did:plc:cbkjy5n7bk3ax2wplmtjofq2" rel="did">
  • dns:ngerakines.medns scheme. Asserts this DID subject controls the DNS zone for ngerakines.me. Verified by checking for a TXT record on the domain that references the DID.

Prior art: WeatherVane

The WeatherVane project (verify.aviary.domains) was an early experiment exploring this approach. It performs bi-directional verification of identities listed in alsoKnownAs, checking that the DID document points to an external identity and that the external identity points back to the DID. You can see it in action for the example above at verify.aviary.domains/did/did:plc:cbkjy5n7bk3ax2wplmtjofq2.

Lessons Learned

My personal opinion is that implementing everything at the DID document layer makes it prohibitive for most users. I generally don't recommend that people manually configure their DID document because it's risk, even with good tooling. Having an on-protocol record-based system like what you're doing with keytrace.dev makes a lot of sense and lowers the bar, making it a much more effective approach to creating cross-identity verification and links.

That said, I don't think the "alsoKnownAs" field should be discounted, especially for services and high-profile accounts. For service accounts that don't have repositories, like did:web:api.bsky.app, having an alsoKnownAs entry to the primary domain can convey ownership and direct association. It also reduces the number of hops necessary for tooling to perform verification.

  • Identity links are available immediately during DID resolution, without needing to fetch repo data or hit an AppView
  • It's protocol-nativealsoKnownAs is part of the DID Core spec and already supported by did:plc and did:web
  • It's decentralized by design — no labeler or third-party service needed to verify claims, anyone can resolve and check
  • It composes well — the same mechanism works across the broader DID ecosystem, not just ATProtocol

The "Extending Also Known As" blog post explores how the ATMosphere could adopt multiple alsoKnownAs entries beyond just the primary handle, which would further expand keytrace's ability to surface verified identities.

What this could look like for keytrace

Keytrace could adopt a layered approach:

  1. Read alsoKnownAs from the DID document as a primary source of linked identities
  2. Perform bi-directional verification for each URI (similar to WeatherVane's approach)
  3. Use keytrace-specific lexicon records for richer metadata, attestations, or identity types that don't fit neatly into a URI (this is where keytrace's own schemas add value beyond what alsoKnownAs alone provides)

This gives users verified identity links "for free" at the DID layer, while keytrace's own records can layer on additional context, presentation, and proof types.

References

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions