Skip to content

oidc-authn-plugin: per-issuer typ/aud/clock-skew-leeway validation#3

Merged
diffora merged 8 commits into
mainfrom
oidc-authn-per-issuer-validation
Jun 19, 2026
Merged

oidc-authn-plugin: per-issuer typ/aud/clock-skew-leeway validation#3
diffora merged 8 commits into
mainfrom
oidc-authn-per-issuer-validation

Conversation

@diffora

@diffora diffora commented Jun 13, 2026

Copy link
Copy Markdown
Owner

Summary

Adds per-issuer JWT validation policy to oidc-authn-plugin. Each trusted issuer can now pin its own:

  • required JOSE typ header,
  • accepted aud audience(s),
  • clock-skew leeway,

instead of a single global policy applied to every issuer. This lets one plugin instance trust multiple issuers with distinct, tighter rules — e.g. accept long-lived tokens from a general-purpose IdP while requiring a specific token type and audience (and a narrower clock skew) from a second, stricter issuer.

What changed

  • Config (TrustedIssuerInput): new #[serde(default)] fields expected_audience, jose_typ, clock_skew_leeway_secs, validated at load (non-empty/trimmed/lowercased typ; leeway ≤ 300s; audience patterns compiled). Backward-compatible — when a field is unset, the issuer falls back to the existing global policy.
  • Validator: resolves the matched issuer's overrides and applies them — typ enforced case-insensitively (a missing header fails closed when a typ is pinned); leeway applied only to exp/nbf/iat; issuer policy is keyed on the verified iss (re-checked post-signature, so one issuer's policy can never apply to another).
  • Fail-closed audience: a non-empty per-issuer expected_audience now requires the aud claim to be present, rather than depending on the separate global require_audience flag. A token from a pinned issuer that omits aud is rejected.

Tests

Per-issuer matrix: typ accepted (case-insensitive) / wrong-typ / missing-typ-header rejected; per-issuer audience rejects the global audience, accepts its own, accepts an array aud member, and rejects a missing aud even with the global flag off; an issuer without overrides falls back to the global policy and rejects another issuer's audience; leeway wider-accepts / narrower-rejects at the boundary; config fail-fast (blank typ, leeway > 300, bad pattern); deserialization round-trip.

cargo test -p cf-gears-oidc-authn-plugin — all green; clippy clean.

🤖 Generated with Claude Code

Summary by CodeRabbit

Release Notes

  • New Features
    • Added per-issuer JWT validation configuration: specify expected audience patterns, required token type, and clock skew tolerance for each trusted issuer.
    • Enhanced error handling for token type validation failures with dedicated metrics tracking.

asmith987 and others added 6 commits June 11, 2026 11:17
Signed-off-by: Andre Smith <andre.smith+oss@acronis.com>
Signed-off-by: Fluid <fluidcells@pm.me>
Signed-off-by: Andre Smith <andre.smith+oss@acronis.com>
chore: bump the Rust version to 1.96.0
…sdk-canonical-projection

refactor(type-registry): adopt SDK canonical-projection pattern
…sdk-canonical-projection

refactor(resource-group): adopt SDK canonical-projection pattern
@coderabbitai

coderabbitai Bot commented Jun 13, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@diffora, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 55 minutes and 42 seconds. Learn how PR review limits work.

Your organization has used up its prepaid credits, and credit purchases are no longer available. Enable the review add-on in the billing tab to keep reviews running — you're only billed for reviews past your plan's rate limits ($0.25/file).

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: c42ac228-21dd-427d-9532-e64775f75675

📥 Commits

Reviewing files that changed from the base of the PR and between 38a39b1 and e07f8d1.

