+14
-2
app/authenticator.rb
+14
-2
app/authenticator.rb
···
6
6
require 'openssl'
7
7
8
8
class Authenticator
9
+
class InvalidTokenError < StandardError
10
+
end
11
+
9
12
def initialize(hostname:)
10
13
@@pkey_cache ||= {}
11
14
@hostname = hostname
···
15
18
return nil unless auth_header.start_with?('Bearer ')
16
19
17
20
token = auth_header.gsub(/\ABearer /, '')
18
-
data = JSON.parse(Base64.decode64(token.split('.')[1]))
21
+
parts = token.split('.')
22
+
raise InvalidTokenError, "Invalid JWT token" if parts.length != 3
23
+
24
+
begin
25
+
decoded_data = Base64.decode64(parts[1])
26
+
data = JSON.parse(decoded_data)
27
+
rescue StandardError => e
28
+
raise InvalidTokenError, "Invalid JWT token"
29
+
end
30
+
19
31
did = data['iss']
20
-
return nil if data['aud'] != "did:web:#{@hostname}" || data['lxm'] != endpoint
32
+
return nil if did.nil? || data['aud'] != "did:web:#{@hostname}" || data['lxm'] != endpoint
21
33
22
34
pkey = pkey_for_user(did)
23
35
+43
-19
app/server.rb
+43
-19
app/server.rb
···
23
23
content_type :json
24
24
[status, JSON.generate({ error: name, message: message })]
25
25
end
26
+
27
+
def get_user_did
28
+
if settings.development?
29
+
if did = params[:user]
30
+
return did
31
+
else
32
+
halt json_error('AuthMissing', 'Missing "user" parameter', status: 401)
33
+
end
34
+
else
35
+
auth_header = env['HTTP_AUTHORIZATION']
36
+
if auth_header.to_s.strip.empty?
37
+
halt json_error('AuthMissing', 'Missing authentication header', status: 401)
38
+
end
39
+
40
+
begin
41
+
did = @authenticator.decode_user_from_jwt(auth_header, 'blue.feeds.lycan.searchPosts')
42
+
rescue StandardError => e
43
+
halt json_error('InvalidToken', e.message, status: 401)
44
+
end
45
+
46
+
if did
47
+
return did
48
+
else
49
+
halt json_error('InvalidToken', "Invalid JWT token", status: 401)
50
+
end
51
+
end
52
+
end
53
+
54
+
def load_user
55
+
did = get_user_did
56
+
57
+
if user = User.find_by(did: did)
58
+
return user
59
+
else
60
+
halt json_error('AccountNotFound', 'Account not found', status: 401)
61
+
end
62
+
end
26
63
end
27
64
28
65
before do
···
32
69
get '/xrpc/blue.feeds.lycan.searchPosts' do
33
70
headers['access-control-allow-origin'] = '*'
34
71
35
-
if settings.development?
36
-
user = User.find_by(did: params[:user])
37
-
return json_error('UserNotFound', 'Missing "user" parameter') if user.nil?
38
-
else
39
-
begin
40
-
auth_header = env['HTTP_AUTHORIZATION']
41
-
did = @authenticator.decode_user_from_jwt(auth_header, 'blue.feeds.lycan.searchPosts')
42
-
rescue StandardError => e
43
-
p e
44
-
end
45
-
46
-
user = did && User.find_by(did: did)
47
-
return json_error('UserNotFound', 'Missing authentication header') if user.nil?
48
-
end
72
+
@user = load_user
49
73
50
74
if params[:query].to_s.strip.empty?
51
75
return json_error('MissingParameter', 'Missing "query" parameter')
···
58
82
query = QueryParser.new(params[:query])
59
83
60
84
collection = case params[:collection]
61
-
when 'likes' then user.likes
62
-
when 'pins' then user.pins
63
-
when 'quotes' then user.quotes
64
-
when 'reposts' then user.reposts
85
+
when 'likes' then @user.likes
86
+
when 'pins' then @user.pins
87
+
when 'quotes' then @user.quotes
88
+
when 'reposts' then @user.reposts
65
89
else return json_error('InvalidParameter', 'Invalid search collection')
66
90
end
67
91
···
80
104
81
105
post_uris = case params[:collection]
82
106
when 'quotes'
83
-
items.map { |x| "at://#{user.did}/app.bsky.feed.post/#{x.rkey}" }
107
+
items.map { |x| "at://#{@user.did}/app.bsky.feed.post/#{x.rkey}" }
84
108
else
85
109
items.map(&:post).map(&:at_uri)
86
110
end