Skip to content

Server SAML Auth. Declare configs, constants and metadata.#5415

Open
zibet27 wants to merge 4 commits intomainfrom
zibet27/server-auth-saml-core
Open

Server SAML Auth. Declare configs, constants and metadata.#5415
zibet27 wants to merge 4 commits intomainfrom
zibet27/server-auth-saml-core

Conversation

@zibet27
Copy link
Copy Markdown
Collaborator

@zibet27 zibet27 commented Mar 3, 2026

Subsystem
Server Auth

Motivation
KTOR-601 SAML Support
Chunk of #5392

Solution

This PR adds a new ktor-server-auth-saml module that provides SAML 2.0 SSO support for Ktor server applications. This is the foundational layer - it introduces configs, constants, and metadata parsing without the actual authentication flow yet.

What's included:

Configuration

  • SP/IdP metadata configuration
  • Single Logout (SLO) support toggle
  • HTTP binding selection (Redirect/POST)
  • Security settings: clock skew, signature requirements, algorithm allowlists
  • Protection against IdP-initiated SSO and open redirects via RelayState validation
  • ForceAuthn, NameID format, and AuthnContext options

Type-safe Constants
NameIdFormat - email, persistent, transient, etc.
SignatureAlgorithm - RSA/ECDSA with SHA-256/384/512
DigestAlgorithm - SHA-256/384/512
SamlBinding - HTTP-Redirect and HTTP-POST
SamlAuthnContext - Password, MFA, Kerberos, X509

Metadata Handling

  • SamlSpMetadata - SP configuration with signing/encryption credentials, contacts, organization info
  • IdPMetadata - parsed IdP metadata with SSO/SLO endpoints and signing certs
  • parseSamlIdpMetadata() - parses IdP XML with cert expiration validation

Security
SamlReplayCache interface + InMemorySamlReplayCache - replay attack protection
Algorithm allowlisting to prevent downgrade attacks
Certificate expiration warnings

Principal Model
SamlCredential - unverified credential during auth flow
SamlPrincipal - verified principal with NameID, sessionIndex, attributes

What's next:
The actual authentication provider, AuthnRequest generation, response validation, and SLO handling will come in follow-up commits.

Summary by CodeRabbit

  • New Features

    • SAML authentication for Ktor Server: configurable SP/IdP metadata, bindings, algorithms, single logout, and credential handling.
    • Built-in replay protection and secure SAML XML parsing/one-time initializer.
  • Tests

    • Unit tests for replay cache, initializer idempotency, XML parsing (including XXE protection), and configuration parsing.
  • Chores

    • Added new server auth SAML plugin module.

@zibet27 zibet27 requested review from bjhham, e5l and osipxd March 3, 2026 11:13
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Mar 3, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds a new Ktor Server SAML authentication plugin: OpenSAML dependency and repository, build wiring, implementation and public API for SAML (constants, config DSL, metadata parsing, initializer with secure parser pool, crypto helpers, replay cache, utils) and unit tests.

Changes

Cohort / File(s) Summary
Build & Dependency Configuration
build-settings-logic/src/main/kotlin/ktorsettings.dependency-resolution-management.settings.gradle.kts, gradle/libs.versions.toml, ktor-server/ktor-server-plugins/ktor-server-auth-saml/build.gradle.kts, settings.gradle.kts
Adds Shibboleth/OpenSAML Maven repo and OpenSAML 5.x version entries; wires API/impl/runtime OpenSAML dependencies, logging/test libs, and registers new ktor-server-auth-saml module.
Public API Manifest
ktor-server/ktor-server-plugins/ktor-server-auth-saml/api/ktor-server-auth-saml.api
Declares the plugin public API surface (types, classes, functions) exposed by the implementation.
Initialization & Parsing
.../LibSaml.kt
Introduces thread-safe LibSaml singleton with idempotent initialization and an XXE-protected BasicParserPool; throws InitializationException on failures.
Constants & Algorithms
.../SamlConstants.kt
Adds NameIdFormat, SignatureAlgorithm, DigestAlgorithm, SamlBinding, SamlAlgorithms, and SamlAuthnContext value/classes and recommended sets.
Configuration DSL
.../SamlConfig.kt
Adds SamlConfig DSL (extends AuthenticationProvider.Config) with SP/IdP metadata hooks, algorithm/flag properties, replay cache, validate/challenge hooks and SamlChallengeContext.
Metadata Models & Parsing
.../SamlMetadata.kt
Adds SamlSpMetadata builder, SamlContactPerson, IdPMetadata model, parseSamlIdpMetadata(xml) with certificate extraction/validation and binding-specific URL resolution.
Credential & Principal Wrappers
.../SamlPrincipal.kt
Adds SamlCredential and SamlPrincipal exposing assertion/response, nameId, sessionIndex, and attribute accessors (lazy attributes map).
Crypto / Key Handling
.../SamlSecurity.kt
Adds SamlCrypto helper and loadCredential(...) to build BasicX509Credential from keystore; includes internal supportsDecryption check.
Replay Protection
.../SamlReplayCache.kt
Adds SamlReplayCache interface and InMemorySamlReplayCache: mutex-protected map, TTL eviction, background cleanup, bounded-size eviction and tryRecordAssertion semantics.
Utilities
.../SamlUtils.kt
Adds Element.unmarshall() extension using OpenSAML unmarshaller registry with descriptive error when missing.
Tests
.../jvm/test/io/ktor/server/auth/saml/*
Adds unit tests: InMemorySamlReplayCacheTest, SamlConfigTest, LibSamlTest covering cache behavior, config defaults/parse, LibSaml init, parser behavior and XXE protection.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant KtorAuth as Ktor SAML Auth
    participant LibSaml as LibSaml/OpenSAML
    participant Cache as SamlReplayCache
    participant Keystore as KeyStore/Credentials
    participant IdP as IdentityProvider

    Client->>KtorAuth: Submit SAML Response / initiate SSO
    KtorAuth->>LibSaml: ensureInitialized() / parse SAML XML
    LibSaml-->>KtorAuth: XMLObject (Assertion)
    KtorAuth->>Cache: tryRecordAssertion(assertionId, expiry)
    alt not replayed
        KtorAuth->>Keystore: loadCredential(...) (signature verification)
        KtorAuth->>LibSaml: validate signature / verify assertion
        KtorAuth->>IdP: (optional) parseSamlIdpMetadata(xml)
        KtorAuth-->>Client: Authenticate principal / set session
    else replayed
        KtorAuth-->>Client: Reject (replay detected)
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~75 minutes

Possibly related PRs

Suggested reviewers

  • osipxd
  • e5l
  • bjhham

Poem

"I hopped through XML with keys in paw,
Parsers guarded, DOCTYPE saw no law.
I cached a nonce to keep replays at bay,
Signed and parsed, then leapt to play.
Happy hops — SAML's here today! 🐇"

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 42.86% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately reflects the main focus of the PR: introducing SAML configuration, constants, and metadata handling for server authentication.
Description check ✅ Passed The description follows the template structure with Subsystem, Motivation, and Solution sections. It provides clear details about what's included and what's planned next.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch zibet27/server-auth-saml-core

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.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 7

🧹 Nitpick comments (1)
ktor-server/ktor-server-plugins/ktor-server-auth-saml/jvm/test/io/ktor/server/auth/saml/SamlConfigTest.kt (1)

12-12: Consider tightening test names to behavior-only phrasing.

The tests are clear already; optionally drop the test prefix to match the repository’s backtick naming pattern more closely.

As per coding guidelines "Use descriptive test names in backticks following the pattern: describe what is being tested".

Also applies to: 22-22, 32-32, 47-47

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@ktor-server/ktor-server-plugins/ktor-server-auth-saml/jvm/test/io/ktor/server/auth/saml/SamlConfigTest.kt`
at line 12, Rename the test functions to remove the redundant "test" prefix so
they follow the backtick behavior-only naming convention; e.g., change the
function named `test default SamlSpMetadata values` to ``default SamlSpMetadata
values``, and do the same for the other functions referenced (the ones at the
same positions as the declarations currently named with a `test` prefix). Update
any direct references to these function names (if used elsewhere) and ensure the
tests still compile and run.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@ktor-server/ktor-server-plugins/ktor-server-auth-saml/jvm/src/io/ktor/server/auth/saml/SamlConfig.kt`:
- Around line 80-85: The KDoc example for SamlSpMetadata is stale: replace the
placeholder "keyStore { ... }" with the current SAML SP key configuration API
used by SamlSpMetadata (whatever property or builder function now exposes
keys/signing certificate, e.g., the current keystore/keyPair/signingKey
configuration); update the snippet under SamlSpMetadata so it compiles with the
present API and demonstrates setting the SP keys alongside spEntityId and
acsUrl, referring to the SamlSpMetadata builder and the actual key configuration
symbol (the current keystore/keyPair/signingKey API) used in the codebase.

In
`@ktor-server/ktor-server-plugins/ktor-server-auth-saml/jvm/src/io/ktor/server/auth/saml/SamlMetadata.kt`:
- Around line 369-371: The code currently logs and continues when
signingCredentials.isEmpty() in the Saml metadata parsing path (the
signingCredentials check that calls LOGGER.warn("No signing certificates...")),
which allows invalid IdP metadata to silently pass; change this to fail fast by
throwing a descriptive exception (e.g., IllegalArgumentException or a
SamlMetadataParseException) when signingCredentials.isEmpty() so
parsing/initialization aborts immediately with a clear error instead of only
logging a warning.

In
`@ktor-server/ktor-server-plugins/ktor-server-auth-saml/jvm/src/io/ktor/server/auth/saml/SamlPrincipal.kt`:
- Around line 10-13: The KDoc in SamlPrincipal.kt incorrectly states that
SamlCredential "should never be exposed to application code" while the public
API (SamlConfig.validate) exposes it; update the documentation to accurately
reflect that SamlCredential may be provided to user code via SamlConfig.validate
(or clarify the exposure rules), mentioning the SamlCredential type and
SamlConfig.validate so readers understand when it is safe/validated and when it
is internal.
- Around line 142-150: The buildAttributesMap function in
Assertion.buildAttributesMap currently force-unwraps attribute.name (!!) and
overwrites previous entries for the same attribute name; change it to safely
handle null names (skip attributes with null name using attribute.name?.let {
name -> ... } or continue) and merge values when the same name appears across
attributeStatements by appending to an existing list instead of replacing it
(retrieve existing list with get(name) and addAll(values) or use compute(name)
to combine lists), preserving the non-null extracted texts from
attribute.attributeValues.mapNotNull { it.dom?.textContent } and only put into
the map when the resulting list is not empty.

In
`@ktor-server/ktor-server-plugins/ktor-server-auth-saml/jvm/src/io/ktor/server/auth/saml/SamlReplayCache.kt`:
- Around line 53-57: The public API is missing complete KDoc for parameters and
return values: add KDoc tags for the constructor parameter parentScope (describe
its purpose and lifecycle) and for the method tryRecordAssertion(assertionId:
String, expirationTime: Instant): Boolean (document assertionId, expirationTime,
returned Boolean meaning, and any notable exceptions or coroutine/timeout
behavior); update the KDoc on the SamlReplayCache class/constructor and the
tryRecordAssertion function to include `@param` for parentScope, assertionId,
expirationTime and an `@return` explaining true/false semantics and any `@throws` or
concurrency notes.

In
`@ktor-server/ktor-server-plugins/ktor-server-auth-saml/jvm/src/io/ktor/server/auth/saml/SamlSecurity.kt`:
- Around line 58-73: loadCredential currently can let IO/crypto exceptions and
NoSuchElementException escape instead of the declared KeyStoreException; modify
loadCredential to guard all calls that may throw (calls to loadKeyStore,
keyStore.getKey, keyStore.getCertificateChain and the .first() access) by
wrapping the body in a try/catch that catches Exception (or the specific checked
exceptions) and rethrows a KeyStoreException with the original exception as the
cause, and replace certificateChain.first() with certificateChain.firstOrNull()
and throw a KeyStoreException("Certificate chain for alias '$keyAlias' not found
or empty") when null so callers only receive KeyStoreException (preserving the
original exception as the cause).

In
`@ktor-server/ktor-server-plugins/ktor-server-auth-saml/jvm/test/io/ktor/server/auth/saml/InMemorySamlReplayCacheTest.kt`:
- Around line 56-75: The test `test concurrent access safety` uses launch
without a dispatcher so child coroutines run on the runTest test dispatcher
(sequential), which won't surface real data races in InMemorySamlReplayCache;
update the coroutine launches to run on a real parallel dispatcher (for example
use launch(Dispatchers.Default) or wrap the assertion loop in
withContext(Dispatchers.Default)) so the cache methods (recordAssertion,
isReplayed) are exercised concurrently across threads.

---

Nitpick comments:
In
`@ktor-server/ktor-server-plugins/ktor-server-auth-saml/jvm/test/io/ktor/server/auth/saml/SamlConfigTest.kt`:
- Line 12: Rename the test functions to remove the redundant "test" prefix so
they follow the backtick behavior-only naming convention; e.g., change the
function named `test default SamlSpMetadata values` to ``default SamlSpMetadata
values``, and do the same for the other functions referenced (the ones at the
same positions as the declarations currently named with a `test` prefix). Update
any direct references to these function names (if used elsewhere) and ensure the
tests still compile and run.

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b5f010b and 90866c0.

📒 Files selected for processing (16)
  • build-settings-logic/src/main/kotlin/ktorsettings.dependency-resolution-management.settings.gradle.kts
  • gradle/libs.versions.toml
  • ktor-server/ktor-server-plugins/ktor-server-auth-saml/api/ktor-server-auth-saml.api
  • ktor-server/ktor-server-plugins/ktor-server-auth-saml/build.gradle.kts
  • ktor-server/ktor-server-plugins/ktor-server-auth-saml/jvm/src/io/ktor/server/auth/saml/LibSaml.kt
  • ktor-server/ktor-server-plugins/ktor-server-auth-saml/jvm/src/io/ktor/server/auth/saml/SamlConfig.kt
  • ktor-server/ktor-server-plugins/ktor-server-auth-saml/jvm/src/io/ktor/server/auth/saml/SamlConstants.kt
  • ktor-server/ktor-server-plugins/ktor-server-auth-saml/jvm/src/io/ktor/server/auth/saml/SamlMetadata.kt
  • ktor-server/ktor-server-plugins/ktor-server-auth-saml/jvm/src/io/ktor/server/auth/saml/SamlPrincipal.kt
  • ktor-server/ktor-server-plugins/ktor-server-auth-saml/jvm/src/io/ktor/server/auth/saml/SamlReplayCache.kt
  • ktor-server/ktor-server-plugins/ktor-server-auth-saml/jvm/src/io/ktor/server/auth/saml/SamlSecurity.kt
  • ktor-server/ktor-server-plugins/ktor-server-auth-saml/jvm/src/io/ktor/server/auth/saml/SamlUtils.kt
  • ktor-server/ktor-server-plugins/ktor-server-auth-saml/jvm/test/io/ktor/server/auth/saml/InMemorySamlReplayCacheTest.kt
  • ktor-server/ktor-server-plugins/ktor-server-auth-saml/jvm/test/io/ktor/server/auth/saml/SamlConfigTest.kt
  • ktor-server/ktor-server-plugins/ktor-server-auth-saml/jvm/test/io/ktor/server/auth/saml/SamlInitializerTest.kt
  • settings.gradle.kts

@zibet27 zibet27 requested a review from jk1 March 3, 2026 12:39
@zibet27 zibet27 self-assigned this Mar 4, 2026
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

♻️ Duplicate comments (1)
ktor-server/ktor-server-plugins/ktor-server-auth-saml/jvm/src/io/ktor/server/auth/saml/SamlSecurity.kt (1)

74-78: ⚠️ Potential issue | 🟠 Major

Avoid catching Throwable in loadCredential, and add context to the wrapped error.

Line 76 should catch Exception (not Throwable) so fatal JVM errors are not swallowed. Also include keyAlias/keystorePath in the wrapper message for diagnosability.

🔧 Proposed fix
         } catch (e: KeyStoreException) {
             throw e
-        } catch (e: Throwable) {
-            throw KeyStoreException("Failed to load credential", e)
+        } catch (e: Exception) {
+            throw KeyStoreException(
+                "Failed to load credential for alias '$keyAlias' from keystore '$keystorePath' (type='$keystoreType')",
+                e
+            )
         }
#!/bin/bash
rg -n --type=kt 'catch\s*\(\s*\w+\s*:\s*Throwable\s*\)' \
  ktor-server/ktor-server-plugins/ktor-server-auth-saml/jvm/src/io/ktor/server/auth/saml

As per coding guidelines, "Make error messages actionable by including the problematic value and context."

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@ktor-server/ktor-server-plugins/ktor-server-auth-saml/jvm/src/io/ktor/server/auth/saml/SamlSecurity.kt`
around lines 74 - 78, The catch block in loadCredential should not catch
Throwable; change the second catch to catch Exception instead of Throwable to
avoid swallowing fatal JVM errors, and when wrapping the exception into a
KeyStoreException include contextual details (e.g., keyAlias and keystorePath)
in the error message so the thrown KeyStoreException("Failed to load
credential", e) becomes something like KeyStoreException("Failed to load
credential for keyAlias='...' keystorePath='...'", e); update the catch clause
near the KeyStoreException throw in the loadCredential function accordingly.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@ktor-server/ktor-server-plugins/ktor-server-auth-saml/jvm/src/io/ktor/server/auth/saml/SamlMetadata.kt`:
- Around line 323-330: Add missing KDoc tags to the public function
parseSamlIdpMetadata: keep the existing `@param` entries and add an `@return` that
describes the returned IdPMetadata, and add `@throws` tags describing the notable
failure modes callers must handle (e.g., XML parse errors, invalid/malformed
metadata, and certificate validation failures when validateCertificateExpiration
is true). Reference the function name parseSamlIdpMetadata and include the
behavior for expired certificates (exception) and near-expiry warnings so
callers know when exceptions are raised versus logged.

---

Duplicate comments:
In
`@ktor-server/ktor-server-plugins/ktor-server-auth-saml/jvm/src/io/ktor/server/auth/saml/SamlSecurity.kt`:
- Around line 74-78: The catch block in loadCredential should not catch
Throwable; change the second catch to catch Exception instead of Throwable to
avoid swallowing fatal JVM errors, and when wrapping the exception into a
KeyStoreException include contextual details (e.g., keyAlias and keystorePath)
in the error message so the thrown KeyStoreException("Failed to load
credential", e) becomes something like KeyStoreException("Failed to load
credential for keyAlias='...' keystorePath='...'", e); update the catch clause
near the KeyStoreException throw in the loadCredential function accordingly.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 62d445d1-3b9b-4cf7-aa08-e070475ecfd4

📥 Commits

Reviewing files that changed from the base of the PR and between 90866c0 and affd59e.

📒 Files selected for processing (7)
  • ktor-server/ktor-server-plugins/ktor-server-auth-saml/jvm/src/io/ktor/server/auth/saml/SamlConfig.kt
  • ktor-server/ktor-server-plugins/ktor-server-auth-saml/jvm/src/io/ktor/server/auth/saml/SamlMetadata.kt
  • ktor-server/ktor-server-plugins/ktor-server-auth-saml/jvm/src/io/ktor/server/auth/saml/SamlPrincipal.kt
  • ktor-server/ktor-server-plugins/ktor-server-auth-saml/jvm/src/io/ktor/server/auth/saml/SamlReplayCache.kt
  • ktor-server/ktor-server-plugins/ktor-server-auth-saml/jvm/src/io/ktor/server/auth/saml/SamlSecurity.kt
  • ktor-server/ktor-server-plugins/ktor-server-auth-saml/jvm/test/io/ktor/server/auth/saml/InMemorySamlReplayCacheTest.kt
  • ktor-server/ktor-server-plugins/ktor-server-auth-saml/jvm/test/io/ktor/server/auth/saml/SamlConfigTest.kt
🚧 Files skipped from review as they are similar to previous changes (3)
  • ktor-server/ktor-server-plugins/ktor-server-auth-saml/jvm/test/io/ktor/server/auth/saml/SamlConfigTest.kt
  • ktor-server/ktor-server-plugins/ktor-server-auth-saml/jvm/src/io/ktor/server/auth/saml/SamlReplayCache.kt
  • ktor-server/ktor-server-plugins/ktor-server-auth-saml/jvm/src/io/ktor/server/auth/saml/SamlPrincipal.kt

Comment on lines +323 to +330
* Parses SAML IdP metadata from an XML string.
*
* @param xml The metadata XML content
* @param validateCertificateExpiration Whether to validate the certificate expiration (default: true).
* When enabled, expired certificates will cause an exception and certificates expiring
* within 30 days will trigger a warning log.
*/
public fun parseSamlIdpMetadata(xml: String, validateCertificateExpiration: Boolean = true): IdPMetadata {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Complete the public KDoc contract for parseSamlIdpMetadata.

This public API currently documents parameters only; please add @return and notable @throws so callers can handle parse/validation failures intentionally.

As per coding guidelines, "Public API must include KDoc documentation for parameters, return values, and notable exceptions."

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@ktor-server/ktor-server-plugins/ktor-server-auth-saml/jvm/src/io/ktor/server/auth/saml/SamlMetadata.kt`
around lines 323 - 330, Add missing KDoc tags to the public function
parseSamlIdpMetadata: keep the existing `@param` entries and add an `@return` that
describes the returned IdPMetadata, and add `@throws` tags describing the notable
failure modes callers must handle (e.g., XML parse errors, invalid/malformed
metadata, and certificate validation failures when validateCertificateExpiration
is true). Reference the function name parseSamlIdpMetadata and include the
behavior for expired certificates (exception) and near-expiry warnings so
callers know when exceptions are raised versus logged.

* @property ssoUrl The Single Sign-On service URL (default binding - HTTP-Redirect or HTTP-POST)
* @property sloUrl The Single Logout service URL (default binding - HTTP-Redirect or HTTP-POST), null if not available
*/
public class IdPMetadata internal constructor(
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

It seems that there's no way to supply IdpMetadata other than from an XML discovery document. While fairly common, a metadata endpoint is not always available or reachable. A backup option for constructing your own IdPMetadata would be handy.

@zibet27 zibet27 force-pushed the zibet27/server-auth-saml-core branch from e6cdbc7 to c69399e Compare March 10, 2026 12:14
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

♻️ Duplicate comments (1)
ktor-server/ktor-server-plugins/ktor-server-auth-saml/jvm/src/io/ktor/server/auth/saml/SamlMetadata.kt (1)

396-409: ⚠️ Potential issue | 🟡 Minor

Complete the public KDoc contract for parseSamlIdpMetadata.

The KDoc is missing @return and @throws documentation. Callers need to know what exceptions to handle for parse failures, invalid metadata structure, and certificate validation failures.

📝 Suggested KDoc addition
 /**
  * Parses SAML IdP metadata from an XML string.
  *
  * `@param` xml The metadata XML content
  * `@param` validateCertificateExpiration Whether to validate the certificate expiration (default: true).
  *        When enabled, expired certificates will cause an exception and certificates expiring
  *        within 30 days will trigger a warning log.
+ * `@return` The parsed [IdPMetadata] containing IdP configuration
+ * `@throws` IllegalStateException if the metadata is missing required elements (entityID, IDPSSODescriptor, SSO endpoint)
+ * `@throws` java.security.cert.CertificateExpiredException if [validateCertificateExpiration] is true and a certificate is expired
+ * `@throws` org.xml.sax.SAXException if the XML is malformed
  */
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@ktor-server/ktor-server-plugins/ktor-server-auth-saml/jvm/src/io/ktor/server/auth/saml/SamlMetadata.kt`
around lines 396 - 409, Update the KDoc for parseSamlIdpMetadata to include an
`@return` explaining it returns an IdPMetadata parsed from the provided XML, and
add `@throws` tags documenting the possible failure modes: XML parsing/IO errors
(e.g., IOException / SAXException) when the input cannot be parsed, invalid
metadata structure errors (e.g., IllegalArgumentException) when required
elements are missing or unmarshalling fails, and certificate validation failures
when validateCertificateExpiration is true (e.g., CertificateException or the
library's certificate validation exception) — mention that certificate
expiration within 30 days will only log a warning while expired certificates
will throw when validation is enabled.
🧹 Nitpick comments (1)
ktor-server/ktor-server-plugins/ktor-server-auth-saml/jvm/src/io/ktor/server/auth/saml/SamlMetadata.kt (1)

277-283: Add @KtorDsl annotation for DSL receiver consistency.

The IdPMetadata class is used as a DSL receiver in the IdPMetadata() factory function (line 390), but it's missing the @KtorDsl annotation that SamlSpMetadata and SamlContactPerson have.

✨ Suggested fix
 /**
  * Represents parsed Identity Provider (IdP) metadata.
  *
  * This class extracts and holds the essential information from SAML metadata
  * needed for the SP to interact with the IdP.
  */
+@KtorDsl
 public class IdPMetadata internal constructor() {

As per coding guidelines: "All types used as receivers in DSL should be annotated with @KtorDsl".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@ktor-server/ktor-server-plugins/ktor-server-auth-saml/jvm/src/io/ktor/server/auth/saml/SamlMetadata.kt`
around lines 277 - 283, The IdPMetadata class is used as a DSL receiver but
lacks the `@KtorDsl` annotation; add the `@KtorDsl` annotation to the IdPMetadata
class declaration (public class IdPMetadata ...) and ensure the KtorDsl symbol
is imported so the annotation compiles; this keeps it consistent with
SamlSpMetadata and SamlContactPerson and satisfies the guideline that all DSL
receiver types be annotated.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@ktor-server/ktor-server-plugins/ktor-server-auth-saml/jvm/src/io/ktor/server/auth/saml/SamlMetadata.kt`:
- Around line 444-454: extractIdPMetadata builds and returns an IdPMetadata
instance without calling its validate() method, allowing empty
signingCredentials to slip through; update extractIdPMetadata to call validate()
on the constructed IdPMetadata before returning (same behavior as the
IdPMetadata() factory), so locate the extractIdPMetadata function and add a call
to validate() on the IdPMetadata instance (or return IdPMetadata().apply { ...
}.also { it.validate() }) to enforce required fields (e.g., signingCredentials)
and fail fast.

---

Duplicate comments:
In
`@ktor-server/ktor-server-plugins/ktor-server-auth-saml/jvm/src/io/ktor/server/auth/saml/SamlMetadata.kt`:
- Around line 396-409: Update the KDoc for parseSamlIdpMetadata to include an
`@return` explaining it returns an IdPMetadata parsed from the provided XML, and
add `@throws` tags documenting the possible failure modes: XML parsing/IO errors
(e.g., IOException / SAXException) when the input cannot be parsed, invalid
metadata structure errors (e.g., IllegalArgumentException) when required
elements are missing or unmarshalling fails, and certificate validation failures
when validateCertificateExpiration is true (e.g., CertificateException or the
library's certificate validation exception) — mention that certificate
expiration within 30 days will only log a warning while expired certificates
will throw when validation is enabled.

---

Nitpick comments:
In
`@ktor-server/ktor-server-plugins/ktor-server-auth-saml/jvm/src/io/ktor/server/auth/saml/SamlMetadata.kt`:
- Around line 277-283: The IdPMetadata class is used as a DSL receiver but lacks
the `@KtorDsl` annotation; add the `@KtorDsl` annotation to the IdPMetadata class
declaration (public class IdPMetadata ...) and ensure the KtorDsl symbol is
imported so the annotation compiles; this keeps it consistent with
SamlSpMetadata and SamlContactPerson and satisfies the guideline that all DSL
receiver types be annotated.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 8b7e4192-3d83-46da-a450-fbbce6ea841a

📥 Commits

Reviewing files that changed from the base of the PR and between affd59e and e6cdbc7.

📒 Files selected for processing (1)
  • ktor-server/ktor-server-plugins/ktor-server-auth-saml/jvm/src/io/ktor/server/auth/saml/SamlMetadata.kt

@zibet27 zibet27 force-pushed the zibet27/server-auth-saml-core branch from c69399e to 13a32a2 Compare March 10, 2026 12:24
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

♻️ Duplicate comments (1)
ktor-server/ktor-server-plugins/ktor-server-auth-saml/jvm/src/io/ktor/server/auth/saml/SamlMetadata.kt (1)

396-404: ⚠️ Potential issue | 🟡 Minor

Finish the public KDoc contract for parseSamlIdpMetadata.

This still documents parameters only. Please add @return and notable @throws for XML parsing failures, malformed metadata, and expired/not-yet-valid certificates so callers can handle failures intentionally.

As per coding guidelines, "Public API must include KDoc documentation for parameters, return values, and notable exceptions."

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@ktor-server/ktor-server-plugins/ktor-server-auth-saml/jvm/src/io/ktor/server/auth/saml/SamlMetadata.kt`
around lines 396 - 404, Update the KDoc for the public function
parseSamlIdpMetadata(xml: String, validateCertificateExpiration: Boolean =
true): IdPMetadata to include an `@return` describing the returned IdPMetadata
structure and to document notable `@throws` cases: add entries for XML parsing
failures (e.g., when the input is not well-formed), malformed/invalid SAML
metadata (missing required elements or unexpected structure), and certificate
validity errors when validateCertificateExpiration is true (expired certificates
and certificates not yet valid), so callers know which exceptions to catch.
🧹 Nitpick comments (2)
ktor-server/ktor-server-plugins/ktor-server-auth-saml/jvm/src/io/ktor/server/auth/saml/SamlMetadata.kt (2)

277-283: Mark IdPMetadata as a DSL receiver.

IdPMetadata is the receiver in IdPMetadata { ... }, but unlike SamlSpMetadata and SamlContactPerson it isn't annotated with @KtorDsl. That leaves nested builders without the usual receiver-scope protection.

As per coding guidelines, "All types used as receivers in DSL should be annotated with @KtorDsl."

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@ktor-server/ktor-server-plugins/ktor-server-auth-saml/jvm/src/io/ktor/server/auth/saml/SamlMetadata.kt`
around lines 277 - 283, IdPMetadata is missing the `@KtorDsl` annotation used for
DSL receivers; add the annotation to the IdPMetadata declaration so it reads
similarly to SamlSpMetadata and SamlContactPerson, i.e., annotate the class
declaration of IdPMetadata with `@KtorDsl` (ensure the correct import for Ktor’s
`@KtorDsl` is present) to provide proper DSL receiver scoping and match project
guidelines.

480-483: Please verify wrapped certificate text is safe with Base64.decode.

Kotlin's default Base64 decoder throws on characters outside the Base64 alphabet, while XML base64Binary permits whitespace in the lexical form. If certValue includes line breaks or indentation, valid <X509Certificate> blocks can fail here; stripping XML whitespace before decoding would make this path robust without relaxing other validation. (kotlinlang.org)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@ktor-server/ktor-server-plugins/ktor-server-auth-saml/jvm/src/io/ktor/server/auth/saml/SamlMetadata.kt`
around lines 480 - 483, The Base64.decode call in SamlMetadata.kt can fail if
the XML-wrapped certValue contains whitespace/newlines; before decoding the
certValue (used by Base64.decode, then ByteArrayInputStream and
certificateFactory.generateCertificate), normalize it by stripping XML
whitespace (e.g., remove all characters where Char.isWhitespace() or apply a
"\\s+" regex replacement) while preserving the existing null-check, then pass
the cleaned string into Base64.decode so valid base64Binary with line
breaks/indentation decodes robustly.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@ktor-server/ktor-server-plugins/ktor-server-auth-saml/jvm/src/io/ktor/server/auth/saml/SamlMetadata.kt`:
- Around line 334-339: The validate() function currently only checks entityId
and ssoUrl for null; update it to reject null or blank values by replacing the
requireNotNull checks with checks that ensure entityId and ssoUrl are not null
or blank (e.g., use require(!entityId.isNullOrBlank()) and
require(!ssoUrl.isNullOrBlank()) ) and keep the existing signingCredentials
non-empty check; update the error messages to say "Entity ID cannot be null or
blank" and "SSO URL cannot be null or blank" so SamlMetadata.validate() fails
fast for empty strings.

---

Duplicate comments:
In
`@ktor-server/ktor-server-plugins/ktor-server-auth-saml/jvm/src/io/ktor/server/auth/saml/SamlMetadata.kt`:
- Around line 396-404: Update the KDoc for the public function
parseSamlIdpMetadata(xml: String, validateCertificateExpiration: Boolean =
true): IdPMetadata to include an `@return` describing the returned IdPMetadata
structure and to document notable `@throws` cases: add entries for XML parsing
failures (e.g., when the input is not well-formed), malformed/invalid SAML
metadata (missing required elements or unexpected structure), and certificate
validity errors when validateCertificateExpiration is true (expired certificates
and certificates not yet valid), so callers know which exceptions to catch.

---

Nitpick comments:
In
`@ktor-server/ktor-server-plugins/ktor-server-auth-saml/jvm/src/io/ktor/server/auth/saml/SamlMetadata.kt`:
- Around line 277-283: IdPMetadata is missing the `@KtorDsl` annotation used for
DSL receivers; add the annotation to the IdPMetadata declaration so it reads
similarly to SamlSpMetadata and SamlContactPerson, i.e., annotate the class
declaration of IdPMetadata with `@KtorDsl` (ensure the correct import for Ktor’s
`@KtorDsl` is present) to provide proper DSL receiver scoping and match project
guidelines.
- Around line 480-483: The Base64.decode call in SamlMetadata.kt can fail if the
XML-wrapped certValue contains whitespace/newlines; before decoding the
certValue (used by Base64.decode, then ByteArrayInputStream and
certificateFactory.generateCertificate), normalize it by stripping XML
whitespace (e.g., remove all characters where Char.isWhitespace() or apply a
"\\s+" regex replacement) while preserving the existing null-check, then pass
the cleaned string into Base64.decode so valid base64Binary with line
breaks/indentation decodes robustly.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 8ae861c9-9fe8-4589-8781-dcee4f3747fe

📥 Commits

Reviewing files that changed from the base of the PR and between e6cdbc7 and c69399e.

📒 Files selected for processing (1)
  • ktor-server/ktor-server-plugins/ktor-server-auth-saml/jvm/src/io/ktor/server/auth/saml/SamlMetadata.kt

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

♻️ Duplicate comments (2)
ktor-server/ktor-server-plugins/ktor-server-auth-saml/jvm/src/io/ktor/server/auth/saml/SamlMetadata.kt (2)

334-339: ⚠️ Potential issue | 🟠 Major

Reject blank entityId and ssoUrl in validate().

requireNotNull still allows "" / blank values here, so IdPMetadata { entityId = ""; ssoUrl = ""; ... } passes validation and only fails later with unusable metadata. Please tighten both checks to reject blank input and make the messages identify the offending property. This will also need the IdPMetadata(...) KDoc throws contract updated accordingly.

Proposed fix
     internal fun validate() {
-        requireNotNull(entityId) { "Entity ID cannot be null" }
-        requireNotNull(ssoUrl) { "SSO URL cannot be null" }
+        require(!entityId.isNullOrBlank()) { "IdPMetadata.entityId must not be blank" }
+        require(!ssoUrl.isNullOrBlank()) { "IdPMetadata.ssoUrl must not be blank" }
         require(signingCredentials.isNotEmpty()) {
             "No signing certificates found in IdP metadata. Signature verification will fail."
         }
     }

As per coding guidelines, "Use require(...) for argument validation, check(...) for state validation, and error(...) for unreachable states".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@ktor-server/ktor-server-plugins/ktor-server-auth-saml/jvm/src/io/ktor/server/auth/saml/SamlMetadata.kt`
around lines 334 - 339, The validate() method currently uses requireNotNull for
entityId and ssoUrl which permits blank strings; update validate() to use
require(!entityId.isNullOrBlank()) and require(!ssoUrl.isNullOrBlank()) with
clear messages like "entityId cannot be null or blank" and "ssoUrl cannot be
null or blank", keep the signingCredentials check as-is, and update the
IdPMetadata(...) KDoc throws clause to reflect that both entityId and ssoUrl
will throw on null or blank inputs.

396-404: ⚠️ Potential issue | 🟡 Minor

Complete the public KDoc for parseSamlIdpMetadata.

This API still documents only its parameters. Please add @return and notable @throws entries for malformed XML/metadata and certificate-validation failures when validateCertificateExpiration is enabled.

As per coding guidelines, "Public API must include KDoc documentation for parameters, return values, and notable exceptions".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@ktor-server/ktor-server-plugins/ktor-server-auth-saml/jvm/src/io/ktor/server/auth/saml/SamlMetadata.kt`
around lines 396 - 404, The KDoc for parseSamlIdpMetadata is incomplete; add
`@return` describing that it returns an IdPMetadata representing parsed IdP
metadata and add `@throws` entries documenting that it throws an exception for
malformed XML or invalid/missing SAML metadata and that it can throw a
certificate-validation exception when validateCertificateExpiration is true
(including behavior for expired certificates vs. certificates expiring within 30
days); update the KDoc above the parseSamlIdpMetadata function to include these
`@return` and `@throws` tags and concise descriptions referencing
parseSamlIdpMetadata and the validateCertificateExpiration parameter.
🧹 Nitpick comments (2)
ktor-server/ktor-server-plugins/ktor-server-auth-saml/api/ktor-server-auth-saml.api (2)

1-20: The public JVM ABI is leaking mangled inline-class accessors.

Names like getSHA256-x-8ZtNE, getNameIdFormat-W8VwlJw, and setRequestedAuthnContext-Br-yMbY are now part of the published surface. That is awkward for Java consumers and expensive to clean up later, so if JVM interop matters I’d add Java-friendly bridges or avoid exposing these inline-value types directly in the public API.

Based on learnings: All public/protected API changes must be intentional and well-documented.

Also applies to: 51-71, 79-100, 115-153

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@ktor-server/ktor-server-plugins/ktor-server-auth-saml/api/ktor-server-auth-saml.api`
around lines 1 - 20, The public API is leaking mangled inline-class accessors
(e.g., DigestAlgorithm$Companion.getSHA256-x-8ZtNE and similar
getNameIdFormat-*/setRequestedAuthnContext-* methods); fix this by adding
Java-friendly bridge methods with stable names (e.g., getSHA256(), getSHA384(),
getSHA512(), getNameIdFormat(), setRequestedAuthnContext(...)) and either mark
the mangled accessor declarations as `@JvmSynthetic` or make the
inline-value-returning members internal/private so they are not part of the
public ABI; update the classes referenced (DigestAlgorithm,
DigestAlgorithm$Companion and the other companion/inline-returning members
called out) to provide these stable `@JvmName/`@JvmOverloads-friendly entry points
for Java callers and hide the compiler-generated mangled accessors.

171-185: Consider whether wrapping OpenSAML types is necessary for this pre-release module.

SamlCredential, SamlPrincipal, SamlSpMetadata, and SamlCrypto expose org.opensaml.* types in their public signatures. This couples the module's contract to OpenSAML and makes future library changes or replacements breaking for consumers.

However, all exposed types are explicitly documented with examples showing intended usage. SAML protocol operations inherently require these types, and wrapping them would add abstraction without significant benefit. Since this module is pre-release, you may retain the current design if the OpenSAML coupling is intentional and acceptable for the target use case. If broader flexibility is desired, consider introducing Ktor-owned wrapper types in a future release.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@ktor-server/ktor-server-plugins/ktor-server-auth-saml/api/ktor-server-auth-saml.api`
around lines 171 - 185, Public APIs SamlCredential, SamlPrincipal,
SamlSpMetadata, and SamlCrypto currently expose org.opensaml types and thus
couple the module to OpenSAML; either (A) explicitly document this design
decision and intended stability in the module README and API KDoc (mentioning
classes SamlCredential, SamlPrincipal, SamlSpMetadata, SamlCrypto and their
methods like getAssertion/getResponse/loadCredential) so consumers know the
coupling is intentional for this pre-release, or (B) introduce Ktor-owned
wrapper types (e.g., SamlCredentialWrapper, SamlPrincipalWrapper,
SamlSpMetadataWrapper and adapt SamlCrypto.loadCredential to return a
BasicX509Credential wrapper) and update public signatures to return/accept those
wrappers while keeping internal conversions to org.opensaml.* to avoid leaking
OpenSAML in the public contract; pick one approach and apply it consistently
across the referenced classes.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@ktor-server/ktor-server-plugins/ktor-server-auth-saml/api/ktor-server-auth-saml.api`:
- Around line 206-209: The SamlReplayCache API currently exposes a racy
check-then-write pair (isReplayed and recordAssertion) alongside
tryRecordAssertion; change the contract so replay enforcement is atomic by
making tryRecordAssertion the sole authoritative enforcement method: update the
SamlReplayCache interface documentation and implementation notes to state that
isReplayed and recordAssertion are non-authoritative helpers only (must not be
used for enforcement), remove or deprecate any public usages that rely on
isReplayed+recordAssertion for enforcement, and update callers to use
tryRecordAssertion for replay checks; reference the SamlReplayCache interface
and its methods isReplayed, recordAssertion, and tryRecordAssertion when making
these changes.

In
`@ktor-server/ktor-server-plugins/ktor-server-auth-saml/jvm/src/io/ktor/server/auth/saml/SamlMetadata.kt`:
- Around line 277-283: IdPMetadata is missing the `@KtorDsl` annotation which is
required for DSL receiver types; add the annotation above the class declaration
for IdPMetadata (the class with internal constructor IdPMetadata()) so it reads
as an `@KtorDsl-annotated` DSL receiver, matching other DSL types in this file and
ensuring proper nested scope resolution.

---

Duplicate comments:
In
`@ktor-server/ktor-server-plugins/ktor-server-auth-saml/jvm/src/io/ktor/server/auth/saml/SamlMetadata.kt`:
- Around line 334-339: The validate() method currently uses requireNotNull for
entityId and ssoUrl which permits blank strings; update validate() to use
require(!entityId.isNullOrBlank()) and require(!ssoUrl.isNullOrBlank()) with
clear messages like "entityId cannot be null or blank" and "ssoUrl cannot be
null or blank", keep the signingCredentials check as-is, and update the
IdPMetadata(...) KDoc throws clause to reflect that both entityId and ssoUrl
will throw on null or blank inputs.
- Around line 396-404: The KDoc for parseSamlIdpMetadata is incomplete; add
`@return` describing that it returns an IdPMetadata representing parsed IdP
metadata and add `@throws` entries documenting that it throws an exception for
malformed XML or invalid/missing SAML metadata and that it can throw a
certificate-validation exception when validateCertificateExpiration is true
(including behavior for expired certificates vs. certificates expiring within 30
days); update the KDoc above the parseSamlIdpMetadata function to include these
`@return` and `@throws` tags and concise descriptions referencing
parseSamlIdpMetadata and the validateCertificateExpiration parameter.

---

Nitpick comments:
In
`@ktor-server/ktor-server-plugins/ktor-server-auth-saml/api/ktor-server-auth-saml.api`:
- Around line 1-20: The public API is leaking mangled inline-class accessors
(e.g., DigestAlgorithm$Companion.getSHA256-x-8ZtNE and similar
getNameIdFormat-*/setRequestedAuthnContext-* methods); fix this by adding
Java-friendly bridge methods with stable names (e.g., getSHA256(), getSHA384(),
getSHA512(), getNameIdFormat(), setRequestedAuthnContext(...)) and either mark
the mangled accessor declarations as `@JvmSynthetic` or make the
inline-value-returning members internal/private so they are not part of the
public ABI; update the classes referenced (DigestAlgorithm,
DigestAlgorithm$Companion and the other companion/inline-returning members
called out) to provide these stable `@JvmName/`@JvmOverloads-friendly entry points
for Java callers and hide the compiler-generated mangled accessors.
- Around line 171-185: Public APIs SamlCredential, SamlPrincipal,
SamlSpMetadata, and SamlCrypto currently expose org.opensaml types and thus
couple the module to OpenSAML; either (A) explicitly document this design
decision and intended stability in the module README and API KDoc (mentioning
classes SamlCredential, SamlPrincipal, SamlSpMetadata, SamlCrypto and their
methods like getAssertion/getResponse/loadCredential) so consumers know the
coupling is intentional for this pre-release, or (B) introduce Ktor-owned
wrapper types (e.g., SamlCredentialWrapper, SamlPrincipalWrapper,
SamlSpMetadataWrapper and adapt SamlCrypto.loadCredential to return a
BasicX509Credential wrapper) and update public signatures to return/accept those
wrappers while keeping internal conversions to org.opensaml.* to avoid leaking
OpenSAML in the public contract; pick one approach and apply it consistently
across the referenced classes.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: d8c79591-ab1b-4824-841e-332ebb924032

📥 Commits

Reviewing files that changed from the base of the PR and between c69399e and 13a32a2.

📒 Files selected for processing (2)
  • ktor-server/ktor-server-plugins/ktor-server-auth-saml/api/ktor-server-auth-saml.api
  • ktor-server/ktor-server-plugins/ktor-server-auth-saml/jvm/src/io/ktor/server/auth/saml/SamlMetadata.kt

@zibet27 zibet27 requested a review from jk1 March 10, 2026 12:48
@zibet27 zibet27 force-pushed the zibet27/server-auth-saml-core branch from dd58b5e to e5fd9e5 Compare March 10, 2026 13:00
@e5l
Copy link
Copy Markdown
Member

e5l commented Mar 13, 2026

Code review

Found 1 issue:

  1. Unused kotlinx-serialization plugin and api(libs.kotlinx.serialization.core) dependency. The build.gradle.kts declares both, but no source file in the module uses any kotlinx.serialization API (no @Serializable annotations, no serialization imports). The api() scope leaks this unused dependency to consumers' compile classpaths. No other auth module in the project includes this dependency.

id("ktorbuild.project.server-plugin")
id("kotlinx-serialization")
}
kotlin {
jvmToolchain(21)
sourceSets {
jvmMain.dependencies {
api(projects.ktorServerAuth)
api(libs.kotlinx.serialization.core)

🤖 Generated with Claude Code

- If this code review was useful, please react with 👍. Otherwise, react with 👎.

Copy link
Copy Markdown
Member

@e5l e5l left a comment

Choose a reason for hiding this comment

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

lgtm

@zibet27
Copy link
Copy Markdown
Collaborator Author

zibet27 commented Mar 13, 2026

  1. Unused kotlinx-serialization plugin and api(libs.kotlinx.serialization.core) dependency. The build.gradle.kts =

It'll be used in the following PRs to serialise SamlSession

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.

3 participants