aws-cognito-srp 0.3.0.1 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 180b657b77c00d5651c02440ac1c269fcf0ff0c0cfed35deb13224ea225585dc
4
- data.tar.gz: 776b06f5fced0c6c96d0fbc3a02810f11273ebc4e28e00199108dac461774cfd
3
+ metadata.gz: 929d703154eb252230b0ec365cf85bb59e632e62a335bcf63d81c0168f6fe3d3
4
+ data.tar.gz: 2b857f9bcf58f8363eae7ad056de998758bfaf6458ca478d41e4398b57d34a11
5
5
  SHA512:
6
- metadata.gz: 56237ee2ed291d3a0a636f75ca9be3762444e8e18b989b75505d9d8a1c67ec1e3574e275ea83fb0b4d2fd873c524297a6280d03ffd93e19f88ddaaadef24f38b
7
- data.tar.gz: de22d3f26a0e34adab3acafc37e8822601565aaef64bfeff9a39a29d69dfc67784421f5dc1458c8424cf78930bf92bf6ee7c0ae2c888e4f03bd8718b2a347520
6
+ metadata.gz: 5763f4fac8412527c21ecfb3ae0e283e4cf7be33fc5eadbc94325c83b1b0aa91d34cfc86ebad7895c9f1e1fad93e8c7f8f0f08180f4219d4f78e1ff63d9cf0c1
7
+ data.tar.gz: 13e4d566a91689460b4aca21d48b73a3655d336dfc3e07e0e8c505b107606489581b720d045c72e0ebc2aea27d59a79c76eeba5cb3be77965818b69cb259f10d
@@ -7,14 +7,15 @@ jobs:
7
7
  strategy:
8
8
  fail-fast: false
9
9
  matrix:
10
- ruby: [2.3, 2.4, 2.5, 2.6, 2.7, '3.0']
10
+ os: [ubuntu-latest, macos-latest]
11
+ ruby: [2.4, 2.5, 2.6, 2.7, '3.0', 3.1, 3.2, jruby, truffleruby]
11
12
 
12
- runs-on: ubuntu-latest
13
+ runs-on: ${{ matrix.os }}
13
14
 
14
- name: Test against Ruby ${{ matrix.ruby }}
15
+ name: Test against ${{ matrix.ruby }} on ${{ matrix.os }}
15
16
 
16
17
  steps:
17
- - uses: actions/checkout@v2
18
+ - uses: actions/checkout@v3
18
19
  - name: Set up Ruby
19
20
  uses: ruby/setup-ruby@v1
20
21
  with:
data/CHANGELOG.md CHANGED
@@ -1,5 +1,13 @@
1
1
  ## Changelog for aws-cognito-srp-ruby
2
2
 
3
+ ### 0.5.0 (February 14❤︎, 2023)
4
+
5
+ * Added support for `client_secret`
6
+
7
+ ### 0.4.0 (October 1, 2021)
8
+
9
+ * Added `refresh_tokens` method
10
+
3
11
  ### 0.3.0 (September 29, 2021)
4
12
 
5
13
  * Added support for Ruby 2.4 and 2.3
data/README.md CHANGED
@@ -25,11 +25,12 @@ gem 'aws-cognito-srp'
25
25
  require "aws-cognito-srp"
26
26
 
27
27
  aws_srp = Aws::CognitoSrp.new(
28
- username: "username",
29
- password: "password",
30
- pool_id: "pool-id",
31
- client_id: "client-id",
32
- aws_client: Aws::CognitoIdentityProvider::Client.new(region: "aws-region")
28
+ username: "username",
29
+ password: "password",
30
+ pool_id: "pool-id",
31
+ client_id: "client-id",
32
+ client_secret: "client-secret", # Optional
33
+ aws_client: Aws::CognitoIdentityProvider::Client.new(region: "aws-region")
33
34
  )
34
35
 
35
36
  resp = aws_srp.authenticate
@@ -38,11 +39,29 @@ resp = aws_srp.authenticate
38
39
  resp.id_token
39
40
  resp.access_token
40
41
  resp.refresh_token
42
+
43
+ # A few hours later ... ⌛️
44
+
45
+ new_tokens = aws_srp.refresh_tokens(resp.refresh_token)
46
+ ```
47
+
48
+ In case you need access to the `USER_ID_FOR_SRP` value from the auth response,
49
+ you can do so by calling `aws_srp.user_id_for_srp` *after* the initial auth
50
+ (`aws_srp` being the same as in the code example above).
51
+
52
+ If you're using a `client_secret` and calling `#refresh_tokens` in a different
53
+ instance than the one that performed the initial call to `#authenticate` you
54
+ will have to pass the `USER_ID_FOR_SRP` value as a keyword argument:
55
+
56
+ ```ruby
57
+ new_tokens = aws_srp.refresh_token(resp.refresh_token,
58
+ user_id_for_srp: your_user_id_for_srp)
41
59
  ```
42
60
 
43
61
  ## Supported rubies
44
62
 
45
- This gem is tested against and supports Ruby 2.3, 2.4, 2.5, 2.6, 2.7 and 3.0.
63
+ This gem is tested against and supports Ruby 2.4 through 3.2, JRuby and
64
+ TruffleRuby.
46
65
 
47
66
  ## Development
48
67
 
@@ -20,11 +20,13 @@ Gem::Specification.new do |spec|
20
20
  end
21
21
  spec.require_paths = ["lib"]
22
22
 
23
+ spec.required_ruby_version = '>= 2.4.0'
24
+
23
25
  spec.add_dependency "aws-sdk-cognitoidentityprovider"
24
26
 
25
- spec.add_development_dependency "bundler", "~> 2.2.0"
27
+ spec.add_development_dependency "bundler", "~> 2.2"
26
28
  spec.add_development_dependency "rake", "~> 13.0"
27
- spec.add_development_dependency "ox", "~> 2.14.0"
29
+ spec.add_development_dependency "nokogiri", "~> 1.9"
28
30
  spec.add_development_dependency "rspec", "~> 3.0"
29
31
  spec.add_development_dependency "pry"
30
32
 
@@ -2,9 +2,6 @@
2
2
 
3
3
  module Aws
4
4
  class CognitoSrp
5
- VERSION = "0.3.0.1"
6
- # ^
7
- # NOTE: the fourth version number is just temporary to reflect an update to
8
- # the gemspec (with no functional changes), remove it in next version bump
5
+ VERSION = "0.5.0"
9
6
  end
10
7
  end
@@ -24,19 +24,6 @@ if Gem::Version.new(RUBY_VERSION) < Gem::Version.new("2.5")
24
24
  using IntegerWithPow
25
25
  end
26
26
 
27
- if Gem::Version.new(RUBY_VERSION) < Gem::Version.new("2.4")
28
- module StringWithUnpack1
29
- refine String do
30
- # String#unpack1 was introduced in Ruby 2.4
31
- def unpack1(fmt)
32
- unpack(fmt)[0]
33
- end
34
- end
35
- end
36
-
37
- using StringWithUnpack1
38
- end
39
-
40
27
  module Aws
41
28
  # Client for AWS Cognito Identity Provider using Secure Remote Password (SRP).
42
29
  #
@@ -59,9 +46,10 @@ module Aws
59
46
  # aws_srp.authenticate
60
47
  #
61
48
  class CognitoSrp
62
- USER_SRP_AUTH = "USER_SRP_AUTH"
63
- PASSWORD_VERIFIER = "PASSWORD_VERIFIER"
64
49
  NEW_PASSWORD_REQUIRED = "NEW_PASSWORD_REQUIRED"
50
+ PASSWORD_VERIFIER = "PASSWORD_VERIFIER"
51
+ REFRESH_TOKEN = "REFRESH_TOKEN"
52
+ USER_SRP_AUTH = "USER_SRP_AUTH"
65
53
 
