Skip to content

Instantly share code, notes, and snippets.

@nomisRev
Created July 30, 2025 07:51
Show Gist options
  • Save nomisRev/a76b02442ea9f53e2ac8d83c2d5fd7e8 to your computer and use it in GitHub Desktop.
Save nomisRev/a76b02442ea9f53e2ac8d83c2d5fd7e8 to your computer and use it in GitHub Desktop.
OpenID Connect example including OAuth2 and JWT
package com.example
import com.auth0.jwk.JwkProviderBuilder
import io.ktor.client.HttpClient
import io.ktor.client.call.body
import io.ktor.client.request.get
import io.ktor.http.HttpMethod
import io.ktor.server.auth.AuthenticationConfig
import io.ktor.server.auth.OAuthServerSettings
import io.ktor.server.auth.authentication
import io.ktor.server.auth.jwt.JWTConfigureFunction
import io.ktor.server.auth.jwt.jwt
import io.ktor.server.auth.oauth
import io.ktor.server.engine.embeddedServer
import io.ktor.server.netty.Netty
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import java.net.URL
fun main() {
embeddedServer(Netty, port = 8080, host = "0.0.0.0") {
val client = HttpClient()
val configuration = client.discover("https://accounts.google.com")
authentication {
configureOpenIdOAuth(configuration, "OPENID_CLIENT_ID", "OPENID_SECRET", client)
configureOpenIdJwk(configuration)
}
}.start(wait = true)
}
@Serializable
data class OpenIdConfiguration(
val issuer: String,
@SerialName("authorization_endpoint")
val authorizationEndpoint: String,
@SerialName("token_endpoint")
val tokenEndpoint: String,
@SerialName("jwks_uri")
val jwksUri: String,
)
/**
* Automatically discover OpenID Connect configuration
*/
suspend fun HttpClient.discover(issuer: String): OpenIdConfiguration =
get("$issuer/.well-known/openid-configuration").body<OpenIdConfiguration>()
/** Configure Ktor's OAuth2 using [OpenIdConfiguration], and app-specific secrets. */
fun AuthenticationConfig.configureOpenIdOAuth(
configuration: OpenIdConfiguration,
clientId: String,
clientSecret: String,
client: HttpClient,
scopes: List<String> = listOf("openid", "profile", "email")
) = oauth("openid-connect") {
urlProvider = { "http://localhost:8080/callback" }
providerLookup = {
OAuthServerSettings.OAuth2ServerSettings(
name = "openid-connect",
authorizeUrl = configuration.authorizationEndpoint,
accessTokenUrl = configuration.tokenEndpoint,
requestMethod = HttpMethod.Post,
clientId = clientId,
clientSecret = clientSecret,
defaultScopes = scopes
)
}
this.client = client
}
fun AuthenticationConfig.configureOpenIdJwk(
configuration: OpenIdConfiguration,
applyJwk: JwkProviderBuilder.() -> Unit = { cached(true).rateLimited(true) },
verify: JWTConfigureFunction = {},
name: String? = null,
) = jwt(name) {
val jwk = JwkProviderBuilder(URL(configuration.jwksUri)).apply(applyJwk).build()
verifier(jwk, configuration.issuer, verify)
validate { credential -> credential }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment