Documentation
¶
Overview ¶
Package identity provides types and routines for resolving handles and DIDs from the network
The two main abstractions are a Directory interface for identity service implementations, and an Identity struct which represents core identity information relevant to atproto. The Directory interface can be nested, somewhat like HTTP middleware, to provide caching, observability, or other bespoke needs in more complex systems.
Index ¶
- Variables
- type BaseDirectory
- func (d *BaseDirectory) Lookup(ctx context.Context, a syntax.AtIdentifier) (*Identity, error)
- func (d *BaseDirectory) LookupDID(ctx context.Context, did syntax.DID) (*Identity, error)
- func (d *BaseDirectory) LookupHandle(ctx context.Context, h syntax.Handle) (*Identity, error)
- func (d *BaseDirectory) Purge(ctx context.Context, atid syntax.AtIdentifier) error
- func (d *BaseDirectory) ResolveDID(ctx context.Context, did syntax.DID) (*DIDDocument, error)
- func (d *BaseDirectory) ResolveDIDRaw(ctx context.Context, did syntax.DID) (json.RawMessage, error)
- func (d *BaseDirectory) ResolveHandle(ctx context.Context, handle syntax.Handle) (syntax.DID, error)
- func (d *BaseDirectory) ResolveHandleDNS(ctx context.Context, handle syntax.Handle) (syntax.DID, error)
- func (d *BaseDirectory) ResolveHandleDNSAuthoritative(ctx context.Context, handle syntax.Handle) (syntax.DID, error)
- func (d *BaseDirectory) ResolveHandleDNSFallback(ctx context.Context, handle syntax.Handle) (syntax.DID, error)
- func (d *BaseDirectory) ResolveHandleWellKnown(ctx context.Context, handle syntax.Handle) (syntax.DID, error)
- func (d *BaseDirectory) ResolveNSID(ctx context.Context, nsid syntax.NSID) (syntax.DID, error)
- type CacheDirectory
- func (d *CacheDirectory) Lookup(ctx context.Context, a syntax.AtIdentifier) (*Identity, error)
- func (d *CacheDirectory) LookupDID(ctx context.Context, did syntax.DID) (*Identity, error)
- func (d *CacheDirectory) LookupDIDWithCacheState(ctx context.Context, did syntax.DID) (*Identity, bool, error)
- func (d *CacheDirectory) LookupHandle(ctx context.Context, h syntax.Handle) (*Identity, error)
- func (d *CacheDirectory) LookupHandleWithCacheState(ctx context.Context, h syntax.Handle) (*Identity, bool, error)
- func (d *CacheDirectory) Purge(ctx context.Context, atid syntax.AtIdentifier) error
- func (d *CacheDirectory) ResolveHandle(ctx context.Context, h syntax.Handle) (syntax.DID, error)
- type DIDDocument
- type Directory
- type DocService
- type DocVerificationMethod
- type Identity
- func (ident *Identity) DIDDocument() DIDDocument
- func (i *Identity) DeclaredHandle() (syntax.Handle, error)
- func (i *Identity) GetPublicKey(id string) (atcrypto.PublicKey, error)
- func (i *Identity) GetServiceEndpoint(id string) string
- func (i *Identity) PDSEndpoint() string
- func (i *Identity) PublicKey() (atcrypto.PublicKey, error)
- type MockDirectory
- func (d *MockDirectory) Insert(ident Identity)
- func (d *MockDirectory) Lookup(ctx context.Context, a syntax.AtIdentifier) (*Identity, error)
- func (d *MockDirectory) LookupDID(ctx context.Context, did syntax.DID) (*Identity, error)
- func (d *MockDirectory) LookupHandle(ctx context.Context, h syntax.Handle) (*Identity, error)
- func (d *MockDirectory) Purge(ctx context.Context, a syntax.AtIdentifier) error
- func (d *MockDirectory) ResolveDID(ctx context.Context, did syntax.DID) (*DIDDocument, error)
- func (d *MockDirectory) ResolveDIDRaw(ctx context.Context, did syntax.DID) (json.RawMessage, error)
- func (d *MockDirectory) ResolveHandle(ctx context.Context, h syntax.Handle) (syntax.DID, error)
- type Resolver
- type ServiceEndpoint
- type VerificationMethod
Constants ¶
This section is empty.
Variables ¶
var ( ErrNSIDResolutionFailed = fmt.Errorf("NSID resolution mechanism failed") ErrNSIDNotFound = fmt.Errorf("NSID not associated with a DID") )
var DefaultPLCURL = "https://plc.directory"
var ErrDIDNotFound = errors.New("DID not found")
Indicates that resolution process completed successfully, but the DID does not exist.
var ErrDIDResolutionFailed = errors.New("DID resolution failed")
Indicates that DID resolution process failed. A wrapped error may provide more context.
var ErrHandleMismatch = errors.New("handle/DID mismatch")
Indicates that resolution process completed successfully, handle mapped to a different DID. This is only returned when looking up a handle, not when looking up a DID.
var ErrHandleNotDeclared = errors.New("DID document did not declare a handle")
Indicates that DID document did not include any handle ("alsoKnownAs"). This is only returned when looking up a handle, not when looking up a DID.
var ErrHandleNotFound = errors.New("handle not found")
Indicates that resolution process completed successfully, but handle does not exist. This is only returned when looking up a handle, not when looking up a DID.
var ErrHandleReservedTLD = errors.New("handle top-level domain is disallowed")
Handle top-level domain (TLD) is one of the special "Reserved" suffixes, and not allowed for atproto use
var ErrHandleResolutionFailed = errors.New("handle resolution failed")
Indicates that handle resolution failed. A wrapped error may provide more context. This is only returned when looking up a handle, not when looking up a DID.
var ErrInvalidHandle = errors.New("invalid handle")
Handle was invalid, in a situation where a valid handle is required.
var ErrKeyNotDeclared = errors.New("DID document did not declare a relevant public key")
Indicates that DID document did not include a public key with the specified ID
Functions ¶
This section is empty.
Types ¶
type BaseDirectory ¶
type BaseDirectory struct {
// if non-empty, this string should have URL method, hostname, and optional port; it should not have a path or trailing slash
PLCURL string
// If not nil, this limiter will be used to rate-limit requests to the PLCURL
PLCLimiter *rate.Limiter
// If not nil, this function will be called inline with DID Web lookups, and can be used to limit the number of requests to a given hostname
DIDWebLimitFunc func(ctx context.Context, hostname string) error
// HTTP client used for did:web, did:plc, and HTTP (well-known) handle resolution
HTTPClient http.Client
// DNS resolver used for DNS handle resolution. Calling code can use a custom Dialer to query against a specific DNS server, or re-implement the interface for even more control over the resolution process
Resolver net.Resolver
// when doing DNS handle resolution, should this resolver attempt re-try against an authoritative nameserver if the first TXT lookup fails?
TryAuthoritativeDNS bool
// set of handle domain suffixes for for which DNS handle resolution will be skipped
SkipDNSDomainSuffixes []string
// set of fallback DNS servers (eg, domain registrars) to try as a fallback. each entry should be "ip:port", eg "8.8.8.8:53"
FallbackDNSServers []string
// skips bi-directional verification of handles when doing DID lookups (eg, `LookupDID`). Does not impact direct resolution (`ResolveHandle`) or handle-specific lookup (`LookupHandle`).
//
// The intended use-case for this flag is as an optimization for services which do not care about handles, but still want to use the `Directory` interface (instead of `ResolveDID`). For example, relay implementations, or services validating inter-service auth requests.
SkipHandleVerification bool
// User-Agent header for HTTP requests. Optional (ignored if empty string).
UserAgent string
}
The zero value ('BaseDirectory{}') is a usable Directory.
func (*BaseDirectory) Lookup ¶
func (d *BaseDirectory) Lookup(ctx context.Context, a syntax.AtIdentifier) (*Identity, error)
func (*BaseDirectory) LookupHandle ¶
func (*BaseDirectory) Purge ¶
func (d *BaseDirectory) Purge(ctx context.Context, atid syntax.AtIdentifier) error
func (*BaseDirectory) ResolveDID ¶
func (d *BaseDirectory) ResolveDID(ctx context.Context, did syntax.DID) (*DIDDocument, error)
Resolves a DID to a parsed `DIDDocument` struct.
This method does not bi-directionally verify handles. Most atproto-specific code should use the `identity.Directory` interface ("Lookup" methods), which implement that check by default, and provide more ergonomic helpers for working with atproto-relevant information in DID documents.
Note that the `DIDDocument` might not include all the information in the original document. Use `ResolveDIDRaw()` to get the full original JSON.
func (*BaseDirectory) ResolveDIDRaw ¶
func (d *BaseDirectory) ResolveDIDRaw(ctx context.Context, did syntax.DID) (json.RawMessage, error)
Low-level method for resolving a DID to a raw JSON document.
This method does not parse the DID document into an atproto-specific format, and does not bi-directionally verify handles. Most atproto-specific code should use the "Lookup*" methods, which do implement that functionality.
func (*BaseDirectory) ResolveHandle ¶
func (*BaseDirectory) ResolveHandleDNS ¶
func (d *BaseDirectory) ResolveHandleDNS(ctx context.Context, handle syntax.Handle) (syntax.DID, error)
Does not cross-verify, only does the handle resolution step.
func (*BaseDirectory) ResolveHandleDNSAuthoritative ¶
func (d *BaseDirectory) ResolveHandleDNSAuthoritative(ctx context.Context, handle syntax.Handle) (syntax.DID, error)
this is a variant of ResolveHandleDNS which first does an authoritative nameserver lookup, then queries there
func (*BaseDirectory) ResolveHandleDNSFallback ¶
func (d *BaseDirectory) ResolveHandleDNSFallback(ctx context.Context, handle syntax.Handle) (syntax.DID, error)
variant of ResolveHandleDNS which uses any configured fallback DNS servers
func (*BaseDirectory) ResolveHandleWellKnown ¶
func (*BaseDirectory) ResolveNSID ¶
Resolves an NSID to a DID, as used for Lexicon resolution (using "_lexicon" DNS TXT record)
type CacheDirectory ¶
type CacheDirectory struct {
Inner Directory
ErrTTL time.Duration
InvalidHandleTTL time.Duration
// contains filtered or unexported fields
}
CacheDirectory is an implementation of identity.Directory with local cache of Handle and DID
func NewCacheDirectory ¶
func NewCacheDirectory(inner Directory, capacity int, hitTTL, errTTL, invalidHandleTTL time.Duration) CacheDirectory
Capacity of zero means unlimited size. Similarly, ttl of zero means unlimited duration.
func (*CacheDirectory) Lookup ¶
func (d *CacheDirectory) Lookup(ctx context.Context, a syntax.AtIdentifier) (*Identity, error)
func (*CacheDirectory) LookupDIDWithCacheState ¶
func (*CacheDirectory) LookupHandle ¶
func (*CacheDirectory) LookupHandleWithCacheState ¶
func (*CacheDirectory) Purge ¶
func (d *CacheDirectory) Purge(ctx context.Context, atid syntax.AtIdentifier) error
func (*CacheDirectory) ResolveHandle ¶
type DIDDocument ¶
type DIDDocument struct {
DID syntax.DID `json:"id"`
AlsoKnownAs []string `json:"alsoKnownAs,omitempty"`
VerificationMethod []DocVerificationMethod `json:"verificationMethod,omitempty"`
Service []DocService `json:"service,omitempty"`
}
type Directory ¶
type Directory interface {
LookupHandle(ctx context.Context, handle syntax.Handle) (*Identity, error)
LookupDID(ctx context.Context, did syntax.DID) (*Identity, error)
Lookup(ctx context.Context, atid syntax.AtIdentifier) (*Identity, error)
// Flushes any cache of the indicated identifier. If directory is not using caching, can ignore this.
Purge(ctx context.Context, atid syntax.AtIdentifier) error
}
Ergonomic interface for atproto identity lookup, by DID or handle.
The "Lookup" methods resolve identities (handle and DID), and return results in a compact, opinionated struct (`Identity`). They do bi-directional handle/DID verification by default. Clients and services should use these methods by default, instead of resolving handles or DIDs separately.
Looking up a handle which fails to resolve, or don't match DID alsoKnownAs, returns an error. When looking up a DID, if the handle does not resolve back to the DID, the lookup succeeds and returns an `Identity` where the Handle is the special `handle.invalid` value.
Some example implementations of this interface could be:
- basic direct resolution on every call
- local in-memory caching layer to reduce network hits
- API client, which just makes requests to PDS (or other remote service)
- client for shared network cache (eg, Redis)
func DefaultDirectory ¶
func DefaultDirectory() Directory
Returns a reasonable Directory implementation for applications
type DocService ¶
type DocVerificationMethod ¶
type Identity ¶
type Identity struct {
DID syntax.DID
// Handle/DID mapping must be bi-directionally verified. If that fails, the Handle should be the special 'handle.invalid' value
Handle syntax.Handle
// These fields represent a parsed subset of a DID document. They are all nullable. Note that the services and keys maps do not preserve order, so they don't exactly round-trip DID documents.
AlsoKnownAs []string
Services map[string]ServiceEndpoint
Keys map[string]VerificationMethod
}
Represents an atproto identity. Could be a regular user account, or a service account (eg, feed generator)
func ParseIdentity ¶
func ParseIdentity(doc *DIDDocument) Identity
Extracts the information relevant to atproto from an arbitrary DID document.
Always returns an invalid Handle field; calling code should only populate that field if it has been bi-directionally verified.
func (*Identity) DIDDocument ¶
func (ident *Identity) DIDDocument() DIDDocument
Helper to generate a DID document based on an identity. Note that there is flexibility around parsing, and this won't necessarily "round-trip" for every valid DID document.
func (*Identity) DeclaredHandle ¶
Returns an atproto handle from the alsoKnownAs URI list for this identifier. Returns an error if there is no handle, or if an at:// URI fails to parse as a handle.
Note that this handle is *not* necessarily to be trusted, as it may not have been bi-directionally verified. The 'Handle' field on the 'Identity' should contain either a verified handle, or the special 'handle.invalid' indicator value.
func (*Identity) GetPublicKey ¶
Identifies and parses a specified service signing public key out of any keys in this identity's DID document.
Returns [ErrKeyNotFound] if there is no such key.
Note that atcrypto.PublicKey is an interface, not a concrete type.
func (*Identity) GetServiceEndpoint ¶
Returns the service endpoint URL for specified service ID (the fragment part of identifier, not including the hash symbol).
The endpoint should be an HTTP URL with method, hostname, and optional port. It may or may not include path segments.
Returns an empty string if the service isn't found, or if the URL fails to parse.
func (*Identity) PDSEndpoint ¶
The home PDS endpoint for this identity, if one is included in the DID document.
The endpoint should be an HTTP URL with method, hostname, and optional port. It may or may not include path segments.
Returns an empty string if the service isn't found, or if the URL fails to parse.
func (*Identity) PublicKey ¶
Identifies and parses the atproto repo signing public key, specifically, out of any keys in this identity's DID document.
Returns [ErrKeyNotFound] if there is no such key.
Note that atcrypto.PublicKey is an interface, not a concrete type.
type MockDirectory ¶
type MockDirectory struct {
Handles map[syntax.Handle]syntax.DID
Identities map[syntax.DID]Identity
// contains filtered or unexported fields
}
A fake identity directory, for use in tests
func NewMockDirectory ¶
func NewMockDirectory() MockDirectory
func (*MockDirectory) Insert ¶
func (d *MockDirectory) Insert(ident Identity)
func (*MockDirectory) Lookup ¶
func (d *MockDirectory) Lookup(ctx context.Context, a syntax.AtIdentifier) (*Identity, error)
func (*MockDirectory) LookupHandle ¶
func (*MockDirectory) Purge ¶
func (d *MockDirectory) Purge(ctx context.Context, a syntax.AtIdentifier) error
func (*MockDirectory) ResolveDID ¶
func (d *MockDirectory) ResolveDID(ctx context.Context, did syntax.DID) (*DIDDocument, error)
func (*MockDirectory) ResolveDIDRaw ¶
func (d *MockDirectory) ResolveDIDRaw(ctx context.Context, did syntax.DID) (json.RawMessage, error)
func (*MockDirectory) ResolveHandle ¶
type Resolver ¶
type Resolver interface {
ResolveDID(ctx context.Context, did syntax.DID) (*DIDDocument, error)
ResolveDIDRaw(ctx context.Context, did syntax.DID) (json.RawMessage, error)
ResolveHandle(ctx context.Context, handle syntax.Handle) (syntax.DID, error)
}
Low-level interface for resolving DIDs and atproto handles.
Most atproto code should use the `identity.Directory` interface instead.
type ServiceEndpoint ¶
Sub-field type for Identity, representing a service endpoint URL declared in the DID document.
type VerificationMethod ¶
Sub-field type for Identity, representing a cryptographic public key declared as a "verificationMethod" in the DID document.
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
Identity Directory implementation which makes HTTP requests to a dedicated identity service.
|
Identity Directory implementation which makes HTTP requests to a dedicated identity service. |
|
cmd
|
|
|
atp-id
command
|
|
|
Identity Directory implementation with tiered caching, using Redis.
|
Identity Directory implementation with tiered caching, using Redis. |