66
54
  N_HEX = %w(
67
55
  FFFFFFFF FFFFFFFF C90FDAA2 2168C234 C4C6628B 80DC1CD1 29024E08
@@ -84,12 +72,15 @@ module Aws
84
72
 
85
73
  INFO_BITS = 'Caldera Derived Key'
86
74
 
87
- def initialize(username:, password:, pool_id:, client_id:, aws_client:)
75
+ attr_reader :user_id_for_srp
76
+
77
+ def initialize(username:, password:, pool_id:, client_id:, aws_client:, client_secret: nil)
88
78
  @username = username
89
79
  @password = password
90
80
  @pool_id = pool_id
91
81
  @client_id = client_id
92
82
  @aws_client = aws_client
83
+ @client_secret = client_secret
93
84
 
94
85
  @big_n = hex_to_long(N_HEX)
95
86
  @g = hex_to_long(G_HEX)
@@ -99,13 +90,16 @@ module Aws
99
90
  end
100
91
 
101
92
  def authenticate
93
+ auth_parameters = {
94
+ USERNAME: @username,
95
+ SRP_A: long_to_hex(@large_a_value),
96
+ SECRET_HASH: @client_secret && secret_hash(@username)
97
+ }.compact
98
+
102
99
  init_auth_response = @aws_client.initiate_auth(
103
100
  client_id: @client_id,
104
101
  auth_flow: USER_SRP_AUTH,
105
- auth_parameters: {
106
- USERNAME: @username,
107
- SRP_A: long_to_hex(@large_a_value)
108
- }
102
+ auth_parameters: auth_parameters
109
103
  )
110
104
 
111
105
  unless init_auth_response.challenge_name == PASSWORD_VERIFIER
@@ -113,12 +107,15 @@ module Aws
113
107
  end
114
108
 
115
109
  challenge_response = process_challenge(init_auth_response.challenge_parameters)
110
+ hash = @client_secret && secret_hash(@user_id_for_srp)
116
111
 
117
- auth_response = @aws_client.respond_to_auth_challenge(
112
+ params = {
118
113
  client_id: @client_id,
119
114
  challenge_name: PASSWORD_VERIFIER,
120
- challenge_responses: challenge_response
121
- )
115
+ challenge_responses: challenge_response.merge(SECRET_HASH: hash).compact
116
+ }
117
+
118
+ auth_response = @aws_client.respond_to_auth_challenge(params)
122
119
 
123
120
  if auth_response.challenge_name == NEW_PASSWORD_REQUIRED
124
121
  raise NewPasswordRequired, "Cognito responded to password verifier with a #{NEW_PASSWORD_REQUIRED} challenge"
@@ -127,6 +124,22 @@ module Aws
127
124
  auth_response.authentication_result
128
125
  end
129
126
 
127
+ def refresh_tokens(refresh_token, user_id_for_srp: @user_id_for_srp)
128
+ auth_parameters = {
129
+ REFRESH_TOKEN: refresh_token,
130
+ SECRET_HASH: @client_secret && secret_hash(user_id_for_srp)
131
+ }.compact
132
+
133
+ resp = @aws_client.initiate_auth(
134
+ client_id: @client_id,
135
+ auth_flow: REFRESH_TOKEN,
136
+ auth_parameters: auth_parameters
137
+ )
138
+
139
+ resp.authentication_result
140
+ end
141
+ alias_method :refresh, :refresh_tokens
142
+
130
143
  private
131
144
 
132
145
  def generate_random_small_a
@@ -156,22 +169,22 @@ module Aws
156
169
  end
157
170
 
158
171
  def process_challenge(challenge_parameters)
159
- user_id_for_srp = challenge_parameters.fetch("USER_ID_FOR_SRP")
172
+ @user_id_for_srp = challenge_parameters.fetch("USER_ID_FOR_SRP")
160
173
  salt_hex = challenge_parameters.fetch("SALT")
161
174
  srp_b_hex = challenge_parameters.fetch("SRP_B")
162
175
  secret_block_b64 = challenge_parameters.fetch("SECRET_BLOCK")
163
176
 
164
177
  timestamp = ::Time.now.utc.strftime("%a %b %-d %H:%M:%S %Z %Y")
165
178
 
166
- hkdf = get_password_authentication_key(user_id_for_srp, @password, srp_b_hex.to_i(16), salt_hex)
179
+ hkdf = get_password_authentication_key(@user_id_for_srp, @password, srp_b_hex.to_i(16), salt_hex)
167
180
  secret_block_bytes = ::Base64.strict_decode64(secret_block_b64)
168
- msg = @pool_id.split("_")[1] + user_id_for_srp + secret_block_bytes + timestamp
181
+ msg = @pool_id.split("_")[1] + @user_id_for_srp + secret_block_bytes + timestamp
169
182
  hmac_digest = ::OpenSSL::HMAC.digest(::OpenSSL::Digest::SHA256.new, hkdf, msg)
170
183
  signature_string = ::Base64.strict_encode64(hmac_digest).force_encoding('utf-8')
171
184
 
172
185
  {
173
186
  TIMESTAMP: timestamp,
174
- USERNAME: user_id_for_srp,
187
+ USERNAME: @user_id_for_srp,
175
188
  PASSWORD_CLAIM_SECRET_BLOCK: secret_block_b64,
176
189
  PASSWORD_CLAIM_SIGNATURE: signature_string
177
190
  }
@@ -228,5 +241,9 @@ module Aws
228
241
  u_hex_hash = hex_hash(pad_hex(big_a) + pad_hex(big_b))
229
242
  hex_to_long(u_hex_hash)
230
243
  end
244
+
245
+ def secret_hash(username)
246
+ Base64.strict_encode64(OpenSSL::HMAC.digest('sha256', @client_secret, username + @client_id))
247
+ end
231
248
  end
232
249
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: aws-cognito-srp
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0.1
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jonathan Viney
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2021-10-01 00:00:00.000000000 Z
13
+ date: 2023-02-14 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: aws-sdk-cognitoidentityprovider
@@ -32,14 +32,14 @@ dependencies:
32
32
  requirements:
33
33
  - - "~>"
34
34
  - !ruby/object:Gem::Version
35
- version: 2.2.0
35
+ version: '2.2'
36
36
  type: :development
37
37
  prerelease: false
38
38
  version_requirements: !ruby/object:Gem::Requirement
39
39
  requirements:
40
40
  - - "~>"
41
41
  - !ruby/object:Gem::Version
42
- version: 2.2.0
42
+ version: '2.2'
43
43
  - !ruby/object:Gem::Dependency
44
44
  name: rake
45
45
  requirement: !ruby/object:Gem::Requirement
@@ -55,19 +55,19 @@ dependencies:
55
55
  - !ruby/object:Gem::Version
56
56
  version: '13.0'
57
57
  - !ruby/object:Gem::Dependency
58
- name: ox
58
+ name: nokogiri
59
59
  requirement: !ruby/object:Gem::Requirement
60
60
  requirements:
61
61
  - - "~>"
62
62
  - !ruby/object:Gem::Version
63
- version: 2.14.0
63
+ version: '1.9'
64
64
  type: :development
65
65
  prerelease: false
66
66
  version_requirements: !ruby/object:Gem::Requirement
67
67
  requirements:
68
68
  - - "~>"
69
69
  - !ruby/object:Gem::Version
70
- version: 2.14.0
70
+ version: '1.9'
71
71
  - !ruby/object:Gem::Dependency
72
72
  name: rspec
73
73
  requirement: !ruby/object:Gem::Requirement
@@ -132,14 +132,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
132
132
  requirements:
133
133
  - - ">="
134
134
  - !ruby/object:Gem::Version
135
- version: '0'
135
+ version: 2.4.0
136
136
  required_rubygems_version: !ruby/object:Gem::Requirement
137
137
  requirements:
138
138
  - - ">="
139
139
  - !ruby/object:Gem::Version
140
140
  version: '0'
141
141
  requirements: []
142
- rubygems_version: 3.2.3
142
+ rubygems_version: 3.3.3
143
143
  signing_key:
144
144
  specification_version: 4
145
145
  summary: AWS Cognito SRP auth for Ruby