sqrl-rack 0.1.0 → 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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4513d44fc6444b9976a2e286cf6edb442c68a03fd02aede2aebce4c57d8c8b3a
4
- data.tar.gz: 5963d6bf1ce3f90ea6f963d4495e03f23d551c69365d346a42aa4c2ac57e539d
3
+ metadata.gz: 613199a036a2c3b8a43b8c9b8c1baea5507d4da6ae57d10eed72687935b7346f
4
+ data.tar.gz: 69de70f7d37d788c1c33b392cf5346024c0ff531d46056366ba10cfdd0414a94
5
5
  SHA512:
6
- metadata.gz: 80aa33c71ed274a44c315c7a10b9d1292f412a13bc7d966fc9d72b05123b00f58d62b2b2bd186d18abf8b397a9bc3917c3bbf18c8e2153804460e05989b3aaf5
7
- data.tar.gz: 66d970edec43830373ee5954d2753094e286896f3472d1800c365b689e5ab62e9b6c9d0304e6fcb9d4c65913d4c51e6536d50a97890caa65058dc5513c3da933
6
+ metadata.gz: 8119c8222f7f1637a80edcf4c9dcac462836dec4477aaa4be385dce3b29fb43015851aceec11bdade4b04ad30e8ecec6cf195cebc018455d1c8d76aa054ed31d
7
+ data.tar.gz: 4b64f3ac2ec52026ff1deacb7396d15d48b7de759c70d7d8c8e95d5b61b8dee0d23852ac38a4e340726ee742810131f7469ea30af3e6beeeb3d17763df125cb8
data/CHANGELOG.md CHANGED
@@ -1,9 +1,41 @@
1
1
  # Changelog
2
2
 
3
- ## 0.1.0 — 2026-10-20
3
+ All notable changes to `sqrl-rack` are documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this
6
+ project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). Every gem in
7
+ the family shares one version number and is released in lockstep.
8
+
9
+ ## [Unreleased]
10
+
11
+ ## [0.1.2] - 2026-10-21
12
+
13
+ ### Changed
14
+
15
+ - Requires sqrl-core 0.1.2 (protocol conformance fixes and the S4 trailing-byte fix; see its
16
+ changelog).
17
+
18
+ ### Security
19
+
20
+ - A login the SQRL client completed in CPS mode (`opt=cps`) can no longer be completed
21
+ through the browser's status poll or a token-less callback. The specification requires the
22
+ server not to sign in the browser that displayed the login page in that case, because that
23
+ page may be a spoof; only the browser the client redirects to the one-time `url=` token is
24
+ signed in.
25
+
26
+ ## [0.1.1] - 2026-10-20
27
+
28
+ ### Changed
29
+
30
+ - Requires sqrl-core 0.1.1, which fixes the `NoMethodError` on Ruby 3.1 and 3.2. No other
31
+ changes.
32
+
33
+ ## [0.1.0] - 2026-10-20
4
34
 
5
35
  First release.
6
36
 
37
+ ### Added
38
+
7
39
  - `SQRL::Rack::Middleware`: the SQRL endpoint, cookie-bound status poll, CPS and poll
8
40
  callbacks, `sqrl.js` and a refresh endpoint, with a request facade (`env["sqrl.server"]`).
9
41
  - `Sinatra::SQRL` extension and a Roda `plugin :sqrl` with the same helpers.
@@ -14,3 +46,8 @@ First release.
14
46
  - Always issues `sqrl://`; `insecure_http: true` is a loopback-only testing mode.
15
47
  - `poll_requires_ip_match` (off by default) and 429 handling for rate-limit hooks.
16
48
  - Requires Ruby 3.1+, Rack 2.2 or 3.x, `rqrcode`.
49
+
50
+ [Unreleased]: https://github.com/danielpclark/sqrl-ruby/compare/v0.1.2...HEAD
51
+ [0.1.2]: https://github.com/danielpclark/sqrl-ruby/compare/v0.1.1...v0.1.2
52
+ [0.1.1]: https://github.com/danielpclark/sqrl-ruby/compare/v0.1.0...v0.1.1
53
+ [0.1.0]: https://github.com/danielpclark/sqrl-ruby/releases/tag/v0.1.0
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # sqrl-rack
2
2
 
