omniauth-apple 1.2.2 → 1.3.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: 81a5350ae8be48914ee324f8586b5d58f83927467bc87106cab846e028e38beb
4
- data.tar.gz: 42db86865c9120c95e7326359e3ac02dd58dbd28bfe84c7fc0bbb002488b0a1b
3
+ metadata.gz: b0a0049edf786737a4acc4af68aeff8b8323a020822dfd530a01c0f8925cc1f1
4
+ data.tar.gz: 44d8cf583c85cb198f6dd5a9f7e593d5109335a78cc01ec7b32feaa69b449df0
5
5
  SHA512:
6
- metadata.gz: 18a1bf098d7687ed17df039b9b2f4b0a388f0d6858a4a54aa8c94a7233622f7cb1d4485a38d870ae430f873aadaaee8d9d1b42c9f8a91545c0bdb10c4cffbe11
7
- data.tar.gz: f53179d2a247e0fd2559614fece6b3b734579d756be44c1b4c40ab9c6911479e38dc7f74800dcc59b36b09749656bb93aff6c8eeccc422238e95667049064b63
6
+ metadata.gz: ecc115718bb19ab99e6b15c05432b19ae73499a8b76f98e05e5cb0b45d61b61549a283709180d0df60b188e3c5db789a5d4c0cfe79d147014ca798df5ecc511a
7
+ data.tar.gz: eaa439dee2483186d09f0aa24e6e653118ca37545f01d074c098366c24daa8b355c8e24df1e0138e0fcd93efa0946a7ae9141c21e6cee7c3629941dbe59b2a65
data/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  ## [Unreleased]
2
2
 
3
+ ## [1.2.2] - 2022-10-31
4
+
5
+ ### Fixed
6
+
7
+ - [#94](https://github.com/nhosoya/omniauth-apple/pull/98) handle fail! in correct way
8
+
3
9
  ## [1.2.1] - 2022-10-25
4
10
 
5
11
  ### Fixed
@@ -1,5 +1,5 @@
1
1
  module OmniAuth
2
2
  module Apple
3
- VERSION = "1.2.2"
3
+ VERSION = '1.3.0'
4
4
  end
5
5
  end
@@ -1,21 +1,17 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'omniauth-oauth2'
4
- require 'net/https'
4
+ require 'json/jwt'
5
5
 
6
6
  module OmniAuth
7
7
  module Strategies
8
8
  class Apple < OmniAuth::Strategies::OAuth2
9
- class JWTFetchingFailed < CallbackError
10
- def initialize(error_reason = nil, error_uri = nil)
11
- super :jwks_fetching_failed, error_reason, error_uri
12
- end
13
- end
9
+ ISSUER = 'https://appleid.apple.com'
14
10
 
15
11
  option :name, 'apple'
16
12
 
17
13
  option :client_options,
18
- site: 'https://appleid.apple.com',
14
+ site: ISSUER,
19
15
  authorize_url: '/auth/authorize',
20
16
  token_url: '/auth/token',
21
17
  auth_scheme: :request_body
@@ -24,13 +20,13 @@ module OmniAuth
24
20
  scope: 'email name'
25
21
  option :authorized_client_ids, []
26
22
 
27
- uid { id_info['sub'] }
23
+ uid { id_info[:sub] }
28
24
 
29
25
  # Documentation on parameters
30
26
  # https://developer.apple.com/documentation/sign_in_with_apple/sign_in_with_apple_rest_api/authenticating_users_with_sign_in_with_apple
31
27
  info do
32
28
  prune!(
33
- sub: id_info['sub'],
29
+ sub: id_info[:sub],
34
30
  email: email,
35
31
  first_name: first_name,
36
32
  last_name: last_name,
@@ -41,8 +37,8 @@ module OmniAuth
41
37
  end
42
38
 
43
39
  extra do
44
- id_token = request.params['id_token'] || access_token&.params&.dig('id_token')
45
- prune!(raw_info: {id_info: id_info, user_info: user_info, id_token: id_token})
40
+ id_token_str = request.params['id_token'] || access_token&.params&.dig('id_token')
41
+ prune!(raw_info: {id_info: id_info, user_info: user_info, id_token: id_token_str})
46
42
  end
47
43
 
48
44
  def client
@@ -50,12 +46,12 @@ module OmniAuth
50
46
  end
51
47
 
52
48
  def email_verified
53
- value = id_info['email_verified']
49
+ value = id_info[:email_verified]
54
50
  value == true || value == "true"
55
51
  end
56
52
 
57
53
  def is_private_email
58
- value = id_info['is_private_email']
54
+ value = id_info[:is_private_email]
59
55
  value == true || value == "true"
60
56
  end
61
57
 
@@ -79,54 +75,68 @@ module OmniAuth
79
75
 
80
76
  def id_info
81
77
  @id_info ||= if request.params&.key?('id_token') || access_token&.params&.key?('id_token')
82
- id_token = request.params['id_token'] || access_token.params['id_token']
83
- if (verification_key = fetch_jwks)
84
- jwt_options = {
85
- verify_iss: true,
86
- iss: 'https://appleid.apple.com',
87
- verify_iat: true,
88
- verify_aud: true,
89
- aud: [options.client_id].concat(options.authorized_client_ids),
90
- algorithms: ['RS256'],
91
- jwks: verification_key
92
- }
93
- payload, _header = ::JWT.decode(id_token, nil, true, jwt_options)
94
- verify_nonce!(payload)
95
- payload
96
- else
97
- {}
98
- end
78
+ id_token_str = request.params['id_token'] || access_token.params['id_token']
79
+ id_token = JSON::JWT.decode(id_token_str, :skip_verification)
80
+ verify_id_token! id_token
81
+ id_token
99
82
  end
100
83
  end
101
84
 
102
- def fetch_jwks
103
- conn = Faraday.new(headers: {user_agent: 'ruby/omniauth-apple'}) do |c|
104
- c.response :json, parser_options: { symbolize_names: true }
105
- c.adapter Faraday.default_adapter
106
- end
107
- res = conn.get 'https://appleid.apple.com/auth/keys'
108
- if res.success?
109
- res.body
110
- else
111
- raise JWTFetchingFailed.new('HTTP Error when fetching JWKs')
112
- end
113
- rescue JWTFetchingFailed, Faraday::Error => e
114
- fail!(:jwks_fetching_failed, e) and nil
85
+ def verify_id_token!(id_token)
86
+ jwk = fetch_jwk! id_token.kid
87
+ verify_signature! id_token, jwk
88
+ verify_claims! id_token
89
+ end
90
+
91
+ def fetch_jwk!(kid)
92
+ JSON::JWK::Set::Fetcher.fetch File.join(ISSUER, 'auth/keys'), kid: kid
93
+ rescue => e
94
+ raise CallbackError.new(:jwks_fetching_failed, e)
95
+ end
96
+
97
+ def verify_signature!(id_token, jwk)
98
+ id_token.verify! jwk
99
+ rescue => e
100
+ raise CallbackError.new(:id_token_signature_invalid, e)
101
+ end
102
+
103
+ def verify_claims!(id_token)
104
+ verify_iss!(id_token)
105
+ verify_aud!(id_token)
106
+ verify_iat!(id_token)
107
+ verify_exp!(id_token)
108
+ verify_nonce!(id_token) if id_token[:nonce_supported]
109
+ end
110
+
111
+ def verify_iss!(id_token)
112
+ invalid_claim! :iss unless id_token[:iss] == ISSUER
115
113
  end
116
114
 
117
- def verify_nonce!(payload)
118
- return unless payload['nonce_supported']
115
+ def verify_aud!(id_token)
116
+ invalid_claim! :aud unless [options.client_id].concat(options.authorized_client_ids).include?(id_token[:aud])
117
+ end
119
118
 
120
- return if payload['nonce'] && payload['nonce'] == stored_nonce
119
+ def verify_iat!(id_token)
120
+ invalid_claim! :iat unless id_token[:iat] <= Time.now.to_i
121
+ end
121
122
 
122
- fail!(:nonce_mismatch, CallbackError.new(:nonce_mismatch, 'nonce mismatch'))
123
+ def verify_exp!(id_token)
124
+ invalid_claim! :exp unless id_token[:exp] >= Time.now.to_i
125
+ end
126
+
127
+ def verify_nonce!(id_token)
128
+ invalid_claim! :nonce unless id_token[:nonce] && id_token[:nonce] == stored_nonce
129
+ end
130
+
131
+ def invalid_claim!(claim)
132
+ raise CallbackError.new(:id_token_claims_invalid, "#{claim} invalid")
123
133
  end
124
134
 
125
135
  def client_id
126
136
  @client_id ||= if id_info.nil?
127
137
  options.client_id
128
138
  else
129
- id_info['aud'] if options.authorized_client_ids.include? id_info['aud']
139
+ id_info[:aud] if options.authorized_client_ids.include? id_info[:aud]
130
140
  end
131
141
  end
132
142
 
@@ -138,7 +148,7 @@ module OmniAuth
138
148
  end
139
149
 
140
150
  def email
141
- id_info['email']
151
+ id_info[:email]
142
152
  end
143
153
 
144
154
  def first_name
@@ -157,16 +167,15 @@ module OmniAuth
157
167
  end
158
168
 
159
169
  def client_secret
160
- payload = {
170
+ jwt = JSON::JWT.new(
161
171
  iss: options.team_id,
162
- aud: 'https://appleid.apple.com',
172
+ aud: ISSUER,
163
173
  sub: client_id,
164
- iat: Time.now.to_i,
165
- exp: Time.now.to_i + 60
166
- }
167
- headers = { kid: options.key_id }
168
-
169
- ::JWT.encode(payload, private_key, 'ES256', headers)
174
+ iat: Time.now,
175
+ exp: Time.now + 60
176
+ )
177
+ jwt.kid = options.key_id
178
+ jwt.sign(private_key).to_s
170
179
  end
171
180
 
172
181
  def private_key
@@ -37,7 +37,7 @@ Gem::Specification.new do |spec|
37
37
  spec.require_paths = ["lib"]
38
38
 
39
39
  spec.add_dependency 'omniauth-oauth2'
40
- spec.add_dependency 'jwt'
40
+ spec.add_dependency 'json-jwt'
41
41
  spec.add_development_dependency "bundler", "~> 2.0"
42
42
  spec.add_development_dependency "rake", "~> 13.0"
43
43
  spec.add_development_dependency "rspec", "~> 3.9"
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: omniauth-apple
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.2
4
+ version: 1.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - nhosoya
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: exe
11
11
  cert_chain: []
12
- date: 2022-10-31 00:00:00.000000000 Z
12
+ date: 2023-01-17 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: omniauth-oauth2
@@ -26,7 +26,7 @@ dependencies:
26
26
  - !ruby/object:Gem::Version
27
27
  version: '0'
28
28
  - !ruby/object:Gem::Dependency
29
- name: jwt
29
+ name: json-jwt
30
30
  requirement: !ruby/object:Gem::Requirement
31
31
  requirements:
32
32
  - - ">="
@@ -150,7 +150,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
150
150
  - !ruby/object:Gem::Version
151
151
  version: '0'
152
152
  requirements: []
153
- rubygems_version: 3.3.7
153
+ rubygems_version: 3.3.26
154
154
  signing_key:
155
155
  specification_version: 4
156
156
  summary: OmniAuth strategy for Sign In with Apple