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

c9x0cxw0  于 2023-03-03  发布在  Kotlin
关注(0)|答案(1)|浏览(189)

所以我试图为Kotlin,Ktor设置OAuth。我试图遵循documentation,但我在第2步的配置部分卡住了。当我的程序运行时:

call.request.queryParameters["redirectUrl"]!!

我得到了一个空点异常。当在调试器模式下运行程序时,我可以看到call/request/queryParameters不为空。所以应该是“redirectUrl”没有“工作”。
我试着搜索这行代码的用途,但我在任何地方都找不到任何解释。我只能在本文档中找到它的用法。我假设它应该是用来获得一些重定向的URL,但我不知道从哪里来的。
如何解决零点异常?
这是我的课如果有用的话

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.")
    }
}

}

w46czmvw

w46czmvw1#

如果需要将客户端重定向到它原来的URL,可以在/login端点上添加查询参数redirectUrl(实际名称不重要,但必须保持一致),流程如下:
1.客户端请求未受保护的端点
1.如果会话不存在(客户端未经身份验证),服务器将使用包含请求的URL的查询参数redirectUrl重定向到/login

  1. /login端点触发OAuth2身份验证,并且在创建state时,redirectUrl被保存到onStateCreated块内的redirectsMap。
    1.客户端由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)
    }
}

相关问题