Class: DiscourseSubscriptionClient::Authorization

Inherits:
Object
  • Object
show all
Defined in:
lib/discourse_subscription_client/authorization.rb

Class Method Summary collapse

Class Method Details

.client_id(user_id) ⇒ Object



81
82
83
# File 'lib/discourse_subscription_client/authorization.rb', line 81

def self.client_id(user_id)
  "#{Discourse.current_hostname}:#{user_id}:#{SecureRandom.hex(8)}"
end

.decrypt_payload(request_id, payload) ⇒ Object



40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
# File 'lib/discourse_subscription_client/authorization.rb', line 40

def self.decrypt_payload(request_id, payload)
  keys = get_keys(request_id)

  return false unless keys.present? && keys.pem

  delete_keys(request_id)

  rsa = OpenSSL::PKey::RSA.new(keys.pem)
  decrypted_payload = rsa.private_decrypt(Base64.decode64(payload))

  return false unless decrypted_payload.present?

  begin
    data = JSON.parse(decrypted_payload).symbolize_keys
  rescue JSON::ParserError
    return false
  end

  return false unless data[:nonce] == keys.nonce

  data[:user_id] = keys.user_id
  data
end

.delete_keys(request_id) ⇒ Object



96
97
98
# File 'lib/discourse_subscription_client/authorization.rb', line 96

def self.delete_keys(request_id)
  PluginStore.remove(DiscourseSubscriptionClient::PLUGIN_NAME, "#{keys_db_key}_#{request_id}")
end

.generate_keys(user_id, request_id) ⇒ Object



33
34
35
36
37
38
# File 'lib/discourse_subscription_client/authorization.rb', line 33

def self.generate_keys(user_id, request_id)
  rsa = OpenSSL::PKey::RSA.generate(2048)
  nonce = SecureRandom.hex(32)
  set_keys(request_id, user_id, rsa, nonce)
  OpenStruct.new(nonce: nonce, public_key: rsa.public_key)
end

.get_keys(request_id) ⇒ Object



64
65
66
67
68
69
70
71
# File 'lib/discourse_subscription_client/authorization.rb', line 64

def self.get_keys(request_id)
  raw = PluginStore.get(DiscourseSubscriptionClient::PLUGIN_NAME, "#{keys_db_key}_#{request_id}")
  OpenStruct.new(
    user_id: raw && raw["user_id"],
    pem: raw && raw["pem"],
    nonce: raw && raw["nonce"]
  )
end

.keys_db_keyObject



85
86
87
# File 'lib/discourse_subscription_client/authorization.rb', line 85

def self.keys_db_key
  "keys"
end

.process_response(request_id, payload) ⇒ Object



26
27
28
29
30
31
# File 'lib/discourse_subscription_client/authorization.rb', line 26

def self.process_response(request_id, payload)
  data = decrypt_payload(request_id, payload)
  return false unless data.is_a?(Hash) && data[:key] && data[:user_id]

  data
end

.request_id(supplier_id) ⇒ Object



7
8
9
# File 'lib/discourse_subscription_client/authorization.rb', line 7

def self.request_id(supplier_id)
  "#{supplier_id}-#{SecureRandom.hex(32)}"
end

.revoke(supplier) ⇒ Object



73
74
75
76
77
78
79
# File 'lib/discourse_subscription_client/authorization.rb', line 73

def self.revoke(supplier)
  url = "#{supplier.url}/user-api-key/revoke"
  request = DiscourseSubscriptionClient::Request.new(:supplier, supplier.id)
  headers = { "User-Api-Key" => supplier.api_key }
  result = request.perform(url, headers: headers, body: nil, opts: { method: "POST" })
  result && result[:success] == "OK"
end

.set_keys(request_id, user_id, rsa, nonce) ⇒ Object



89
90
91
92
93
94
# File 'lib/discourse_subscription_client/authorization.rb', line 89

def self.set_keys(request_id, user_id, rsa, nonce)
  PluginStore.set(DiscourseSubscriptionClient::PLUGIN_NAME, "#{keys_db_key}_#{request_id}",
                  user_id: user_id,
                  pem: rsa.export,
                  nonce: nonce)
end

.url(user, supplier, request_id) ⇒ Object



11
12
13
14
15
16
17
18
19
20
21
22
23
24
# File 'lib/discourse_subscription_client/authorization.rb', line 11

def self.url(user, supplier, request_id)
  keys = generate_keys(user.id, request_id)
  params = {
    public_key: keys.public_key,
    nonce: keys.nonce,
    client_id: client_id(user.id),
    auth_redirect: "#{Discourse.base_url}/admin/plugins/subscription-client/suppliers/authorize/callback",
    application_name: SiteSetting.title,
    scopes: SCOPE
  }
  uri = URI.parse("#{supplier.url}/user-api-key/new")
  uri.query = URI.encode_www_form(params)
  uri.to_s
end