atproto_auth 0.2.1 → 0.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3b5a970c60c05fb183389ef64b1fbd38bfdfc1e2cda615189e0c0e74362f6097
4
- data.tar.gz: a841c5f2eebcb6aaf093566e2abda9d0e53cd2e298d0ce20d308e96aa51bdbbf
3
+ metadata.gz: 1543cc3c9cf5c099a76a62e75990217400930bfd00f8fa19b53b4bef9c035940
4
+ data.tar.gz: 294daf80d312117a27d7bcfda8fdb1e48865793736aa3a491bf13f61f73caeaa
5
5
  SHA512:
6
- metadata.gz: 663b4810b6e888ac345a2d3a67eb8d506a2bd41257c318a7d61978172078a69b1b084f13fee6d0a42f0c982b85c46922a6c4b2b8134f8a84d88b07a36a6ce697
7
- data.tar.gz: 0e3c7cd954d9a8a7803c2aba41f12d45d3ecf877b7c130ee732f844d75cb352fabb9bf88173006610962604eff8752baf966939be5aa0263d09e808a97b35328
6
+ metadata.gz: 1f58e87d6dddab0421cc3637c166d84468f3b863004e6e22f377a200bb149b4bf51db8bf6b4d5d15161a897bcdee15801352932f7d457b57a53142dc4da42296
7
+ data.tar.gz: 21ce4544366475e39cce0bc0e52596fbfd9278b32a18c8b30193330f3b9946177c06450c3ddda93d3136bd386e9496279834821b7fec45be5f8c369e015f6ed7
data/CHANGELOG.md CHANGED
@@ -4,6 +4,10 @@ All notable changes to this project will be documented in this file.
4
4
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
5
5
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
6
 
7
+ ## [0.2.1] - 2024-12-11
8
+ ### Added
9
+ - Added support for did:web users
10
+
7
11
  ## [0.2.1] - 2024-12-11
8
12
  ### Fixed
9
13
  - Fixed a bug with access token hash generation
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: ../..
3
3
  specs:
4
- atproto_auth (0.2.1)
4
+ atproto_auth (0.2.2)
5
5
  jose (~> 1.2)
6
6
  jwt (~> 2.9)
7
7
  redis (~> 5.3)
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "resolv"
4
+
5
+ module AtprotoAuth
6
+ module Identity
7
+ # Validates decentralized identifiers (DIDs)
8
+ class DID
9
+ PREFIXES = ["did:plc:", "did:web:"].freeze
10
+
11
+ def initialize(did)
12
+ @did = did
13
+ end
14
+
15
+ def validate!
16
+ return if PREFIXES.any? { |prefix| @did.start_with?(prefix) }
17
+
18
+ raise Error, "Invalid DID format (must be one of #{PREFIXES.join(", ")}): #{@did}"
19
+ end
20
+
21
+ def to_s
22
+ @did
23
+ end
24
+ end
25
+ end
26
+ end
@@ -68,16 +68,10 @@ module AtprotoAuth
68
68
  raise DocumentError, "Document must be a Hash" unless data.is_a?(Hash)
69
69
  raise DocumentError, "Document must have id" unless data["id"]
70
70
 
71
- validate_did!(data["id"])
71
+ DID.new(data["id"]).validate!
72
72
  validate_services!(data["service"])
73
73
  end
74
74
 
75
- def validate_did!(did)
76
- return if did.start_with?("did:plc:")
77
-
78
- raise DocumentError, "Invalid DID format (must be did:plc:): #{did}"
79
- end
80
-
81
75
  def validate_services!(services)
82
76
  return if services.nil?
83
77
  raise DocumentError, "services must be an array" unless services.is_a?(Array)
@@ -39,7 +39,7 @@ module AtprotoAuth
39
39
  # @return [Hash] Resolution result with :did, :document, and :pds keys
40
40
  # @raise [ResolutionError] if resolution fails
41
41
  def get_did_info(did)
42
- validate_did!(did)
42
+ DID.new(did).validate!
43
43
 
