SIGN IN SIGN UP

KTOR-9841 OpenID Connect Plugin (#5632)

* Add OpenID Connect discovery metadata

* Allow external test services during startup (#5635)

* rename plugin from openid to oidc

Co-authored-by: Cursor <cursoragent@cursor.com>

* use content negotiation plugin

* Add OIDC provider lifecycle

# Conflicts:
#	ktor-server/ktor-server-plugins/ktor-server-auth-oidc/api/ktor-server-auth-oidc.api
#	ktor-server/ktor-server-plugins/ktor-server-auth-oidc/jvm/test/io/ktor/server/auth/oidc/FetchOpenIdProviderMetadataTest.kt

* remove duplicated dependencies

* Add OIDC token validation and Bearer auth

* remove custom auth context

* Add OIDC OAuth callback and UserInfo (#5641)

* Add OIDC OAuth callback and UserInfo

Co-authored-by: Cursor <cursoragent@cursor.com>

* OIDC Plugin. Support PKCE (#5692)

* Support PKCE

* add sealed CodeChallengeMethod

* OIDC session routes (#5693)

* Support PKCE

* add sealed CodeChallengeMethod

* Add OIDC OAuth callback and UserInfo

* Add OIDC sessions support

* Fix OIDC token refresh cache pruning

* Fix duplicated PKCE config property after rebase.

Remove the accidental duplicate codeChallengeMethod declaration introduced during conflict resolution so the rebased branch compiles cleanly.

Co-authored-by: Cursor <cursoragent@cursor.com>

---------

Co-authored-by: Cursor <cursoragent@cursor.com>

* OAuth 2.0 Protected Resource Metadata to the OIDC plugin (#5695)

* RFC 9728 Protected Resource Metadata

Co-authored-by: Cursor <cursoragent@cursor.com>

* Add OIDC integration tests and scope protected resource ContentNegotiation.

Port local WIP from protected-resource-metadata worktree: route-scoped metadata
serialization, browser flow, opaque introspection, provider operations, and
typed authentication coverage.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Derive authorization servers and scopes from bearer providers only

---------

Co-authored-by: Cursor <cursoragent@cursor.com>

* rename  ->

---------

Co-authored-by: Cursor <cursoragent@cursor.com>

* Move sessions inside of oauth; remove oidc config merging

* Expose token-native OIDC schemes and rename provider to identityProvider

Co-authored-by: Cursor <cursoragent@cursor.com>

* Drop stale causedByValidation from the OIDC ABI dump

* rename oauth.onSuccess and onFailure

* remove redundant dispatching; check access token is not id token; expose token refresh window; improve docs and tests

* mark API as experimental

* Validate ID token azp claim per OIDC Core 3.1.3.7

Reject multi-audience ID tokens without an azp claim and any ID token
whose azp names another client, on both callback and refresh paths.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* Select token endpoint client authentication method from provider metadata

Use client_secret_basic for the code exchange and token refresh when
metadata declares supported methods without client_secret_post; keep the
form-body default otherwise. Add an explicit tokenEndpointAuthMethod
override for client registrations that require a specific method. Unify
introspection and token endpoint methods into ClientAuthenticationMethod.

Also require the OIDC-mandatory exp and iat claims on verified ID tokens,
and capture discovery state per operation via context parameters so one
operation never mixes metadata and JWKS from different refreshes.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* Decode TokenClaims segments with URL-safe Base64 and tighten string accessors

JWT segments are Base64URL; the standard-alphabet decoder silently turned
any segment containing - or _ into an empty claims object. claimString and
headerString now return null only for absent values and throw for present
non-string values instead of skipping them. Add callback tests for the
required exp and iat ID token claims.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* Use a per-provider authorization state cookie

All providers shared a single KTOR_OIDC_STATE cookie, so starting a
login with one provider overwrote the pending authorization
transaction of another and the first callback was rejected. Suffix
the cookie name with the provider name, which registration already
restricts to cookie-safe characters.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* Validate discovery refresh delays and JWT clock skew

A negative discoveryRefreshInterval silently disabled periodic
refresh even though only Duration.ZERO is documented to do so. A
non-positive discoveryRefreshFailureDelay made the refresh loop
retry immediately after every failure, and an infinite one blocked
all later retries. A negative clockSkew only failed inside the JWT
verifier with an unhelpful message, while an infinite one accepted
expired tokens forever. Reject these values at install time.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* Parse TokenClaims header and payload lazily

The header and payload properties re-decoded Base64 and re-parsed
JSON on every access. Compute them once on first access instead.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* Release provider reservations when registration is cancelled

releaseProvider takes the registration mutex, so a cancelled
registration could skip cleanup when the mutex was contended,
leaving the provider name and issuer reserved forever. Run the
cleanup in a non-cancellable context.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* Allow token_use access for AWS Cognito

* Propagate refresh token exceptions; check clientId and clientSecret are non blank

* Propagate refresh exception, make OidcTokenRejectedException public

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
P
Pantus Oleh committed
98a56b73012e1497b231c5db14cb72924051f75b
Parent: 6b20bd0
Committed by GitHub <noreply@github.com> on 8/31/2026, 8:22:45 AM