⛔ Files ignored due to path filters (2)
  • Cargo.lock is excluded by !**/*.lock
  • tools/dylint_lints/Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (121)
  • .github/workflows/ci.yml
  • gears/credstore/credstore/Cargo.toml
  • gears/credstore/credstore/src/domain/error.rs
  • gears/credstore/credstore/src/domain/error_tests.rs
  • gears/credstore/credstore/src/domain/service_tests.rs
  • gears/mini-chat/mini-chat/src/gts/permissions.rs
  • gears/system/account-management/account-management/src/domain/bootstrap/service.rs
  • gears/system/account-management/account-management/src/domain/bootstrap/service_tests.rs
  • gears/system/account-management/account-management/src/domain/gts_validation.rs
  • gears/system/account-management/account-management/src/domain/gts_validation_tests.rs
  • gears/system/account-management/account-management/src/domain/tenant/service/mod.rs
  • gears/system/account-management/account-management/src/domain/tenant/service/service_tests.rs
  • gears/system/account-management/account-management/src/domain/user/service.rs
  • gears/system/account-management/account-management/src/domain/user/service_tests.rs
  • gears/system/account-management/account-management/src/domain/user_groups/cascade.rs
  • gears/system/account-management/account-management/src/domain/user_groups/cascade_tests.rs
  • gears/system/account-management/account-management/src/domain/user_groups/registration.rs
  • gears/system/account-management/account-management/src/domain/user_groups/registration_tests.rs
  • gears/system/account-management/account-management/src/gear.rs
  • gears/system/account-management/account-management/src/gear_tests.rs
  • gears/system/account-management/account-management/src/infra/rg/checker_tests.rs
  • gears/system/account-management/account-management/src/infra/rg/test_helpers.rs
  • gears/system/account-management/account-management/src/infra/types_registry/checker.rs
  • gears/system/account-management/account-management/src/infra/types_registry/checker_tests.rs
  • gears/system/account-management/account-management/src/infra/types_registry/metadata_schema_registry.rs
  • gears/system/account-management/account-management/src/infra/types_registry/test_helpers.rs
  • gears/system/account-management/account-management/src/tr_plugin/tests.rs
  • gears/system/account-management/plugins/static-idp-plugin/Cargo.toml
  • gears/system/account-management/plugins/static-idp-plugin/src/gear.rs
  • gears/system/authn-resolver/authn-resolver/Cargo.toml
  • gears/system/authn-resolver/authn-resolver/src/domain/error.rs
  • gears/system/authn-resolver/plugins/oidc-authn-plugin/benches/jwt_validation.rs
  • gears/system/authn-resolver/plugins/oidc-authn-plugin/benches/s2s_exchange.rs
  • gears/system/authn-resolver/plugins/oidc-authn-plugin/src/config.rs
  • gears/system/authn-resolver/plugins/oidc-authn-plugin/src/domain/authenticate_tests.rs
  • gears/system/authn-resolver/plugins/oidc-authn-plugin/src/domain/error.rs
  • gears/system/authn-resolver/plugins/oidc-authn-plugin/src/domain/error_tests.rs
  • gears/system/authn-resolver/plugins/oidc-authn-plugin/src/domain/metrics.rs
  • gears/system/authn-resolver/plugins/oidc-authn-plugin/src/domain/metrics/definitions.rs
  • gears/system/authn-resolver/plugins/oidc-authn-plugin/src/domain/validator.rs
  • gears/system/authn-resolver/plugins/oidc-authn-plugin/src/domain/validator_tests.rs
  • gears/system/authn-resolver/plugins/oidc-authn-plugin/src/infra/token_client_tests.rs
  • gears/system/authn-resolver/plugins/oidc-authn-plugin/src/test_support/test_fixtures.rs
  • gears/system/authn-resolver/plugins/oidc-authn-plugin/tests/common/mod.rs
  • gears/system/authz-resolver/authz-resolver/Cargo.toml
  • gears/system/authz-resolver/authz-resolver/src/domain/error.rs
  • gears/system/oagw/oagw/src/infra/type_provisioning.rs
  • gears/system/resource-group/resource-group-sdk/Cargo.toml
  • gears/system/resource-group/resource-group-sdk/src/api.rs
  • gears/system/resource-group/resource-group-sdk/src/error.rs
  • gears/system/resource-group/resource-group-sdk/src/error_tests.rs
  • gears/system/resource-group/resource-group-sdk/src/field.rs
  • gears/system/resource-group/resource-group-sdk/src/gts.rs
  • gears/system/resource-group/resource-group-sdk/src/lib.rs
  • gears/system/resource-group/resource-group-sdk/src/precondition.rs
  • gears/system/resource-group/resource-group-sdk/src/reason.rs
  • gears/system/resource-group/resource-group/Cargo.toml
  • gears/system/resource-group/resource-group/src/api/rest/error.rs
  • gears/system/resource-group/resource-group/src/domain/error.rs
  • gears/system/resource-group/resource-group/src/domain/read_service.rs
  • gears/system/resource-group/resource-group/src/domain/rg_service.rs
  • gears/system/resource-group/resource-group/src/domain/validation.rs
  • gears/system/resource-group/resource-group/tests/common/mod.rs
  • gears/system/resource-group/resource-group/tests/domain_unit_test.rs
  • gears/system/tenant-resolver/plugins/rg-tr-plugin/Cargo.toml
  • gears/system/tenant-resolver/plugins/rg-tr-plugin/src/domain/service.rs
  • gears/system/tenant-resolver/plugins/rg-tr-plugin/src/domain/service_tests.rs
  • gears/system/tenant-resolver/tenant-resolver/Cargo.toml
  • gears/system/tenant-resolver/tenant-resolver/src/domain/error.rs
  • gears/system/types-registry/types-registry-sdk/Cargo.toml
  • gears/system/types-registry/types-registry-sdk/src/api.rs
  • gears/system/types-registry/types-registry-sdk/src/error.rs
  • gears/system/types-registry/types-registry-sdk/src/error_tests.rs
  • gears/system/types-registry/types-registry-sdk/src/field.rs
  • gears/system/types-registry/types-registry-sdk/src/gts.rs
  • gears/system/types-registry/types-registry-sdk/src/lib.rs
  • gears/system/types-registry/types-registry-sdk/src/models.rs
  • gears/system/types-registry/types-registry-sdk/src/models_tests.rs
  • gears/system/types-registry/types-registry-sdk/src/precondition.rs
  • gears/system/types-registry/types-registry-sdk/src/testing.rs
  • gears/system/types-registry/types-registry/src/api/rest/error.rs
  • gears/system/types-registry/types-registry/src/domain/error.rs
  • gears/system/types-registry/types-registry/src/domain/local_client.rs
  • gears/system/types-registry/types-registry/src/domain/local_client_tests.rs
  • gears/system/types-registry/types-registry/src/domain/service.rs
  • libs/rustls-fips-shim/Cargo.toml
  • libs/toolkit-db/tests/ui/fail/unscoped_query_execution.stderr
  • libs/toolkit-odata-macros/tests/ui/fail/string_op_on_int_field.stderr
  • rust-toolchain.toml
  • tools/dylint_lints/Cargo.toml
  • tools/dylint_lints/de01_contract_layer/de0101_no_serde_in_contract/src/lib.rs
  • tools/dylint_lints/de01_contract_layer/de0102_no_toschema_in_contract/src/lib.rs
  • tools/dylint_lints/de01_contract_layer/de0103_no_http_types_in_contract/src/lib.rs
  • tools/dylint_lints/de01_contract_layer/de0104_no_api_dto_in_contract/src/lib.rs
  • tools/dylint_lints/de01_contract_layer/de0110_no_schema_for_on_gts_structs/src/lib.rs
  • tools/dylint_lints/de02_api_layer/de0201_dtos_only_in_api_rest/src/lib.rs
  • tools/dylint_lints/de02_api_layer/de0202_dtos_not_referenced_outside_api/src/lib.rs
  • tools/dylint_lints/de02_api_layer/de0203_dtos_must_use_api_dto/src/lib.rs
  • tools/dylint_lints/de02_api_layer/de0204_dtos_must_have_toschema_derive/src/lib.rs
  • tools/dylint_lints/de02_api_layer/de0205_operation_builder/src/lib.rs
  • tools/dylint_lints/de03_domain_layer/de0301_no_infra_in_domain/src/lib.rs
  • tools/dylint_lints/de03_domain_layer/de0308_no_http_in_domain/src/lib.rs
  • tools/dylint_lints/de03_domain_layer/de0309_must_have_domain_model/src/lib.rs
  • tools/dylint_lints/de05_client_layer/de0503_plugin_client_suffix/src/lib.rs
  • tools/dylint_lints/de05_client_layer/de0504_client_versioning/src/lib.rs
  • tools/dylint_lints/de07_security/de0706_no_direct_sqlx/src/lib.rs
  • tools/dylint_lints/de07_security/de0707_drop_zeroize/src/lib.rs
  • tools/dylint_lints/de07_security/de0708_no_non_fips_hasher/src/lib.rs
  • tools/dylint_lints/de08_rest_api_conventions/de0801_api_endpoint_version/src/lib.rs
  • tools/dylint_lints/de08_rest_api_conventions/de0802_use_odata_ext/src/lib.rs
  • tools/dylint_lints/de08_rest_api_conventions/de0803_api_snake_case/src/lib.rs
  • tools/dylint_lints/de09_gts_layer/de0901_gts_string_pattern/src/lib.rs
  • tools/dylint_lints/de09_gts_layer/de0902_no_schema_for_on_gts_structs/src/lib.rs
  • tools/dylint_lints/de11_testing/de1101_tests_in_separate_files/src/lib.rs
  • tools/dylint_lints/de12_documentation/de1201_docs_rs_all_features/src/lib.rs
  • tools/dylint_lints/de13_common_patterns/de1301_no_print_macros/src/lib.rs
  • tools/dylint_lints/de13_common_patterns/de1302_error_from_to_string/src/lib.rs
  • tools/dylint_lints/de13_common_patterns/de1303_no_primitive_type_alias/src/lib.rs
  • tools/dylint_lints/lint_utils/Cargo.toml
  • tools/dylint_lints/lint_utils/src/lib.rs
  • tools/dylint_lints/rust-toolchain.toml
📝 Walkthrough

Walkthrough

The OIDC AuthN plugin now supports per-issuer JWT validation overrides. Configuration is extended with expected audience patterns, required JOSE typ headers, and per-issuer clock-skew leeway. The JWT validator uses a new ResolvedIssuer type to apply these overrides during token validation, replacing global-only settings when configured per issuer.

Changes

Per-Issuer JWT Validation Overrides

Layer / File(s) Summary
Configuration schema and per-issuer override parsing
src/config.rs
New ResolvedIssuer struct encapsulates discovery base plus per-issuer overrides. TrustedIssuerInput schema extended with expected_audience, jose_typ, and clock_skew_leeway_secs fields. IssuerRuleCompiled parses and validates overrides at compile time; IssuerTrustConfig::resolve_issuer returns the complete ResolvedIssuer. Test helpers and fixtures updated to populate new fields with defaults.
JWT validator refactored for per-issuer overrides
src/domain/validator.rs
validate_inner resolves issuer to ResolvedIssuer and applies per-issuer overrides: enforces issuer-pinned jose_typ (case-insensitive), computes effective clock-skew leeway from issuer override or global config, derives expected audience from issuer-specific or global. Audience requirement now fails closed when either global audience is required or issuer pins an audience.
Error handling and metrics
src/domain/error.rs, src/domain/metrics/definitions.rs, src/domain/error_tests.rs
New AuthNError::InvalidTokenType variant for JOSE typ mismatch, mapped to Unauthorized gateway error. New TOKEN_REJECTION_REASON_INVALID_TYP metric constant tracks typ validation failures.
JWT signing test helpers and fixtures
src/test_support/test_fixtures.rs, src/domain/validator_tests.rs
New sign_jwt_with_typ and sign_jwt_without_typ helpers control JOSE typ header in test tokens. Test trust builders updated to populate override fields with explicit defaults.
Comprehensive per-issuer override behavior tests
src/domain/validator_tests.rs
New test suites verify jose_typ enforcement (case-insensitive matching, missing header rejection, ignored when unconfigured), per-issuer audience precedence over global (including required-aud when pinned), and per-issuer leeway widening/narrowing acceptance windows.
Benchmark and integration test updates
benches/jwt_validation.rs, benches/s2s_exchange.rs, src/infra/token_client_tests.rs, tests/common/mod.rs
All test configurations updated to explicitly set new TrustedIssuerInput override fields to defaults (empty Vec and None), reflecting the schema change.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Poem

🐰 I hop through config lines with glee,

Per-issuer rules now set token decree,
Typ and audience, leeway in tow,
Validators learn each issuer's flow,
Tests flutter in a joyous show.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The pull request title accurately summarizes the main change: adding per-issuer typ/aud/clock-skew-leeway validation to the oidc-authn-plugin, which is the core feature introduced across all modified files.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch oidc-authn-per-issuer-validation

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@diffora
diffora force-pushed the oidc-authn-per-issuer-validation branch from 2cfb500 to 38a39b1 Compare June 13, 2026 19:01

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
gears/system/authn-resolver/plugins/oidc-authn-plugin/src/test_support/test_fixtures.rs (1)

83-89: ⚡ Quick win

Fail fast in test token signing helpers instead of returning an empty token.

Line 88 and Line 101 currently swallow JWT encoding errors via unwrap_or_default(), which can mask the true failure source in downstream validator tests. In test fixtures, panic-on-failure is usually better for diagnosis.

Suggested patch
 pub fn sign_jwt_with_typ(claims: &serde_json::Value, kid: Option<&str>, typ: &str) -> String {
     use jsonwebtoken::{Header, encode};
     let mut header = Header::new(Algorithm::RS256);
     header.kid = kid.map(str::to_owned);
     header.typ = Some(typ.to_owned());
-    encode(&header, claims, &key_material().encoding_key).unwrap_or_default()
+    encode(&header, claims, &key_material().encoding_key)
+        .unwrap_or_else(|error| panic!("test JWT encoding should succeed: {error}"))
 }
@@
 pub fn sign_jwt_without_typ(claims: &serde_json::Value, kid: Option<&str>) -> String {
     use jsonwebtoken::{Header, encode};
     let mut header = Header::new(Algorithm::RS256);
     header.kid = kid.map(str::to_owned);
     header.typ = None;
-    encode(&header, claims, &key_material().encoding_key).unwrap_or_default()
+    encode(&header, claims, &key_material().encoding_key)
+        .unwrap_or_else(|error| panic!("test JWT encoding should succeed: {error}"))
 }

Also applies to: 96-102

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@gears/system/authn-resolver/plugins/oidc-authn-plugin/src/test_support/test_fixtures.rs`
around lines 83 - 89, The test JWT helpers currently swallow encoding errors by
calling encode(...).unwrap_or_default(), which masks failures; in the
sign_jwt_with_typ function (and any other test signing helpers in this file that
call encode(...).unwrap_or_default()) replace unwrap_or_default() with a
panic-on-failure such as expect("failed to encode test JWT") or unwrap() so test
failures surface immediately, keeping header.kid and header.typ handling
unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In
`@gears/system/authn-resolver/plugins/oidc-authn-plugin/src/test_support/test_fixtures.rs`:
- Around line 83-89: The test JWT helpers currently swallow encoding errors by
calling encode(...).unwrap_or_default(), which masks failures; in the
sign_jwt_with_typ function (and any other test signing helpers in this file that
call encode(...).unwrap_or_default()) replace unwrap_or_default() with a
panic-on-failure such as expect("failed to encode test JWT") or unwrap() so test
failures surface immediately, keeping header.kid and header.typ handling
unchanged.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 3c6b6350-6e3a-4be2-a3ce-b7730e93b345

📥 Commits

Reviewing files that changed from the base of the PR and between 2cfb500 and 38a39b1.

📒 Files selected for processing (12)
  • gears/system/authn-resolver/plugins/oidc-authn-plugin/benches/jwt_validation.rs
  • gears/system/authn-resolver/plugins/oidc-authn-plugin/benches/s2s_exchange.rs
  • gears/system/authn-resolver/plugins/oidc-authn-plugin/src/config.rs
  • gears/system/authn-resolver/plugins/oidc-authn-plugin/src/domain/error.rs
  • gears/system/authn-resolver/plugins/oidc-authn-plugin/src/domain/error_tests.rs
  • gears/system/authn-resolver/plugins/oidc-authn-plugin/src/domain/metrics.rs
  • gears/system/authn-resolver/plugins/oidc-authn-plugin/src/domain/metrics/definitions.rs
  • gears/system/authn-resolver/plugins/oidc-authn-plugin/src/domain/validator.rs
  • gears/system/authn-resolver/plugins/oidc-authn-plugin/src/domain/validator_tests.rs
  • gears/system/authn-resolver/plugins/oidc-authn-plugin/src/infra/token_client_tests.rs
  • gears/system/authn-resolver/plugins/oidc-authn-plugin/src/test_support/test_fixtures.rs
  • gears/system/authn-resolver/plugins/oidc-authn-plugin/tests/common/mod.rs
✅ Files skipped from review due to trivial changes (2)
  • gears/system/authn-resolver/plugins/oidc-authn-plugin/src/domain/metrics/definitions.rs
  • gears/system/authn-resolver/plugins/oidc-authn-plugin/src/domain/metrics.rs
🚧 Files skipped from review as they are similar to previous changes (9)
  • gears/system/authn-resolver/plugins/oidc-authn-plugin/benches/s2s_exchange.rs
  • gears/system/authn-resolver/plugins/oidc-authn-plugin/tests/common/mod.rs
  • gears/system/authn-resolver/plugins/oidc-authn-plugin/benches/jwt_validation.rs
  • gears/system/authn-resolver/plugins/oidc-authn-plugin/src/infra/token_client_tests.rs
  • gears/system/authn-resolver/plugins/oidc-authn-plugin/src/domain/error.rs
  • gears/system/authn-resolver/plugins/oidc-authn-plugin/src/domain/error_tests.rs
  • gears/system/authn-resolver/plugins/oidc-authn-plugin/src/domain/validator.rs
  • gears/system/authn-resolver/plugins/oidc-authn-plugin/src/domain/validator_tests.rs
  • gears/system/authn-resolver/plugins/oidc-authn-plugin/src/config.rs

@diffora
diffora force-pushed the oidc-authn-per-issuer-validation branch from 38a39b1 to 1dbea54 Compare June 13, 2026 19:17
Add optional per-issuer expected_audience, jose_typ, and
clock_skew_leeway_secs overrides on TrustedIssuerInput; enforce them in
the JWT validator (typ checked case-insensitively, per-issuer audience
replaces the global list when set, per-issuer leeway overrides global).
Issuers without overrides keep existing behavior.

Signed-off-by: Diffora <ddiffora@gmail.com>
@diffora
diffora force-pushed the oidc-authn-per-issuer-validation branch 2 times, most recently from d294ecd to 868647c Compare June 13, 2026 21:27
…igration

Add #[serde(flatten)] extra to JwtClaims so claim mapping can read non-standard claims (e.g. cap tokens' subject_tenant/scopes) by name instead of dropping them at deserialize.

Signed-off-by: Diffora <ddiffora@gmail.com>
@diffora
diffora force-pushed the oidc-authn-per-issuer-validation branch from 868647c to e07f8d1 Compare June 13, 2026 21:28
@diffora
diffora merged commit 46f2e8f into main Jun 19, 2026
24 checks passed
diffora pushed a commit that referenced this pull request Jul 16, 2026
- Security (major): the multipart report-part callback now validates the
  caller-supplied part size against the token's authoritative
  claims.multipart.size (the exact per-part size from compute_plan) and persists
  that value, so a holder of the signed token can no longer forge part sizes and
  corrupt the completed version.size. Test: report_part_rejects_forged_size.
- finalize: drop the redundant second SHA-256 — reuse the already-verified
  hash_value (verify_content_hash only returns Ok on an exact match).
- IdempotencyRepo::insert takes the IdempotencyInsert struct instead of 6
  positional args (removes the too_many_arguments allow).
- policy_service: extract a shared authorize_admin_or_owner helper (dedup the
  ADMIN_POLICY-first / owner-check logic).
- mark the test-only expires_at mutators #[doc(hidden)] with a "test-support
  only" note (a Cargo test-support feature was rejected: it would break/skip the
  default `cargo test` since external integration-test crates call them).

Retention-rule 404 mislabel (CodeRabbit #3) was already fixed by the Tier 3
RetentionRuleNotFound change.

Signed-off-by: Roland From <rfedorov@linkentools.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants