identity

package
v0.0.0-...-ef8e99b Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 3, 2024 License: Apache-2.0, MIT Imports: 19 Imported by: 8

Documentation

Overview

Package identity provides types and routines for resolving handles and DIDs from the network

The two main abstractions are a Catalog interface for identity service implementations, and an Identity structure which represents core identity information relevant to atproto. The Catalog interface can be nested, somewhat like HTTP middleware, to provide caching, observability, or other bespoke needs in more complex systems.

Much of the implementation of this SDK is based on existing code in indigo:api/extra.go

Index

Constants

This section is empty.

Variables

View Source
var DefaultPLCURL = "https://plc.directory"
View Source
var ErrDIDNotFound = errors.New("DID not found")

Indicates that resolution process completed successfully, but the DID does not exist.

View Source
var ErrDIDResolutionFailed = errors.New("DID resolution failed")

Indicates that DID resolution process failed. A wrapped error may provide more context.

View Source
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.

View Source
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.

View Source
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.

View Source
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

View Source
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.

View Source
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
}

The zero value ('BaseDirectory{}') is a usable Directory.

func (*BaseDirectory) Lookup

func (*BaseDirectory) LookupDID

func (d *BaseDirectory) LookupDID(ctx context.Context, did syntax.DID) (*Identity, error)

func (*BaseDirectory) LookupHandle

func (d *BaseDirectory) LookupHandle(ctx context.Context, h syntax.Handle) (*Identity, error)

func (*BaseDirectory) Purge

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 (d *BaseDirectory) ResolveHandle(ctx context.Context, handle syntax.Handle) (syntax.DID, error)

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 (d *BaseDirectory) ResolveHandleWellKnown(ctx context.Context, handle syntax.Handle) (syntax.DID, error)

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 time.Duration, 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 (*CacheDirectory) LookupDID

func (d *CacheDirectory) LookupDID(ctx context.Context, did syntax.DID) (*Identity, error)

func (*CacheDirectory) LookupDIDWithCacheState

func (d *CacheDirectory) LookupDIDWithCacheState(ctx context.Context, did syntax.DID) (*Identity, bool, error)

func (*CacheDirectory) LookupHandle

func (d *CacheDirectory) LookupHandle(ctx context.Context, h syntax.Handle) (*Identity, error)

func (*CacheDirectory) LookupHandleWithCacheState

func (d *CacheDirectory) LookupHandleWithCacheState(ctx context.Context, h syntax.Handle) (*Identity, bool, error)

func (*CacheDirectory) Purge

func (*CacheDirectory) ResolveHandle

func (d *CacheDirectory) ResolveHandle(ctx context.Context, h syntax.Handle) (syntax.DID, error)

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 DocService struct {
	ID              string `json:"id"`
	Type            string `json:"type"`
	ServiceEndpoint string `json:"serviceEndpoint"`
}

type DocVerificationMethod

type DocVerificationMethod struct {
	ID                 string `json:"id"`
	Type               string `json:"type"`
	Controller         string `json:"controller"`
	PublicKeyMultibase string `json:"publicKeyMultibase"`
}

type HandleEntry

type HandleEntry struct {
	Updated time.Time
	DID     syntax.DID
	Err     error
}

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

func (i *Identity) DeclaredHandle() (syntax.Handle, error)

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

func (i *Identity) GetPublicKey(id string) (crypto.PublicKey, error)

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

func (i *Identity) GetServiceEndpoint(id string) string

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

func (i *Identity) PDSEndpoint() string

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

func (i *Identity) PublicKey() (crypto.PublicKey, error)

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 IdentityEntry

type IdentityEntry struct {
	Updated  time.Time
	Identity *Identity
	Err      error
}

type Key

type Key struct {
	Type               string
	PublicKeyMultibase string
}

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 (*MockDirectory) LookupDID

func (d *MockDirectory) LookupDID(ctx context.Context, did syntax.DID) (*Identity, error)

func (*MockDirectory) LookupHandle

func (d *MockDirectory) LookupHandle(ctx context.Context, h syntax.Handle) (*Identity, error)

func (*MockDirectory) Purge

type Service

type Service struct {
	Type string
	URL  string
}

Directories

Path Synopsis
cmd
Identity Directory implementation with tiered caching, using Redis.
Identity Directory implementation with tiered caching, using Redis.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL