standard_id-apple 0.1.1 → 0.1.2
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 +4 -4
- data/lib/standard_id/apple/providers/apple.rb +30 -14
- data/lib/standard_id/apple/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 3c67afb888da7a7a20542d46149eaf86215d02de9c097a757b98223f4c992811
|
|
4
|
+
data.tar.gz: b905edd16718f7fee932b567250a7caa5136d1cf64f82030668b7bcb8dd40d87
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: fdd51606e4a08272c10bae448cecbf0472e8449a5679229013138b5fed0abef6f2e404ef1ef495731a1744c58538fbfc1c141af974ad02c825212a5a51adffc1
|
|
7
|
+
data.tar.gz: 58e35ebc3804fd52719774db5a63229918e0c89462dca2b7f654a8a57820389549044c1ca42e27cf46155afc6617942084e1ce41b650866c9ba0a049e7599289
|
|
@@ -12,40 +12,47 @@ module StandardId
|
|
|
12
12
|
JWKS_URI = "#{ISSUER}/auth/keys".freeze
|
|
13
13
|
DEFAULT_SCOPE = "name email".freeze
|
|
14
14
|
DEFAULT_RESPONSE_MODE = "form_post".freeze
|
|
15
|
+
AUTHORIZATION_PARAM_DEFAULTS = {
|
|
16
|
+
scope: DEFAULT_SCOPE,
|
|
17
|
+
response_mode: DEFAULT_RESPONSE_MODE
|
|
18
|
+
}.freeze
|
|
15
19
|
|
|
16
20
|
class << self
|
|
17
21
|
def provider_name
|
|
18
22
|
"apple"
|
|
19
23
|
end
|
|
20
24
|
|
|
21
|
-
def
|
|
22
|
-
scope
|
|
23
|
-
|
|
25
|
+
def supported_authorization_params
|
|
26
|
+
[:nonce, :scope, :response_mode]
|
|
27
|
+
end
|
|
24
28
|
|
|
29
|
+
def authorization_url(state:, redirect_uri:, **options)
|
|
25
30
|
ensure_basic_credentials!
|
|
26
31
|
|
|
27
32
|
query = {
|
|
28
33
|
client_id: StandardId.config.apple_client_id,
|
|
29
|
-
redirect_uri
|
|
34
|
+
redirect_uri:,
|
|
30
35
|
response_type: "code",
|
|
31
|
-
|
|
32
|
-
response_mode: response_mode,
|
|
33
|
-
state: state
|
|
36
|
+
state:
|
|
34
37
|
}
|
|
35
38
|
|
|
36
|
-
|
|
39
|
+
supported_authorization_params.each do |param|
|
|
40
|
+
query[param] = options[param] || AUTHORIZATION_PARAM_DEFAULTS[param]
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
"#{AUTH_ENDPOINT}?#{URI.encode_www_form(query.compact)}"
|
|
37
44
|
end
|
|
38
45
|
|
|
39
|
-
def get_user_info(code: nil, id_token: nil, access_token: nil, redirect_uri: nil, **options)
|
|
46
|
+
def get_user_info(code: nil, id_token: nil, access_token: nil, redirect_uri: nil, nonce: nil, **options)
|
|
40
47
|
client_id = options[:client_id] || StandardId.config.apple_client_id
|
|
41
48
|
|
|
42
49
|
if id_token.present?
|
|
43
50
|
build_response(
|
|
44
|
-
verify_id_token(id_token: id_token, client_id: client_id),
|
|
51
|
+
verify_id_token(id_token: id_token, client_id: client_id, nonce: nonce),
|
|
45
52
|
tokens: { id_token: id_token }
|
|
46
53
|
)
|
|
47
54
|
elsif code.present?
|
|
48
|
-
exchange_code_for_user_info(code: code, redirect_uri: redirect_uri, client_id: client_id)
|
|
55
|
+
exchange_code_for_user_info(code: code, redirect_uri: redirect_uri, client_id: client_id, nonce: nonce)
|
|
49
56
|
elsif access_token.present?
|
|
50
57
|
raise StandardId::InvalidRequestError, "Access token login flow is not supported for Apple"
|
|
51
58
|
else
|
|
@@ -82,7 +89,7 @@ module StandardId
|
|
|
82
89
|
params.merge(client_id: client_id)
|
|
83
90
|
end
|
|
84
91
|
|
|
85
|
-
def exchange_code_for_user_info(code:, redirect_uri:, client_id: StandardId.config.apple_client_id)
|
|
92
|
+
def exchange_code_for_user_info(code:, redirect_uri:, client_id: StandardId.config.apple_client_id, nonce: nil)
|
|
86
93
|
ensure_full_credentials!(client_id: client_id)
|
|
87
94
|
raise StandardId::InvalidRequestError, "Missing authorization code" if code.blank?
|
|
88
95
|
|
|
@@ -108,7 +115,7 @@ module StandardId
|
|
|
108
115
|
raise StandardId::InvalidRequestError, "Apple response missing id_token" if id_token.blank?
|
|
109
116
|
|
|
110
117
|
tokens = extract_token_payload(parsed_token)
|
|
111
|
-
user_info = verify_id_token(id_token: id_token, client_id: client_id)
|
|
118
|
+
user_info = verify_id_token(id_token: id_token, client_id: client_id, nonce: nonce)
|
|
112
119
|
|
|
113
120
|
build_response(user_info, tokens: tokens)
|
|
114
121
|
rescue StandardError => e
|
|
@@ -117,7 +124,7 @@ module StandardId
|
|
|
117
124
|
raise StandardId::OAuthError, e.message, cause: e
|
|
118
125
|
end
|
|
119
126
|
|
|
120
|
-
def verify_id_token(id_token:, client_id: StandardId.config.apple_client_id)
|
|
127
|
+
def verify_id_token(id_token:, client_id: StandardId.config.apple_client_id, nonce: nil)
|
|
121
128
|
raise StandardId::InvalidRequestError, "Missing id_token" if id_token.blank?
|
|
122
129
|
raise StandardId::InvalidRequestError, "Apple client_id is not configured" if client_id.blank?
|
|
123
130
|
|
|
@@ -137,6 +144,15 @@ module StandardId
|
|
|
137
144
|
verify_aud: true
|
|
138
145
|
)
|
|
139
146
|
|
|
147
|
+
# Validate nonce if provided (web flow with server-generated nonce)
|
|
148
|
+
if nonce.present?
|
|
149
|
+
token_nonce = verified_payload["nonce"]
|
|
150
|
+
if token_nonce != nonce
|
|
151
|
+
raise StandardId::InvalidRequestError,
|
|
152
|
+
"ID token nonce mismatch. Expected: #{nonce}, got: #{token_nonce}"
|
|
153
|
+
end
|
|
154
|
+
end
|
|
155
|
+
|
|
140
156
|
{
|
|
141
157
|
"sub" => verified_payload["sub"],
|
|
142
158
|
"email" => verified_payload["email"],
|