identizer 0.1.0 → 0.1.1

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: 76e9316e637b4f310e3bd6a3de54774b7fd22ca365ae04942b0aae0196a218ad
4
- data.tar.gz: 2c99082c990f28cabab4e57139dca3659839df1a3b6297a6f1aa3c42a175ec1d
3
+ metadata.gz: 35ee37820b54d6bbc2d8749adef4f8e464fdc579556019502998db7e75c6b12c
4
+ data.tar.gz: 3fdf1b5c9ef7f9ae6b17d9e817201e885810cf835a5eda89fca703ee716fa344
5
5
  SHA512:
6
- metadata.gz: 71bc913525b42bc3ddad2762cc5dc6f869a694c26cbfb45830a9eb74923631a158b49eba54c95e7ed6e2c26f6507d6cc136af3539f73669357174b7a8c1823e4
7
- data.tar.gz: 31fbca1b65dc8b02de55d4adf1acac07c12f4e59db1a712bdae0bac0da2e3c1b8f38d534eb2d5cb398e891cd49dbc08d192b817a7b75616e5c384ff4d4718f3d
6
+ metadata.gz: 40372939cb3c487b517fc9ff87a0114e93537f5acdf02854f849ec68f42d30dd9ff34dac631060e91ba1abc60c6152d127b6b0b7ffaf30a7b82d1af9e772d213
7
+ data.tar.gz: bc9c93f7492f2947e01a6db13655795bae3557d4d5310c8824259842ef888745703a4dbc9247fd30add059c46d918a32d70789cce9be6f1735dd685ecbdaf043
data/CHANGELOG.md CHANGED
@@ -6,10 +6,20 @@ to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ## [0.1.1] - 2026-07-21
10
+
11
+ ### Fixed
12
+ - Token endpoints now read `code_verifier`, `grant_type`, `refresh_token` and
13
+ `client_id` from a JSON request body, not just form-encoded params. PKCE
14
+ exchanges and refresh-token grants sent as JSON (what the Auth0 SDKs do)
15
+ returned `invalid_grant`.
16
+ - `--password` and `--rs256` are no longer overridden by settings previously
17
+ saved from the web admin; an explicit flag now wins, as documented.
18
+
9
19
  ## [0.1.0] - 2026-06-27
10
20
 
11
21
  First release. A local identity provider for developing and testing auth/SSO
12
- integrations, extracted and decoupled from the tap-v3 SSO emulator.
22
+ integrations.
13
23
 
14
24
  ### OIDC / OAuth2
