auth-sanitizer 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: 48345c9c15c3bcfefec251d9258d1a949ce27ed13f46a23c1458efffa1a20ebe
4
- data.tar.gz: 55a0935c3ac081f62bf9767f3a1157911dbf5fae71e5f7c669954d3dfeffd842
3
+ metadata.gz: 82404648ebaf0dca9ca6fe3862f28a9a40ecb19a28c40490acede95d4a99b457
4
+ data.tar.gz: 67be7cc8612f8802b948083a02f7970b0cb86832cee7ac0b1827e15364f6c189
5
5
  SHA512:
6
- metadata.gz: fa2206c9f38364d722d6ddc5cb1d52d626c57f37ee681f4c3dd745b3add67720435f8507033eb9fd6d765532b791723946282ed3fa1da70521df53d86300318e
7
- data.tar.gz: 54a1aaa99bf99ffa69079bf000fbc9ab3b995bfda620eb797f488fefd83fa26f1854bd89428ad91ae25d0cc2c3bd38add165002d2833391d2541dead0bd199a6
6
+ metadata.gz: 5e306278d81c5b98b0d2611faf13afa198dec6847207a4f29fecbc0d1b8af55e2b4e917b37bce1a29d5f0f930f60dad979d80b36fd389a89d5703e671142d1cf
7
+ data.tar.gz: 14829bc1a17358726e62948e47b900d9ed02e222c73433f3b65cd98d9131e0202a11b3810b7864175bb82ac3e83303666cbcd80cd085b25a27ddc12c0e0351d9
checksums.yaml.gz.sig CHANGED
Binary file
data/CHANGELOG.md CHANGED
@@ -30,6 +30,17 @@ Please file a bug if you notice a violation of semantic versioning.
30
30
 
31
31
  ### Security
32
32
 
33
+ ## [0.1.1] - 2026-05-15
34
+
35
+ - TAG: [v0.1.1][0.1.1t]
36
+ - COVERAGE: 100.00% -- 134/134 lines in 5 files
37
+ - BRANCH COVERAGE: 100.00% -- 28/28 branches in 5 files
38
+ - 87.50% documented
39
+
40
+ ### Added
41
+
42
+ - Usage documentation in README.md
43
+
33
44
  ## [0.1.0] - 2026-05-15
34
45
 
35
46
  - TAG: [v0.1.0][0.1.0t]
@@ -41,6 +52,8 @@ Please file a bug if you notice a violation of semantic versioning.
41
52
 
42
53
  - Initial release
43
54
 
44
- [Unreleased]: https://github.com//ruby-oauth/auth-sanitizer/compare/v0.1.0...HEAD
55
+ [Unreleased]: https://github.com//ruby-oauth/auth-sanitizer/compare/v0.1.1...HEAD
56
+ [0.1.1]: https://github.com//ruby-oauth/auth-sanitizer/compare/v0.1.0...v0.1.1
57
+ [0.1.1t]: https://github.com//ruby-oauth/auth-sanitizer/releases/tag/v0.1.1
45
58
  [0.1.0]: https://github.com/ruby-oauth/auth-sanitizer/compare/21d6165dca7eef8e7b9bb01fdfc4cc8bab4e5b96...v0.1.0
46
59
  [0.1.0t]: https://github.com/ruby-oauth/auth-sanitizer/releases/tag/v0.1.0
data/README.md CHANGED
@@ -28,6 +28,36 @@ I've summarized my thoughts in [this blog post](https://dev.to/galtzo/hostile-ta
28
28
 
29
29
  ## 🌻 Synopsis
30
30
 