3
- SQRL login for Rack applications and Sinatra: a middleware that mounts the SQRL endpoint,
3
+ SQRL login for Rack applications, Sinatra and Roda: a middleware that mounts the SQRL endpoint,
4
4
  the browser's status poll and the login callback; a Sinatra extension with view helpers;
5
5
  the browser-side `sqrl.js`; and QR code rendering. Built on
6
6
  [`sqrl-core`](../sqrl-core).
@@ -32,9 +32,10 @@ run ->(env) {
32
32
 
33
33
  The middleware serves `POST /sqrl/cli` (the SQRL protocol endpoint), `GET /sqrl/status`
34
34
  (cookie-bound JSON poll), `GET /sqrl/callback` (login completion, with or without a CPS
35
- token) and `GET /sqrl/sqrl.js`. Everything else gets `env["sqrl.server"]`, a
36
- `SQRL::Rack::Facade` with `login_url`, `login_block`, `script_tag`, `qr_svg`,
37
- `identity`, `authenticated?` and `logout!`.
35
+ token), `GET /sqrl/refresh` (a fresh login URL for the page) and `GET /sqrl/sqrl.js`.
36
+ Everything else gets `env["sqrl.server"]`, a `SQRL::Rack::Facade` with `login_url`,
37
+ `login_block`, `script_tag`, `qr_svg`, `refresh_url`, `identity`, `authenticated?` and
38
+ `logout!`.
38
39
 
39
40
  Every `SQRL::Server::Config` option is accepted (`on_unknown_identity`, `ask`, `sin`,
40
41
  `require_ip_match`, `nut_ttl`, `cps_token_ttl`, ...). Without `host:` the request host is
@@ -179,8 +180,9 @@ element dispatches `sqrl:cps-detected`, `sqrl:authenticated` (`detail.next`),
179
180
  5. The middleware stores the identity in the session, runs `on_login`, and redirects to the
180
181
  pending login's `return_to` or `after_login`.
181
182
 
182
- See [`examples/rack-app`](../../examples/rack-app) and
183
- [`examples/sinatra-app`](../../examples/sinatra-app). and [`examples/roda-app`](../../examples/roda-app).
183
+ See [`examples/rack-app`](../../examples/rack-app),
184
+ [`examples/sinatra-app`](../../examples/sinatra-app) and
185
+ [`examples/roda-app`](../../examples/roda-app).
184
186
 
185
187
  ## Testing
186
188
 
@@ -174,8 +174,14 @@ module SQRL
174
174
  Completion.new(identity: identity, pending_login: login, via: via)
175
175
  end
176
176
 
177
- # Whether a pending login may be completed without a CPS token.
177
+ # Whether a pending login may be completed without a CPS token. Never when the SQRL
178
+ # client flagged +cps+: the server then "MUST NOT authenticate the browser session upon
179
+ # successful authentication" (On The Wire v1.07, +url=+); only the browser that presents
180
+ # the one-time token the client received may complete it. Otherwise a spoofed login
181
+ # page that keeps polling would be signed in, which is exactly what CPS exists to stop.
178
182
  def poll_completable?(login)
183
+ return false if login.cps?
184
+
179
185
  !@poll_requires_ip_match || login.ip_matched == true
180
186
  end
181
187
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sqrl-rack
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Daniel P. Clark
@@ -49,14 +49,14 @@ dependencies:
49
49
  requirements:
50
50
  - - "~>"
51
51
  - !ruby/object:Gem::Version
52
- version: 0.1.0
52
+ version: 0.1.2
53
53
  type: :runtime
54
54
  prerelease: false
55
55
  version_requirements: !ruby/object:Gem::Requirement
56
56
  requirements:
57
57
  - - "~>"
58
58
  - !ruby/object:Gem::Version
59
- version: 0.1.0
59
+ version: 0.1.2
60
60
  description: Rack middleware serving the SQRL endpoint, status poll and CPS callback,
61
61
  a Sinatra extension with view helpers, the browser-side script and QR code rendering.
62
62
  email: