Class: AtprotoAuth::Identity::Resolver
- Inherits:
-
Object
- Object
- AtprotoAuth::Identity::Resolver
- Defined in:
- lib/atproto_auth/identity/resolver.rb
Overview
Resolves and validates AT Protocol identities
Constant Summary collapse
- PLC_DIRECTORY_URL =
"https://plc.directory"
- DID_PLC_PREFIX =
"did:plc:"
- HANDLE_REGEX =
/^([a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?$/
Instance Method Summary collapse
-
#get_did_info(did) ⇒ Hash
Fetches and parses DID Document.
-
#initialize(plc_directory: nil) ⇒ Resolver
constructor
Creates a new Identity resolver.
-
#resolve_handle(handle) ⇒ Hash
Resolves a handle to a DID Document.
-
#verify_handle_binding(handle, did) ⇒ Boolean
Verifies that a handle belongs to a DID.
-
#verify_issuer_binding(did, issuer) ⇒ Boolean
Verifies that an auth server (issuer) is authorized for a DID.
-
#verify_pds_binding(did, pds_url) ⇒ Boolean
Verifies that a PDS hosts a given DID.
Constructor Details
#initialize(plc_directory: nil) ⇒ Resolver
Creates a new Identity resolver
15 16 17 |
# File 'lib/atproto_auth/identity/resolver.rb', line 15 def initialize(plc_directory: nil) @plc_directory = plc_directory || PLC_DIRECTORY_URL end |
Instance Method Details
#get_did_info(did) ⇒ Hash
Fetches and parses DID Document
41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 |
# File 'lib/atproto_auth/identity/resolver.rb', line 41 def get_did_info(did) DID.new(did).validate! # Fetch and parse DID document doc_data = fetch_did_document(did) document = Document.new(doc_data) # Validate PDS URL format validate_pds_url!(document.pds) { did: did, document: document, pds: document.pds } rescue DocumentError => e raise ResolutionError, "Invalid DID document: #{e.}" rescue StandardError => e raise ResolutionError, "Failed to resolve DID #{did}: #{e.}" end |
#resolve_handle(handle) ⇒ Hash
Resolves a handle to a DID Document
23 24 25 26 27 28 29 30 31 32 33 34 35 |
# File 'lib/atproto_auth/identity/resolver.rb', line 23 def resolve_handle(handle) validate_handle!(handle) normalized = normalize_handle(handle) # First try DNS-based resolution did = resolve_handle_dns(normalized) return get_did_info(did) if did # Fall back to HTTP resolution via a known PDS resolve_handle_http(normalized) rescue StandardError => e raise ResolutionError, "Failed to resolve handle #{handle}: #{e.}" end |
#verify_handle_binding(handle, did) ⇒ Boolean
Verifies that a handle belongs to a DID
103 104 105 106 107 108 109 110 111 112 113 114 |
# File 'lib/atproto_auth/identity/resolver.rb', line 103 def verify_handle_binding(handle, did) info = get_did_info(did) unless info[:document].has_handle?(handle) raise ValidationError, "Handle #{handle} does not belong to DID #{did}" end true rescue StandardError => e raise ValidationError, "Failed to verify handle binding: #{e.}" end |
#verify_issuer_binding(did, issuer) ⇒ Boolean
Verifies that an auth server (issuer) is authorized for a DID
79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 |
# File 'lib/atproto_auth/identity/resolver.rb', line 79 def verify_issuer_binding(did, issuer) # Get PDS location from DID info = get_did_info(did) pds_url = info[:pds] # Fetch resource server metadata to find auth server resource_server = ServerMetadata::ResourceServer.from_url(pds_url) auth_server_url = resource_server..first # Compare normalized URLs if normalize_url(auth_server_url) != normalize_url(issuer) raise ValidationError, "Issuer #{issuer} is not authorized for DID #{did}" end true rescue StandardError => e raise ValidationError, "Failed to verify issuer binding: #{e.}" end |
#verify_pds_binding(did, pds_url) ⇒ Boolean
Verifies that a PDS hosts a given DID
63 64 65 66 67 68 69 70 71 72 |
# File 'lib/atproto_auth/identity/resolver.rb', line 63 def verify_pds_binding(did, pds_url) info = get_did_info(did) if normalize_url(info[:pds]) != normalize_url(pds_url) raise ValidationError, "PDS #{pds_url} is not authorized for DID #{did}" end true rescue StandardError => e raise ValidationError, "Failed to verify PDS binding: #{e.}" end |