31
+ `auth-sanitizer` provides small, dependency-light helpers for keeping OAuth and authentication secrets out of object
32
+ inspection and log output.
33
+
34
+ The gem is intentionally narrow in scope. It does not change HTTP requests, token objects, persistence, or application
35
+ configuration for you. Instead, it gives host gems and applications two reusable redaction surfaces:
36
+
37
+ - `Auth::Sanitizer::FilteredAttributes` redacts selected instance variables from `#inspect`.
38
+ - `Auth::Sanitizer::SanitizedLogger` wraps an existing logger and redacts sensitive values from string log messages.
39
+
40
+ Out of the box, logger sanitization filters the key names most commonly found in OAuth and OpenID Connect debug output:
41
+
42
+ ```ruby
43
+ Auth::Sanitizer.default_filtered_keys
44
+ # => [
45
+ # "access_token",
46
+ # "refresh_token",
47
+ # "id_token",
48
+ # "client_secret",
49
+ # "assertion",
50
+ # "code_verifier",
51
+ # "token",
52
+ # ]
53
+ ```
54
+
55
+ Redacted values are replaced with `"[FILTERED]"` by default. The replacement label can be changed globally by installing
56
+ a provider, or per logger by passing `label:` to `Auth::Sanitizer::SanitizedLogger.new`.
57
+
58
+ The library snapshots filter configuration when a redacting object is initialized. That keeps already-created objects
59
+ and logger wrappers stable even if a host application changes its configuration later.
60
+
31
61
  ## 💡 Info you can shake a stick at
32
62
 
33
63
  | Tokens to Remember | [![Gem name][⛳️name-img]][⛳️gem-name] [![Gem namespace][⛳️namespace-img]][⛳️gem-namespace] |
@@ -143,8 +173,235 @@ NOTE: Be prepared to track down certs for signed gems and add them the same way
143
173
 
144
174
  ## ⚙️ Configuration
145
175
 
176
+ Most applications can use the defaults. Configuration is available when a host gem or application wants to align
177
+ redaction with its own logging conventions.
178
+
179
+ ### Filtered Label
180
+
181
+ The default replacement label is:
182
+
183
+ ```ruby
184
+ Auth::Sanitizer.filtered_label
185
+ # => "[FILTERED]"
186
+ ```
187
+
188
+ To use a different label globally, install a callable provider:
189
+
190
+ ```ruby
191
+ Auth::Sanitizer.filtered_label_provider = -> { "[REDACTED]" }
192
+ ```
193
+
194
+ The provider is called when a `FilteredAttributes` object or `SanitizedLogger` wrapper is initialized. Existing
195
+ instances keep the label they captured at initialization time:
196
+
197
+ ```ruby
198
+ Auth::Sanitizer.filtered_label_provider = -> { "[FILTERED]" }
199
+ logger = Auth::Sanitizer::SanitizedLogger.new(Logger.new($stdout))
200
+
201
+ Auth::Sanitizer.filtered_label_provider = -> { "[REDACTED]" }
202
+
203
+ # `logger` still uses "[FILTERED]"; new wrappers use "[REDACTED]".
204
+ ```
205
+
206
+ This makes it safe for libraries to delegate the label to host configuration:
207
+
208
+ ```ruby
209
+ Auth::Sanitizer.filtered_label_provider = -> { MyGem.config.filtered_label }
210
+ ```
211
+
212
+ ### Logger Keys
213
+
214
+ `Auth::Sanitizer::SanitizedLogger` defaults to `Auth::Sanitizer.default_filtered_keys`. Pass `filtered_keys:` when your
215
+ application logs additional sensitive fields:
216
+
217
+ ```ruby
218
+ logger = Auth::Sanitizer::SanitizedLogger.new(
219
+ Logger.new($stdout),
220
+ filtered_keys: Auth::Sanitizer.default_filtered_keys + %w[
221
+ api_key
222
+ private_key
223
+ session_secret
224
+ ],
225
+ )
226
+ ```
227
+
228
+ You can also replace the list entirely:
229
+
230
+ ```ruby
231
+ logger = Auth::Sanitizer::SanitizedLogger.new(
232
+ Logger.new($stdout),
233
+ filtered_keys: %w[my_secret],
234
+ label: "[GONE]",
235
+ )
236
+ ```
237
+
238
+ Logger key matching is case-insensitive for supported string formats. The keys are used to redact:
239
+
240
+ - JSON-style pairs, such as `"access_token": "abc123"` and `'client_secret': 'abc123'`
241
+ - query-string and form-encoded pairs, such as `access_token=abc123&scope=read`
242
+ - `Authorization:` header values, regardless of `filtered_keys`
243
+
244
+ Only string payloads are sanitized. Non-string log payloads are delegated unchanged to the wrapped logger.
245
+
246
+ ### Inspect Attributes
247
+
248
+ Classes opt in to inspect redaction by including `Auth::Sanitizer::FilteredAttributes` and declaring the attribute names
249
+ that should be hidden:
250
+
251
+ ```ruby
252
+ class OAuthCredential
253
+ include Auth::Sanitizer::FilteredAttributes
254
+
255
+ attr_reader :access_token, :expires_at
256
+
257
+ filtered_attributes :access_token
258
+
259
+ def initialize(access_token, expires_at)
260
+ @access_token = access_token
261
+ @expires_at = expires_at
262
+ end
263
+ end
264
+ ```
265
+
266
+ Declared names are matched against instance variable names. For example, `filtered_attributes :access_token` redacts
267
+ `@access_token` in `#inspect`.
268
+
269
+ Calling `filtered_attributes` again replaces the class-level list:
270
+
271
+ ```ruby
272
+ OAuthCredential.filtered_attributes(:access_token, :refresh_token)
273
+ OAuthCredential.filtered_attribute_names
274
+ # => [:access_token, :refresh_token]
275
+ ```
276
+
277
+ Passing no attributes clears the class-level list for subsequently initialized objects:
278
+
279
+ ```ruby
280
+ OAuthCredential.filtered_attributes
281
+ OAuthCredential.filtered_attribute_names
282
+ # => []
283
+ ```
284
+
285
+ As with logger wrappers, the per-object filter is captured during initialization. Objects that already exist keep their
286
+ original inspect behavior.
287
+
146
288
  ## 🔧 Basic Usage
