kotlin - 尝试使用 Ktor 设置 OAuth,providerLookup 问题

标签 kotlin oauth nullpointerexception ktor

所以我正在尝试为 Kotlin、Ktor 设置 OAuth。我试图遵循 documentation 但我陷入了config partstep 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 端点。以下是流程的步骤:

  1. 客户端请求不 protected 端点
  2. 如果 session 不存在(客户端未经身份验证),服务器将使用查询参数 redirectUrl 重定向到 /login 进行响应,其中包含所请求的 URL。
  3. /login 端点会触发 OAuth2 身份验证,当创建 state 时,redirectUrl 将保存到 redirects 映射到 onStateCreated block 内。
  4. 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/

相关文章:

grails - Grails oauth无法正常运行

java - 我可以从此例程中得到空指针异常吗?

java - 如果有父级,Quarkus 不会构建

android - 为什么 android studio 不为所有安全参数生成代码?

kotlin - Kotlin 如何通过运行示例解释 {} 或 ()

Android 应用程序使用 google 帐户登录

c# - 基于客户端特定角色的身份验证?

java - 如何用java读取我电脑中的所有mp3文件?

java - 替换 fragment 时出现 NullpointerException

generics - 如何规避 Kotlin 的限制 "Type parameter is forbidden for catch parameter"