44
44
  # Fetch and parse DID document
45
45
  doc_data = fetch_did_document(did)
@@ -108,12 +108,6 @@ module AtprotoAuth
108
108
  raise ResolutionError, "Invalid handle format: #{handle}"
109
109
  end
110
110
 
111
- def validate_did!(did)
112
- return if did.start_with?(DID_PLC_PREFIX)
113
-
114
- raise ResolutionError, "Invalid DID format (must be did:plc:): #{did}"
115
- end
116
-
117
111
  def normalize_handle(handle)
118
112
  normalized = handle.start_with?("@") ? handle[1..] : handle
119
113
  normalized.downcase
@@ -178,17 +172,52 @@ module AtprotoAuth
178
172
  response = AtprotoAuth.configuration.http_client.get(uri.to_s)
179
173
  did = response[:body].strip
180
174
 
181
- validate_did!(did)
175
+ DID.new(did).validate!
182
176
  get_did_info(did)
183
177
  end
184
178
 
185
179
  def fetch_did_document(did)
186
- # Fetch document from PLC directory
180
+ if did.start_with?("did:web:")
181
+ fetch_web_did_document(did)
182
+ else
183
+ fetch_plc_did_document(did)
184
+ end
185
+ end
186
+
187
+ def fetch_plc_did_document(did)
187
188
  uri = URI.join(@plc_directory, "/#{did}")
188
189
  response = AtprotoAuth.configuration.http_client.get(uri.to_s)
189
190
  JSON.parse(response[:body])
190
191
  end
191
192
 
193
+ def fetch_web_did_document(did)
194
+ # Strip off the "did:web:" prefix
195
+ identifier = did.delete_prefix("did:web:")
196
+
197
+ # Convert colons to slashes for path components
198
+ # But we need to handle any percent-encoded colons in the domain portion first
199
+ parts = identifier.split(":", 2) # Split on first colon to separate domain from path
200
+ domain = parts[0]
201
+ path = parts[1]
202
+
203
+ # Construct the URL
204
+ url = if path
205
+ # Replace remaining colons with slashes and append did.json
206
+ path_with_slashes = path.tr(":", "/")
207
+ "https://#{domain}/#{path_with_slashes}/did.json"
208
+ else
209
+ # No path - use .well-known location
210
+ "https://#{domain}/.well-known/did.json"
211
+ end
212
+
213
+ begin
214
+ response = AtprotoAuth.configuration.http_client.get(url)
215
+ JSON.parse(response[:body])
216
+ rescue StandardError => e
217
+ raise ResolutionError, "Failed to fetch did:web document: #{e.message}"
218
+ end
219
+ end
220
+
192
221
  def validate_pds_url!(url)
193
222
  uri = URI(url)
194
223
  return if uri.is_a?(URI::HTTPS)
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module AtprotoAuth
4
- VERSION = "0.2.1"
4
+ VERSION = "0.2.2"
5
5
  end
data/lib/atproto_auth.rb CHANGED
@@ -33,6 +33,7 @@ require "atproto_auth/state/session"
33
33
  require "atproto_auth/state/session_manager"
34
34
 
35
35
  require "atproto_auth/identity"
36
+ require "atproto_auth/identity/did"
36
37
  require "atproto_auth/identity/document"
37
38
  require "atproto_auth/identity/resolver"
38
39
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: atproto_auth
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 0.2.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Josh Huckabee
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-12-11 00:00:00.000000000 Z
11
+ date: 2024-12-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: jose
@@ -92,6 +92,7 @@ files:
92
92
  - lib/atproto_auth/errors.rb
93
93
  - lib/atproto_auth/http_client.rb
94
94
  - lib/atproto_auth/identity.rb
95
+ - lib/atproto_auth/identity/did.rb
95
96
  - lib/atproto_auth/identity/document.rb
96
97
  - lib/atproto_auth/identity/resolver.rb
97
98
  - lib/atproto_auth/par.rb