authsignal-ruby 5.1.0 → 5.2.0

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: 83967ef0e6e635ee8073707bd26080c9349a0a15ad7352baa99e8d0097aebdcd
4
- data.tar.gz: 9bd1c701d4d60705ba92b90335bb8a5dafb889ac4298eb5935df6ce0a1dab963
3
+ metadata.gz: 233b8ce1fffe587695f60a898cbd6ca8172e2ed4fcd4e290bd1bbf2c31f35e69
4
+ data.tar.gz: 884eae4802fa843c90110be96614d5ed39a115ff466a498462945bb468da3288
5
5
  SHA512:
6
- metadata.gz: f5ae54c8f9ebcf44efea16e05815b0320dac64909f8306decd8abe35b2ba33913b00471f0b6b5ecdfa9131f239dc08ae070ea18e28a5129506a09ce625c461c4
7
- data.tar.gz: 9689b2cb484837bac9ee107a55688abdd9ca9ba80f2d1a3a8668433edce69f74523c168afca7f660cfb788f1714d525a386ae5288f32ed8833d05a743bf89e1a
6
+ metadata.gz: af223d4b81a5c0457b8e4a530d7be4fab23d16bdbe72908ffd47533b69ff5a764a716cfc7e6c58f02beff55c93de452ae11996bd10e0f0912e43383b5dc0113f
7
+ data.tar.gz: 56fe2d42bf6e63a09d0daeb452f380369885d26cb70481ae0da3018a10806583d2a72cfdf69f4e408b8b94cc0799d00a44c47917c8ba2c0f3163e500ecd692cd
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- authsignal-ruby (5.1.0)
4
+ authsignal-ruby (5.2.0)
5
5
  faraday (>= 2.0.1)
6
6
  faraday-retry (~> 2.2)
7
7
 
data/README.md CHANGED
@@ -2,7 +2,10 @@
2
2
 
3
3
  # Authsignal Ruby SDK
4
4
 