15
25
  - Authorization-code flow with PKCE (S256/plain), refresh-token grant (rotated,
@@ -44,5 +54,6 @@ integrations, extracted and decoupled from the tap-v3 SSO emulator.
44
54
  enforcement; registered JWT claims protected from directory-attribute forging.
45
55
  - `nokogiri` (SAML) and `net-ldap` (LDAP) load lazily; `sqlite3` is optional.
46
56
 
47
- [Unreleased]: https://github.com/alex-andreiev/identizer/compare/v0.1.0...HEAD
57
+ [Unreleased]: https://github.com/alex-andreiev/identizer/compare/v0.1.1...HEAD
58
+ [0.1.1]: https://github.com/alex-andreiev/identizer/compare/v0.1.0...v0.1.1
48
59
  [0.1.0]: https://github.com/alex-andreiev/identizer/releases/tag/v0.1.0
data/lib/identizer/cli.rb CHANGED
@@ -15,6 +15,7 @@ module Identizer
15
15
  def initialize(argv)
16
16
  @argv = argv
17
17
  @demo = true
18
+ @explicit = [] # settings given as flags; they outrank the persisted ones
18
19
  end
19
20
 
20
21
  def run
@@ -27,7 +28,7 @@ module Identizer
27
28
  # starting the server. Separated out so it can be exercised in tests.
28
29
  def configure(config = Identizer.configuration)
29
30
  parser(config).parse!(@argv)
30
- config.apply_persisted_settings! # web-admin saved password/signing
31
+ config.apply_persisted_settings!(except: @explicit) # web-admin saved password/signing
31
32
  config.seed_identities = [DEMO_USER] if @demo && config.seed_identities.empty?
32
33
  load_sqlite(config) if config.sqlite_path
33
34
  config
@@ -69,11 +70,15 @@ module Identizer
69
70
  opts.on("--tls-key PATH", "TLS private key (PEM)") { |value| config.tls_key_path = value }
70
71
  opts.on("--password PASS", "Shared sign-in password (default 'password')") do |value|
71
72
  config.shared_password = value
73
+ @explicit << :shared_password
72
74
  end
73
75
  opts.on("--sqlite PATH", "Use a SQLite-backed directory at PATH (needs the sqlite3 gem)") do |value|
74
76
  config.sqlite_path = value
75
77
  end
76
- opts.on("--rs256", "Sign id_tokens with RS256 + publish JWKS") { config.signing = :rs256 }
78
+ opts.on("--rs256", "Sign id_tokens with RS256 + publish JWKS") do
79
+ config.signing = :rs256
80
+ @explicit << :signing
81
+ end
77
82
  opts.on("--no-demo", "Don't seed the demo user on first run") { @demo = false }
78
83
  opts.on("--quiet", "Don't log requests") { config.request_logging = false }
79
84
  opts.on("--ldap-port PORT", Integer, "Also start an LDAP listener on PORT") { |value| config.ldap_port = value }
@@ -140,11 +140,12 @@ module Identizer
140
140
  end
141
141
 
142
142
  # Apply settings previously saved from the web admin (password, signing mode).
143
- # Called at boot; explicit flags/config still override afterwards.
144
- def apply_persisted_settings!
143
+ # Called at boot. `except` names the settings given explicitly on the command
144
+ # line — those always win, so a saved value can never shadow a flag.
145
+ def apply_persisted_settings!(except: [])
145
146
  data = JSON.parse(File.read(settings_path))
146
- self.shared_password = data["shared_password"] if data["shared_password"]
147
- self.signing = data["signing"].to_sym if data["signing"]
147
+ self.shared_password = data["shared_password"] if data["shared_password"] && !except.include?(:shared_password)
148
+ self.signing = data["signing"].to_sym if data["signing"] && !except.include?(:signing)
148
149
  self
149
150
  rescue StandardError
150
151
  self
@@ -42,23 +42,18 @@ module Identizer
42
42
  # Consume a one-time authorization code and enforce PKCE when a challenge
43
43
  # was issued — uniformly, so a code can't be redeemed at a different token
44
44
  # endpoint to skip the check. Returns the Authorization, or nil if the code
45
- # is unknown or PKCE verification fails.
45
+ # is unknown or PKCE verification fails. Reads both the code and the
46
+ # verifier from the same merged view, so form- and JSON-encoded token
47
+ # requests behave identically (the Auth0 SDKs POST JSON).
46
48
  def redeem_code(request)
47
- authorization = consume(code_param(request))
49
+ params = merged_params(request)
50
+ authorization = consume(params["code"])
48
51
  return nil if authorization.nil?
49
- return nil unless authorization.pkce_valid?(request.params["code_verifier"])
52
+ return nil unless authorization.pkce_valid?(params["code_verifier"])
50
53
 
51
54
  authorization
52
55
  end
53
56
 
54
- def code_param(request)
55
- if json_request?(request)
56
- parse_json(request)["code"]
57
- else
58
- request.params["code"]
59
- end
60
- end
61
-
62
57
  def bearer(request)
63
58
  request.get_header("HTTP_AUTHORIZATION").to_s.sub(/\ABearer\s+/i, "")
64
59
  end
@@ -6,7 +6,7 @@ module Identizer
6
6
  # discovery and JWKS documents, and the end-session (logout) endpoint.
7
7
  class Oidc < Base
8
8
  def token(request)
9
- case request.params["grant_type"]
9
+ case merged_params(request)["grant_type"]
10
10
  when "refresh_token" then refresh(request)
11
11
  else authorization_code(request)
12
12
  end
@@ -75,7 +75,7 @@ module Identizer
75
75
  end
76
76
 
77
77
  def refresh(request)
78
- authorization = refresh_tokens.take(request.params["refresh_token"]) # single-use, rotated
78
+ authorization = refresh_tokens.take(merged_params(request)["refresh_token"]) # single-use, rotated
79
79
  return json(400, { error: "invalid_grant" }) if authorization.nil?
80
80
 
81
81
  issue(authorization)
@@ -106,7 +106,7 @@ module Identizer
106
106
  def valid_client?(request)
107
107
  return true if config.clients.empty?
108
108
 
109
- config.clients.any? { |client| client[:client_id] == request.params["client_id"] }
109
+ config.clients.any? { |client| client[:client_id] == merged_params(request)["client_id"] }
110
110
  end
111
111
  end
112
112
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Identizer
4
- VERSION = "0.1.0"
4
+ VERSION = "0.1.1"
5
5
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: identizer
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alex Andreiev
8
8
  bindir: exe
9
9
  cert_chain: []
10
- date: 2026-06-27 00:00:00.000000000 Z
10
+ date: 2026-07-21 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: jwt