147
289
 
290
+ Require the gem:
291
+
292
+ ```ruby
293
+ require "auth/sanitizer"
294
+ ```
295
+
296
+ ### Redact `#inspect`
297
+
298
+ Use `Auth::Sanitizer::FilteredAttributes` for objects that may appear in exception messages, console sessions, or debug
299
+ output through `#inspect`:
300
+
301
+ ```ruby
302
+ class TokenResponse
303
+ include Auth::Sanitizer::FilteredAttributes
304
+
305
+ attr_reader :access_token, :refresh_token, :scope
306
+
307
+ filtered_attributes :access_token, :refresh_token
308
+
309
+ def initialize(access_token:, refresh_token:, scope:)
310
+ @access_token = access_token
311
+ @refresh_token = refresh_token
312
+ @scope = scope
313
+ end
314
+ end
315
+
316
+ response = TokenResponse.new(
317
+ access_token: "access-token-value",
318
+ refresh_token: "refresh-token-value",
319
+ scope: "profile email",
320
+ )
321
+
322
+ response.inspect
323
+ # => #<TokenResponse:123456 @access_token=[FILTERED], @refresh_token=[FILTERED], @scope="profile email">
324
+ ```
325
+
326
+ Only the configured attributes are redacted. Other instance variables remain visible so inspected objects are still
327
+ useful while debugging.
328
+
329
+ ### Redact Logger Output
330
+
331
+ Wrap an existing logger with `Auth::Sanitizer::SanitizedLogger`:
332
+
333
+ ```ruby
334
+ require "logger"
335
+ require "auth/sanitizer"
336
+
337
+ logger = Auth::Sanitizer::SanitizedLogger.new(Logger.new($stdout))
338
+
339
+ logger.debug("access_token=abc123&scope=profile")
340
+ # Logs: access_token=[FILTERED]&scope=profile
341
+
342
+ logger.debug('{"client_secret": "super-secret", "grant_type": "client_credentials"}')
343
+ # Logs: {"client_secret": "[FILTERED]", "grant_type": "client_credentials"}
344
+
345
+ logger.debug("Authorization: Bearer abc123")
346
+ # Logs: Authorization: "[FILTERED]"
347
+ ```
348
+
349
+ The wrapper implements the common Ruby logger methods and sanitizes string values passed through them:
350
+
351
+ ```ruby
352
+ logger.add(Logger::DEBUG, "refresh_token=abc123", "oauth")
353
+ logger << "id_token=abc123"
354
+
355
+ logger.debug { "code_verifier=abc123" }
356
+ logger.info("token=abc123")
357
+ logger.warn("client_secret=abc123")
358
+ logger.error("assertion=abc123")
359
+ logger.fatal("Authorization: Bearer abc123")
360
+ logger.unknown("access_token=abc123")
361
+ ```
362
+
363
+ The wrapper also delegates common logger configuration to the wrapped logger when supported:
364
+
365
+ ```ruby
366
+ logger.level = Logger::WARN
367
+ logger.progname = "my-app"
368
+ logger.formatter = proc { |_severity, _time, _progname, message| "#{message}\n" }
369
+ logger.close
370
+ ```
371
+
372
+ Methods not implemented by the wrapper are delegated to the underlying logger when that logger responds to them.
373
+
374
+ ### Custom Logger Keys
375
+
376
+ Use `filtered_keys:` for application-specific secrets:
377
+
378
+ ```ruby
379
+ logger = Auth::Sanitizer::SanitizedLogger.new(
380
+ Logger.new($stdout),
381
+ filtered_keys: %w[access_token api_key signing_secret],
382
+ label: "[SECRET]",
383
+ )
384
+
385
+ logger.debug("api_key=12345&access_token=abc123")
386
+ # Logs: api_key=[SECRET]&access_token=[SECRET]
387
+ ```
388
+
389
+ `filtered_keys:` applies to JSON-style, query-string, and form-encoded key/value pairs. `Authorization:` headers are
390
+ always redacted by `SanitizedLogger`, even if `Authorization` is not listed as a filtered key.
391
+
392
+ ### Important Limits
393
+
394
+ `auth-sanitizer` is a logging and inspection helper, not a complete secret-management system.
395
+
396
+ - It redacts supported string patterns before delegating to a logger.
397
+ - It does not mutate source hashes, token objects, HTTP requests, or HTTP responses.
398
+ - It does not recursively sanitize arbitrary Ruby objects passed to a logger as non-string payloads.
399
+ - It cannot protect secrets that are logged through a different logger, printed directly, or interpolated into an
400
+ unsupported format.
401
+
402
+ For best results, wrap the logger as close as possible to the code that emits authentication debug output, and avoid
403
+ logging raw token structures unless they pass through the sanitizer first.
404
+
148
405
  ## 🦷 FLOSS Funding
