You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

KTor中如何验证微软OAuth 2访问令牌?

验证微软OAuth访问令牌(KTor实现)

KTor提供了jwt认证插件来验证JWT格式的令牌(包括微软的访问令牌/ID令牌),可以直接完成签名、签发者、受众等核心字段的验证。以下是具体实现步骤:

1. 添加依赖

首先确保项目引入KTor的JWT认证依赖,以Gradle为例:

implementation("io.ktor:ktor-server-auth-jwt:$ktor_version")
// 替换$ktor_version为你使用的KTor版本,比如2.3.3

2. 配置JWT认证插件

在install(Authentication)块中新增JWT验证配置,结合微软Azure AD的特定参数:

install(Authentication) {
    // 保留你已有的OAuth配置
    oauth("auth-oauth-aad") {
        urlProvider = { /* 你的OAuth回调路径,比如Url("/callback") */ }
        providerLookup = {
            OAuthServerSettings.OAuth2ServerSettings(
                name = "azure-ad",
                authorizeUrl = "https://login.microsoftonline.com/{你的租户ID}/oauth2/v2.0/authorize",
                accessTokenUrl = "https://login.microsoftonline.com/{你的租户ID}/oauth2/v2.0/token",
                clientId = "你的应用客户端ID",
                clientSecret = "你的应用客户端密钥",
                defaultScopes = listOf("openid", "profile", "email")
            )
        }
    }

    // 新增JWT验证配置
    jwt("auth-jwt-aad") {
        val azureTenantId = "你的租户ID"
        val clientId = "你的应用客户端ID"
        val issuer = "https://login.microsoftonline.com/$azureTenantId/v2.0"

        // 配置验证规则:签发者、受众、签名算法
        verifier(
            JWT.require(Algorithm.RSA256(null, null))
                .withIssuer(issuer)
                .withAudience(clientId) // 验证令牌受众是否匹配你的应用ID
                .build(),
            // 从微软JWKS端点获取公钥,用于验证签名
            fetchAzureADJwks(issuer)
        )

        // 令牌验证通过后的用户信息处理
        validate { credential ->
            // JWT库已自动验证exp过期字段,可额外检查其他自定义字段
            if (credential.payload.audience.contains(clientId)) {
                JWTPrincipal(credential.payload)
            } else {
                null // 验证不通过返回null
            }
        }
    }
}

// 辅助函数:获取微软Azure AD的JWKS密钥集(用于验证签名)
private fun fetchAzureADJwks(issuer: String): JWKSet {
    val jwksEndpoint = "$issuer/discovery/v2.0/keys"
    HttpClient(CIO).use { client ->
        val jwksJson = client.get(jwksEndpoint).bodyAsText()
        return JWKSet.parse(jwksJson)
    }
}

3. 使用JWT验证保护路由

在需要验证令牌的路由上,添加authenticate("auth-jwt-aad")注解,KTor会自动解析请求中的Bearer令牌并完成验证:

routing {
    authenticate("auth-jwt-aad") {
        get("/protected") {
            val principal = call.principal<JWTPrincipal>()
            val userId = principal?.payload?.getClaim("oid")?.asString()
            call.respondText("Authenticated user ID: $userId")
        }
    }
}

关键验证说明

  • 签名验证:通过微软公开的JWKS密钥集验证令牌签名,确保令牌未被篡改
  • 签发者验证:确保令牌由指定的微软Azure AD租户签发
  • 受众验证:确保令牌是颁发给你的应用(匹配客户端ID)
  • 过期验证:JWT库会自动验证exp字段,确保令牌未过期

优化建议

  • 缓存JWKS密钥:微软的密钥不会频繁变动,可添加缓存逻辑避免每次请求都调用JWKS端点
  • 多租户适配:如果是多租户应用,可将租户ID设为common,但需额外验证租户合法性

内容的提问来源于stack exchange,提问作者Ranjith

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 20:12:37