5
- The Authsignal Ruby library for server-side applications.
5
+ [![Gem Version](https://img.shields.io/gem/v/authsignal-ruby.svg)](https://rubygems.org/gems/authsignal-ruby)
6
+ [![License](https://img.shields.io/github/license/authsignal/authsignal-ruby.svg)](https://github.com/authsignal/authsignal-ruby/blob/main/LICENSE.txt)
7
+
8
+ The official Authsignal Ruby library for server-side applications. Use this SDK to easily integrate Authsignal's multi-factor authentication (MFA) and passwordless features into your Ruby backend.
6
9
 
7
10
  ## Installation
8
11
 
@@ -12,48 +15,42 @@ Add this line to your application's Gemfile:
12
15
  gem "authsignal-ruby"
13
16
  ```
14
17
 
15
- ## Documentation
16
-
17
- Refer to our [SDK documentation](https://docs.authsignal.com/sdks/server/overview) for information on how to use this SDK.
18
-
19
- Or check out our [Ruby on Rails Quickstart Guide](https://docs.authsignal.com/integrations/ruby-on-rails).
18
+ And then execute:
19
+ ```bash
20
+ bundle install
21
+ ```
20
22
 
21
- ### Response & Error handling
23
+ Or install it yourself as:
24
+ ```bash
25
+ gem install authsignal-ruby
26
+ ```
22
27
 
23
- The Authsignal SDK offers two response formats. By default, its methods return the payload in hash format.
28
+ ## Getting started
24
29
 
25
- Example:
30
+ Initialize the Authsignal client with your secret key from the [Authsignal Portal](https://portal.authsignal.com/) and the API URL for your region.
26
31
 
27
32
  ```ruby
28
- Authsignal.enroll_verified_authenticator(
29
- user_id: 'AS_001',
30
- attributes: {
31
- verification_method: 'INVALID',
32
- email: 'hamish@authsignal.com'
33
- }
34
- )
35
-
36
- # returns:
37
- {
38
- "error": "invalid_request",
39
- "errorCode": "invalid_request",
40
- "errorDescription": "body.verificationMethod must be equal to one of the allowed values - allowedValues: AUTHENTICATOR_APP,EMAIL_MAGIC_LINK,EMAIL_OTP,SMS"
41
- }
33
+ require 'authsignal'
34
+
35
+ # Initialize the client
36
+ Authsignal.setup do |config|
37
+ config.api_secret_key = ENV['AUTHSIGNAL_SECRET_KEY']
38
+ config.api_url = ENV['AUTHSIGNAL_API_URL'] # Use region-specific URL
39
+ end
42
40
  ```
43
41
 
44
- All methods have a bang (!) counterpart that raises an Authsignal::ApiError if the request fails.
42
+ ### API URLs by region
45
43
 
46
- Example:
44
+ | Region | API URL |
45
+ | ----------- | -------------------------------- |
46
+ | US (Oregon) | https://api.authsignal.com/v1 |
47
+ | AU (Sydney) | https://au.api.authsignal.com/v1 |
48
+ | EU (Dublin) | https://eu.api.authsignal.com/v1 |
47
49
 
48
- ```ruby
49
- Authsignal.enroll_verified_authenticator!(
50
- user_id: 'AS_001',
51
- attributes: {
52
- verification_method: 'INVALID',
53
- email: 'hamish@authsignal.com'
54
- }
55
- )
56
-
57
- # raise:
58
- <Authsignal::ApiError: AuthsignalError: 400 - body.verificationMethod must be equal to one of the allowed values - allowedValues: AUTHENTICATOR_APP,EMAIL_MAGIC_LINK,EMAIL_OTP,SMS.
59
- ```
50
+ ## License
51
+
52
+ This SDK is licensed under the [MIT License](LICENSE.txt).
53
+
54
+ ## Documentation
55
+
56
+ For more information and advanced usage examples, refer to the official [Authsignal server-Side SDK documentation](https://docs.authsignal.com/sdks/server/overview).
@@ -2,7 +2,7 @@ require 'erb'
2
2
 
3
3
  module Authsignal
4
4
  class Client
5
- USER_AGENT = "Authsignal Ruby v#{Authsignal::VERSION}"
5
+ USER_AGENT = "authsignal-ruby"
6
6
  NO_API_KEY_MESSAGE = "No Authsignal API Secret Key Set"
7
7
 
8
8
  RETRY_OPTIONS = {
@@ -0,0 +1,7 @@
1
+ module Authsignal
2
+ class InvalidSignatureError < StandardError
3
+ def initialize(message)
4
+ super(message)
5
+ end
6
+ end
7
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Authsignal
4
- VERSION = "5.1.0"
4
+ VERSION = "5.2.0"
5
5
  end
@@ -0,0 +1,83 @@
1
+ require 'openssl'
2
+ require 'json'
3
+ require 'base64'
4
+
5
+ module Authsignal
6
+ DEFAULT_TOLERANCE = 5
7
+
8
+ class Webhook
9
+ VERSION = "v2"
10
+
11
+ attr_reader :api_secret_key
12
+
13
+ def initialize(api_secret_key)
14
+ @api_secret_key = api_secret_key
15
+ end
16
+
17
+ def construct_event(payload, signature, tolerance = DEFAULT_TOLERANCE)
18
+ parsed_signature = parse_signature(signature)
19
+
20
+ seconds_since_epoch = Time.now.to_i
21
+
22
+ if tolerance > 0 && parsed_signature[:timestamp] < seconds_since_epoch - (tolerance * 60)
23
+ raise InvalidSignatureError, "Timestamp is outside the tolerance zone."
24
+ end
25
+
26
+ hmac_content = "#{parsed_signature[:timestamp]}.#{payload}"
27
+
28
+ computed_signature = OpenSSL::HMAC.digest(
29
+ OpenSSL::Digest.new('sha256'),
30
+ @api_secret_key,
31
+ hmac_content
32
+ )
33
+ computed_signature_base64 = Base64.strict_encode64(computed_signature).delete('=')
34
+
35
+ match = false
36
+
37
+ parsed_signature[:signatures].each do |sig|
38
+ if sig == computed_signature_base64
39
+ match = true
40
+ break
41
+ end
42
+ end
43
+
44
+ unless match
45
+ raise InvalidSignatureError, "Signature mismatch."
46
+ end
47
+
48
+ JSON.parse(payload, symbolize_names: true)
49
+ end
50
+
51
+ def parse_signature(value)
52
+ result = {
53
+ timestamp: -1,
54
+ signatures: []
55
+ }
56
+
57
+ return handle_invalid_signature unless value
58
+
59
+ value.split(',').each do |item|
60
+ kv = item.split('=')
61
+ next unless kv.length == 2
62
+
63
+ if kv[0] == 't'
64
+ result[:timestamp] = kv[1].to_i
65
+ elsif kv[0] == VERSION
66
+ result[:signatures] << kv[1]
67
+ end
68
+ end
69
+
70
+ if result[:timestamp] == -1 || result[:signatures].empty?
71
+ handle_invalid_signature
72
+ end
73
+
74
+ result
75
+ end
76
+
77
+ private
78
+
79
+ def handle_invalid_signature
80
+ raise InvalidSignatureError, "Signature format is invalid."
81
+ end
82
+ end
83
+ end
data/lib/authsignal.rb CHANGED
@@ -4,11 +4,13 @@ require "authsignal/version"
4
4
  require "authsignal/client"
5
5
  require "authsignal/configuration"
6
6
  require "authsignal/api_error"
7
+ require "authsignal/invalid_signature_error"
8
+ require "authsignal/webhook"
7
9
  require "authsignal/middleware/json_response"
8
10
  require "authsignal/middleware/json_request"
9
11
 
10
12
  module Authsignal
11
- NON_API_METHODS = [:setup, :configuration, :default_configuration]
13
+ NON_API_METHODS = [:setup, :configuration, :default_configuration, :webhook]
12
14
 
13
15
  class << self
14
16
  attr_writer :configuration
@@ -25,6 +27,10 @@ module Authsignal
25
27
  configuration.defaults
26
28
  end
27
29
 
30
+ def webhook
31
+ @webhook ||= Webhook.new(configuration.api_secret_key)
32
+ end
33
+
28
34
  def get_user(user_id:)
29
35
  response = Client.new.get_user(user_id: user_id)
30
36
 
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: authsignal-ruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 5.1.0
4
+ version: 5.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - justinsoong
8
8
  bindir: exe
9
9
  cert_chain: []
10
- date: 2025-03-25 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: faraday
@@ -102,9 +102,11 @@ files:
102
102
  - lib/authsignal/api_error.rb
103
103
  - lib/authsignal/client.rb
104
104
  - lib/authsignal/configuration.rb
105
+ - lib/authsignal/invalid_signature_error.rb
105
106
  - lib/authsignal/middleware/json_request.rb
106
107
  - lib/authsignal/middleware/json_response.rb
107
108
  - lib/authsignal/version.rb
109
+ - lib/authsignal/webhook.rb
108
110
  homepage: https://github.com/authsignal/authsignal-ruby
109
111
  licenses:
110
112
  - MIT
@@ -125,7 +127,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
125
127
  - !ruby/object:Gem::Version
126
128
  version: '0'
127
129
  requirements: []
128
- rubygems_version: 3.6.2
130
+ rubygems_version: 3.6.9
129
131
  specification_version: 4
130
132
  summary: The Authsignal ruby server side signal API.
131
133
  test_files: []