所以我正在尝试为 Kotlin、Ktor 设置 OAuth。我试图遵循 documentation 但我陷入了config part上step 2 。当我的程序运行时:
call.request.queryParameters["redirectUrl"]!!
我得到一个空点异常。在调试器模式下运行程序时,我可以看到 call/request/queryParameters 不为空。所以应该是“redirectUrl”不“工作”。
我试图搜索该行的用途,但我在任何地方都找不到它的任何解释。我只能在这个文档中找到它的用途。我认为它应该获得一些重定向 URL,但我不知道从哪里获得。
如何解决我的零点异常?
如果有帮助的话,这是我的类(class)
package com.example.plugins
import io.ktor.server.auth.*
import io.ktor.client.*
import io.ktor.client.engine.apache.*
import io.ktor.http.*
import io.ktor.serialization.kotlinx.json.*
import io.ktor.server.sessions.*
import io.ktor.server.response.*
import io.ktor.server.application.*
import io.ktor.server.plugins.contentnegotiation.*
import io.ktor.server.routing.*
fun Application.configureSecurity() {
val redirects = mutableMapOf<String, String>()
authentication {
oauth("auth-oauth-google") {
urlProvider = { "http://localhost:8086/callback" }
providerLookup = {
OAuthServerSettings.OAuth2ServerSettings(
name = "google",
authorizeUrl = "https://accounts.google.com/o/oauth2/auth",
accessTokenUrl = "https://accounts.google.com/o/oauth2/token",
requestMethod = HttpMethod.Post,
clientId = System.getenv("GOOGLE_CLIENT_ID"),
clientSecret = System.getenv("GOOGLE_CLIENT_SECRET"),
defaultScopes = listOf("https://www.googleapis.com/auth/userinfo.profile"),
extraAuthParameters = listOf("access_type" to "offline"),
onStateCreated = { call, state ->
redirects[state] = call.request.queryParameters["redirectUrl"]!!
}
)
}
client = HttpClient(Apache)
}
}
data class MySession(val count: Int = 0)
install(Sessions) {
cookie<MySession>("MY_SESSION") {
cookie.extensions["SameSite"] = "lax"
cookie.maxAgeInSeconds = 120
cookie.path = "/testing"
}
cookie<UserSession>("USER_SESSION") {
cookie.extensions["SameSite"] = "lax"
cookie.maxAgeInSeconds = 120
cookie.path = "/testingss"
}
}
routing {
authenticate("auth-oauth-google") {
get("login") {
call.respondRedirect("/callback")
}
get("/callback") {
val principal: OAuthAccessTokenResponse.OAuth2? = call.principal()
call.sessions.set(UserSession(principal!!.state!!, principal.accessToken))
val redirect = redirects[principal.state!!]
call.respondRedirect(redirect!!)
}
}
get("/session/increment") {
val session = call.sessions.get<MySession>() ?: MySession()
call.sessions.set(session.copy(count = session.count + 1))
call.respondText("Counter is ${session.count}. Refresh to increment.")
}
}
}
最佳答案
如果您需要将客户端重定向到其来源的 URL,请将查询参数 redirectUrl
(实际名称无关紧要,但必须一致)添加到 /login
端点。以下是流程的步骤:
- 客户端请求不 protected 端点
- 如果 session 不存在(客户端未经身份验证),服务器将使用查询参数
redirectUrl
重定向到/login
进行响应,其中包含所请求的 URL。 /login
端点会触发 OAuth2 身份验证,当创建state
时,redirectUrl
将保存到redirects
映射到onStateCreated
block 内。- OAuth2 提供商将客户端重定向到回调 URL,其中重定向发生在之前保存的 URL。
这是一个例子:
get("/{path}") {
val userSession: UserSession? = call.sessions.get()
if (userSession != null) {
val userInfo: UserInfo = httpClient.get("https://www.googleapis.com/oauth2/v2/userinfo") {
headers {
append(HttpHeaders.Authorization, "Bearer ${userSession.token}")
}
}.body()
call.respondText("Hello, ${userInfo.name}!")
} else {
val redirectUrl = URLBuilder("http://0.0.0.0:8080/login").run {
parameters.append("redirectUrl", call.request.uri)
build()
}
call.respondRedirect(redirectUrl)
}
}
关于kotlin - 尝试使用 Ktor 设置 OAuth,providerLookup 问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/75579794/