sqrl-client 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 +4 -4
- data/CHANGELOG.md +35 -1
- data/lib/sqrl/client/agent.rb +16 -7
- data/lib/sqrl/client/conformance/runner.rb +15 -4
- metadata +3 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 8a9db39e917407e067ccc959b250dd36ee6d027177f8e733dd5938729c7be7bd
|
|
4
|
+
data.tar.gz: 5e0949bc3ea41694426a66690c6f76429c92f38e8125c08f14d99d7a0a36fcbf
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 9e712f1fbdca9d1db2ee81bb3a1fd2b0bb2a8594b01140b4ed0f752046db2f7beb08aa75fa15099b3c80b185c90b9b13354b9cc1db20c7c38bc171a7562dc3a6
|
|
7
|
+
data.tar.gz: e2bbb78aa9529c7e35b9dc2085499f98e413651599efc4010b80a33b5a5b4c4f42d0eef565141674099c6a6139f565015dc093247935c88cc4eb0f128e750897
|
data/CHANGELOG.md
CHANGED
|
@@ -1,9 +1,38 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
All notable changes to `sqrl-client` 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
|
+
- After a transient error the agent retries with the fresh nut and stops as soon as two
|
|
16
|
+
successive replies carry the identical TIF, raising `LoginFailed` (reason `:transient`)
|
|
17
|
+
with GRC's "The SQRL login page has expired" message, as Gibson specified
|
|
18
|
+
(grc.sqrl:23543). `max_transient_retries` remains as an upper bound.
|
|
19
|
+
- The conformance runner's `transient_recovery` case accepts both conforming server
|
|
20
|
+
behaviours: recovery on retry, or the identical repeated transient error.
|
|
21
|
+
- Requires sqrl-core 0.1.2.
|
|
22
|
+
|
|
23
|
+
## [0.1.1] - 2026-10-20
|
|
24
|
+
|
|
25
|
+
### Changed
|
|
26
|
+
|
|
27
|
+
- Requires sqrl-core 0.1.1, which fixes the `NoMethodError` on Ruby 3.1 and 3.2. No other
|
|
28
|
+
changes.
|
|
29
|
+
|
|
30
|
+
## [0.1.0] - 2026-10-20
|
|
4
31
|
|
|
5
32
|
First release.
|
|
6
33
|
|
|
34
|
+
### Added
|
|
35
|
+
|
|
7
36
|
- `SQRL::Client::Agent`: login, query, disable, enable, remove against any SQRL site, with
|
|
8
37
|
login-page discovery, previous-identity handling, `ask` and `sin` answering, transient
|
|
9
38
|
retry and CPS handoff on the same cookie jar.
|
|
@@ -15,3 +44,8 @@ First release.
|
|
|
15
44
|
- A 23-case server conformance suite usable from Ruby, RSpec (`it_behaves_like "a SQRL
|
|
16
45
|
server"`) and the command line, with JUnit output.
|
|
17
46
|
- Requires Ruby 3.1+ and `http-cookie`.
|
|
47
|
+
|
|
48
|
+
[Unreleased]: https://github.com/danielpclark/sqrl-ruby/compare/v0.1.2...HEAD
|
|
49
|
+
[0.1.2]: https://github.com/danielpclark/sqrl-ruby/compare/v0.1.1...v0.1.2
|
|
50
|
+
[0.1.1]: https://github.com/danielpclark/sqrl-ruby/compare/v0.1.0...v0.1.1
|
|
51
|
+
[0.1.0]: https://github.com/danielpclark/sqrl-ruby/releases/tag/v0.1.0
|
data/lib/sqrl/client/agent.rb
CHANGED
|
@@ -88,6 +88,9 @@ module SQRL
|
|
|
88
88
|
class Agent
|
|
89
89
|
# Seconds between status polls for non-CPS logins.
|
|
90
90
|
DEFAULT_POLL_INTERVAL = 0.5
|
|
91
|
+
# The message GRC's reference client shows when a login page has gone stale
|
|
92
|
+
# (Gibson, grc.sqrl:21887, 7 Feb 2019).
|
|
93
|
+
TRANSIENT_MESSAGE = "The SQRL login page has expired. Please refresh the page, then log in with SQRL."
|
|
91
94
|
|
|
92
95
|
attr_reader :identity, :transport, :options, :alt_id, :logger
|
|
93
96
|
attr_accessor :cps, :follow_cps, :unknown_site, :ask_handler, :max_transient_retries, :poll, :poll_interval,
|
|
@@ -209,11 +212,10 @@ module SQRL
|
|
|
209
212
|
break unless session.state.transient?
|
|
210
213
|
|
|
211
214
|
transient += 1
|
|
212
|
-
next unless transient > @max_transient_retries
|
|
215
|
+
next unless transient > @max_transient_retries || repeated_error?(ctx)
|
|
213
216
|
|
|
214
|
-
raise LoginFailed.new(
|
|
215
|
-
|
|
216
|
-
state: session.state)
|
|
217
|
+
raise LoginFailed.new(TRANSIENT_MESSAGE, reason: :transient, tif: session.last_response.tif,
|
|
218
|
+
state: session.state)
|
|
217
219
|
end
|
|
218
220
|
|
|
219
221
|
finish(ctx, command)
|
|
@@ -237,10 +239,10 @@ module SQRL
|
|
|
237
239
|
case state.kind
|
|
238
240
|
when :transient
|
|
239
241
|
transient += 1
|
|
240
|
-
next if transient <= @max_transient_retries
|
|
242
|
+
next if transient <= @max_transient_retries && !repeated_error?(ctx)
|
|
241
243
|
|
|
242
|
-
raise LoginFailed.new(
|
|
243
|
-
|
|
244
|
+
raise LoginFailed.new(TRANSIENT_MESSAGE, reason: :transient, tif: session.last_response.tif,
|
|
245
|
+
state: state)
|
|
244
246
|
when :unknown
|
|
245
247
|
next if session.has_previous? && session.try_next_previous
|
|
246
248
|
|
|
@@ -258,6 +260,13 @@ module SQRL
|
|
|
258
260
|
end
|
|
259
261
|
end
|
|
260
262
|
|
|
263
|
+
# "In the case that two successive TIF errors exactly match, the SQRL client MUST abort the
|
|
264
|
+
# transaction and ask the user to please refresh their login page" (Gibson, grc.sqrl:23543,
|
|
265
|
+
# 23 Nov 2019; On The Wire v1.07, "Transient Error Details").
|
|
266
|
+
def repeated_error?(ctx)
|
|
267
|
+
ctx.tifs.length >= 2 && ctx.tifs[-1] == ctx.tifs[-2]
|
|
268
|
+
end
|
|
269
|
+
|
|
261
270
|
def answer_ask(ctx)
|
|
262
271
|
ask = ctx.session.pending_ask
|
|
263
272
|
return unless ask
|
|
@@ -451,15 +451,26 @@ module SQRL
|
|
|
451
451
|
|
|
452
452
|
# ---- robustness --------------------------------------------------------------------
|
|
453
453
|
|
|
454
|
+
# A stale nut must draw a transient error (0x20) with a fresh nut. What happens on the
|
|
455
|
+
# retry depends on the server (On The Wire v1.07, "Transient Error Details"): a server
|
|
456
|
+
# that can tie the stale nut back to its browser session lets the retry succeed; a
|
|
457
|
+
# server that keeps its state by reference answers with exactly the same error, which
|
|
458
|
+
# tells the client to have the user refresh the page. Both are conforming; anything else
|
|
459
|
+
# (a different error, or a "success" nobody's browser can complete) is not.
|
|
454
460
|
def case_transient_recovery(ctx)
|
|
455
461
|
id = identity
|
|
456
462
|
browser = transport
|
|
457
463
|
page = @site.login_page(browser)
|
|
458
464
|
bogus = page.sqrl_url.sub(/nut=[^&]+/, "nut=conformance-stale")
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
465
|
+
begin
|
|
466
|
+
result = agent(id, transport: browser, cps: false, poll: false).login(bogus)
|
|
467
|
+
ctx.transcript.concat(result.transcript)
|
|
468
|
+
check(result.tif_history.first.transient_error?, "the stale nut did not produce a transient error")
|
|
469
|
+
check(result.authenticated?, "login did not recover from the transient error")
|
|
470
|
+
rescue LoginFailed => e
|
|
471
|
+
check(e.reason == :transient && e.tif&.transient_error?,
|
|
472
|
+
"the stale nut did not produce a transient error (#{e.message})")
|
|
473
|
+
end
|
|
463
474
|
end
|
|
464
475
|
|
|
465
476
|
def case_concurrent_logins(ctx)
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: sqrl-client
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.1.
|
|
4
|
+
version: 0.1.2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Daniel P. Clark
|
|
@@ -29,14 +29,14 @@ dependencies:
|
|
|
29
29
|
requirements:
|
|
30
30
|
- - "~>"
|
|
31
31
|
- !ruby/object:Gem::Version
|
|
32
|
-
version: 0.1.
|
|
32
|
+
version: 0.1.2
|
|
33
33
|
type: :runtime
|
|
34
34
|
prerelease: false
|
|
35
35
|
version_requirements: !ruby/object:Gem::Requirement
|
|
36
36
|
requirements:
|
|
37
37
|
- - "~>"
|
|
38
38
|
- !ruby/object:Gem::Version
|
|
39
|
-
version: 0.1.
|
|
39
|
+
version: 0.1.2
|
|
40
40
|
description: Identity management, the full SQRL command set, CPS handoff, login-page
|
|
41
41
|
discovery, a Capybara helper, a CLI and a server conformance suite.
|
|
42
42
|
email:
|