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
- func TestDIDDocFeedGenParse(t *testing.T)
- func TestDIDDocParse(t *testing.T)
- 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, a syntax.AtIdentifier) error
- func (d *BaseDirectory) ResolveDID(ctx context.Context, did syntax.DID) (*DIDDocument, error)
- func (d *BaseDirectory) ResolveDIDPLC(ctx context.Context, did syntax.DID) (*DIDDocument, error)
- func (d *BaseDirectory) ResolveDIDWeb(ctx context.Context, did syntax.DID) (*DIDDocument, 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)
- type CacheDirectory
- func (d *CacheDirectory) IsHandleStale(e *HandleEntry) bool
- func (d *CacheDirectory) IsIdentityStale(e *IdentityEntry) bool
- 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, a 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 HandleEntry
- type Identity
- type IdentityEntry
- type Key
- 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
- type Service
Constants ¶
This section is empty.
Variables ¶
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 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 ¶
func TestDIDDocFeedGenParse ¶
func TestDIDDocParse ¶
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 }
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, a syntax.AtIdentifier) error
func (*BaseDirectory) ResolveDID ¶
func (d *BaseDirectory) ResolveDID(ctx context.Context, did syntax.DID) (*DIDDocument, error)
WARNING: this does *not* bi-directionally verify account metadata; it only implements direct DID-to-DID-document lookup for the supported DID methods, and parses the resulting DID Doc into an Identity struct
func (*BaseDirectory) ResolveDIDPLC ¶
func (d *BaseDirectory) ResolveDIDPLC(ctx context.Context, did syntax.DID) (*DIDDocument, error)
func (*BaseDirectory) ResolveDIDWeb ¶
func (d *BaseDirectory) ResolveDIDWeb(ctx context.Context, did syntax.DID) (*DIDDocument, error)
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 ¶
type CacheDirectory ¶
type CacheDirectory struct { Inner Directory ErrTTL time.Duration InvalidHandleTTL time.Duration // contains filtered or unexported fields }
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) IsHandleStale ¶
func (d *CacheDirectory) IsHandleStale(e *HandleEntry) bool
func (*CacheDirectory) IsIdentityStale ¶
func (d *CacheDirectory) IsIdentityStale(e *IdentityEntry) bool
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, a 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, h syntax.Handle) (*Identity, error) LookupDID(ctx context.Context, d syntax.DID) (*Identity, error) Lookup(ctx context.Context, i syntax.AtIdentifier) (*Identity, error) // Flushes any cache of the indicated identifier. If directory is not using caching, can ignore this. Purge(ctx context.Context, i syntax.AtIdentifier) error }
API for doing account lookups by DID or handle, with bi-directional verification handled automatically. Almost all atproto services and clients should use an implementation of this interface instead of resolving handles or DIDs separately
Handles which fail to resolve, or don't match DID alsoKnownAs, are an error. DIDs which resolve but the handle does not resolve back to the DID return 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]Service Keys map[string]Key }
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) 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 crypto.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 serivce 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 serivce 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 crypto.PublicKey is an interface, not a concrete type.
type MockDirectory ¶
type MockDirectory struct { Handles map[syntax.Handle]syntax.DID Identities map[syntax.DID]Identity }
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