standard_singpass 0.6.0 → 0.7.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: 2ea89fcd5571a503ae9bec3dcc4c69f038e8109e68c3dfba9a119eb08efdf392
4
- data.tar.gz: 43c8d9ee1f0344de72f0b6bffa181d0df12475c9f10c5ee6d80f92e9bd192a05
3
+ metadata.gz: 35e2fb1210199ace98e5db77de85e6a3650ee9297bffd8f8a0f2d16f743cba8e
4
+ data.tar.gz: 594ff25cfe621eb103dc397889b91a21cb49316b23ba6b2e849d42f5046a5a33
5
5
  SHA512:
6
- metadata.gz: b8a3c50ad2b135eef0d4ecea3d979b21f1b223a54966114544f08aa1ce78fad0d25779e28f365c8ff57c87ae1ec03836ab1290624e11d0de3c0dbc862324d884
7
- data.tar.gz: c335087baa92503937ed273d6a5528bac1310ac2636a7e529e7f9619e4414b6ce64245142760899544327b4e8138fdbaebde31205e8f7cbd44ed91aa68bfa250
6
+ metadata.gz: '008b3123acb642f298caf073931dfd5778645dea026cdd3baf99045d4cb46caa74834d77cee80861042dee89d8a454d58717f39c20dc3bd2746c319716157726'
7
+ data.tar.gz: d93185d6bb749e2413d8181f35b6383863fa95afe78642c4d6548b92bcf7f441fc8d9a0ba0a440e6f7c954883ffc4736b2684025e68b6cf4dceaae37c65882ac
data/CHANGELOG.md CHANGED
@@ -7,6 +7,17 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.7.0] - 2026-10-25
11
+
12
+ ### Changed
13
+
14
+ - **`get_person_data` now requires a `nonce` by default.** Passing `nonce: nil` (or omitting it) raises
15
+ `StandardSingpass::Myinfo::ConfigurationError` with a clear message. The nonce binds the id_token to
16
+ the session and prevents replay attacks; PKCE + DPoP substantially raise the bar but do not fully close
17
+ the replay window without it. The only consumer, `fundbright-web`, already passes the nonce from the
18
+ session on every call, so it is unaffected. To opt out for flows where no nonce was included in the PAR
19
+ request, pass `skip_nonce_validation: true` — this is intentionally verbose so it stands out in review.
20
+
10
21
  ## [0.6.0] - 2026-10-22
11
22
 
12
23
  ### Changed
@@ -101,10 +101,19 @@ module StandardSingpass
101
101
  "#{@authorize_url}?#{URI.encode_www_form(params)}"
102
102
  end
103
103
 
104
- sig { params(auth_code: String, code_verifier: String, dpop_key_pair: OpenSSL::PKey::EC, nonce: T.nilable(String)).returns(T::Hash[Symbol, T.untyped]) }
105
- def get_person_data(auth_code:, code_verifier:, dpop_key_pair:, nonce: nil)
104
+ sig { params(auth_code: String, code_verifier: String, dpop_key_pair: OpenSSL::PKey::EC, nonce: T.nilable(String), skip_nonce_validation: T::Boolean).returns(T::Hash[Symbol, T.untyped]) }
105
+ def get_person_data(auth_code:, code_verifier:, dpop_key_pair:, nonce: nil, skip_nonce_validation: false)
106
+ unless skip_nonce_validation
107
+ if nonce.blank?
108
+ raise ConfigurationError,
109
+ "nonce is required for id_token replay protection. " \
110
+ "Pass the nonce you sent in the PAR request. " \
111
+ "Only pass skip_nonce_validation: true for flows where no nonce was sent in the PAR request."
112
+ end
113
+ end
114
+
106
115
  token_data = exchange_token(auth_code:, code_verifier:, dpop_key_pair:)
107
- id_token_payload = validate_id_token(token_data[:id_token], nonce:)
116
+ id_token_payload = validate_id_token(token_data[:id_token], nonce: skip_nonce_validation ? nil : nonce)
108
117
 
109
118
  person_data = fetch_userinfo(access_token: token_data[:access_token], dpop_key_pair:)
110
119
 
@@ -1,3 +1,3 @@
1
1
  module StandardSingpass
2
- VERSION = "0.6.0"
2
+ VERSION = "0.7.0"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: standard_singpass
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.0
4
+ version: 0.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jaryl Sim