149
406
 
150
407
  While ruby-oauth tools are free software and will always be, the project would benefit immensely from some funding.
data/REEK CHANGED
@@ -1,2 +1 @@
1
- Error: No such file - is
2
- Error: No such file - empty
1
+ reek is empty
@@ -3,7 +3,7 @@
3
3
  module Auth
4
4
  module Sanitizer
5
5
  module Version
6
- VERSION = "0.1.0"
6
+ VERSION = "0.1.1"
7
7
  end
8
8
  VERSION = Version::VERSION # Traditional Constant Location
9
9
  end
data.tar.gz.sig CHANGED
Binary file
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: auth-sanitizer
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
  - Peter H. Boling
@@ -249,10 +249,10 @@ licenses:
249
249
  - MIT
250
250
  metadata:
251
251
  homepage_uri: https://auth-sanitizer.galtzo.com/
252
- source_code_uri: https://github.com/ruby-oauth/auth-sanitizer/tree/v0.1.0
253
- changelog_uri: https://github.com/ruby-oauth/auth-sanitizer/blob/v0.1.0/CHANGELOG.md
252
+ source_code_uri: https://github.com/ruby-oauth/auth-sanitizer/tree/v0.1.1
253
+ changelog_uri: https://github.com/ruby-oauth/auth-sanitizer/blob/v0.1.1/CHANGELOG.md
254
254
  bug_tracker_uri: https://github.com/ruby-oauth/auth-sanitizer/issues
255
- documentation_uri: https://www.rubydoc.info/gems/auth-sanitizer/0.1.0
255
+ documentation_uri: https://www.rubydoc.info/gems/auth-sanitizer/0.1.1
256
256
  funding_uri: https://github.com/sponsors/pboling
257
257
  wiki_uri: https://github.com/ruby-oauth/auth-sanitizer/wiki
258
258
  news_uri: https://www.railsbling.com/tags/auth-sanitizer
metadata.gz.sig CHANGED
Binary file