mirror of
https://github.com/dalbodeule/chibot-chzzk-bot.git
synced 2025-06-09 07:18:22 +00:00
add OAuth flows
- add naver OAuth flow
This commit is contained in:
parent
2f5c4293c0
commit
a828e23767
4
inc.env
4
inc.env
@ -6,5 +6,9 @@ DB_PASS=chzzk
|
|||||||
RUN_AGENT=false
|
RUN_AGENT=false
|
||||||
YOUTUBE_API_KEY=
|
YOUTUBE_API_KEY=
|
||||||
RAPID_KEY=
|
RAPID_KEY=
|
||||||
|
HOST=http://localhost:8080
|
||||||
|
FRONTEND=http://localhost:3000
|
||||||
|
NAVER_CLIENT_ID=
|
||||||
|
NAVER_CLIENT_SECRET=
|
||||||
NID_AUT=
|
NID_AUT=
|
||||||
NID_SES=
|
NID_SES=
|
@ -18,9 +18,14 @@ dependencies {
|
|||||||
implementation("io.ktor:ktor-server-websockets:$ktorVersion")
|
implementation("io.ktor:ktor-server-websockets:$ktorVersion")
|
||||||
implementation("io.ktor:ktor-server-swagger:$ktorVersion")
|
implementation("io.ktor:ktor-server-swagger:$ktorVersion")
|
||||||
implementation("io.ktor:ktor-server-content-negotiation:$ktorVersion")
|
implementation("io.ktor:ktor-server-content-negotiation:$ktorVersion")
|
||||||
implementation("io.ktor:ktor-serialization-kotlinx-json:$ktorVersion")
|
|
||||||
implementation("io.ktor:ktor-server-cors:$ktorVersion")
|
implementation("io.ktor:ktor-server-cors:$ktorVersion")
|
||||||
implementation("io.ktor:ktor-server-swagger:$ktorVersion")
|
implementation("io.ktor:ktor-server-swagger:$ktorVersion")
|
||||||
|
implementation("io.ktor:ktor-server-auth:$ktorVersion")
|
||||||
|
|
||||||
|
implementation("io.ktor:ktor-client-core:$ktorVersion")
|
||||||
|
implementation("io.ktor:ktor-client-cio:$ktorVersion")
|
||||||
|
implementation("io.ktor:ktor-client-content-negotiation:$ktorVersion")
|
||||||
|
implementation("io.ktor:ktor-serialization-kotlinx-json:$ktorVersion")
|
||||||
|
|
||||||
implementation("io.swagger.codegen.v3:swagger-codegen-generators:1.0.50")
|
implementation("io.swagger.codegen.v3:swagger-codegen-generators:1.0.50")
|
||||||
|
|
||||||
@ -35,6 +40,9 @@ dependencies {
|
|||||||
// https://mvnrepository.com/artifact/ch.qos.logback/logback-classic
|
// https://mvnrepository.com/artifact/ch.qos.logback/logback-classic
|
||||||
implementation("ch.qos.logback:logback-classic:1.5.6")
|
implementation("ch.qos.logback:logback-classic:1.5.6")
|
||||||
|
|
||||||
|
// https://mvnrepository.com/artifact/io.github.cdimascio/dotenv-kotlin
|
||||||
|
implementation("io.github.cdimascio:dotenv-kotlin:6.4.1")
|
||||||
|
|
||||||
implementation(project(":common"))
|
implementation(project(":common"))
|
||||||
|
|
||||||
testImplementation(kotlin("test"))
|
testImplementation(kotlin("test"))
|
||||||
|
@ -1,21 +1,38 @@
|
|||||||
package space.mori.chzzk_bot.webserver
|
package space.mori.chzzk_bot.webserver
|
||||||
|
|
||||||
|
import applicationHttpClient
|
||||||
|
import io.github.cdimascio.dotenv.dotenv
|
||||||
|
import io.ktor.client.call.*
|
||||||
|
import io.ktor.client.request.*
|
||||||
import io.ktor.http.*
|
import io.ktor.http.*
|
||||||
import io.ktor.serialization.kotlinx.*
|
import io.ktor.serialization.kotlinx.*
|
||||||
import io.ktor.serialization.kotlinx.json.*
|
import io.ktor.serialization.kotlinx.json.*
|
||||||
import io.ktor.server.application.*
|
import io.ktor.server.application.*
|
||||||
|
import io.ktor.server.auth.*
|
||||||
import io.ktor.server.engine.*
|
import io.ktor.server.engine.*
|
||||||
import io.ktor.server.netty.*
|
import io.ktor.server.netty.*
|
||||||
import io.ktor.server.plugins.contentnegotiation.*
|
import io.ktor.server.plugins.contentnegotiation.*
|
||||||
import io.ktor.server.plugins.cors.routing.*
|
import io.ktor.server.plugins.cors.routing.*
|
||||||
import io.ktor.server.plugins.swagger.*
|
import io.ktor.server.plugins.swagger.*
|
||||||
|
import io.ktor.server.response.*
|
||||||
import io.ktor.server.routing.*
|
import io.ktor.server.routing.*
|
||||||
|
import io.ktor.server.sessions.*
|
||||||
import io.ktor.server.websocket.*
|
import io.ktor.server.websocket.*
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
import kotlinx.serialization.json.Json
|
import kotlinx.serialization.json.Json
|
||||||
|
import space.mori.chzzk_bot.common.dotenv
|
||||||
import space.mori.chzzk_bot.webserver.routes.*
|
import space.mori.chzzk_bot.webserver.routes.*
|
||||||
import java.time.Duration
|
import java.time.Duration
|
||||||
|
|
||||||
val server = embeddedServer(Netty, port = 8080) {
|
val dotenv = dotenv {
|
||||||
|
ignoreIfMissing = true
|
||||||
|
}
|
||||||
|
|
||||||
|
const val naverMeAPIURL = "https://openapi.naver.com/v1/nid/me"
|
||||||
|
|
||||||
|
val redirects = mutableMapOf<String, String>()
|
||||||
|
|
||||||
|
val server = embeddedServer(Netty, port = 8080, ) {
|
||||||
install(WebSockets) {
|
install(WebSockets) {
|
||||||
pingPeriod = Duration.ofSeconds(15)
|
pingPeriod = Duration.ofSeconds(15)
|
||||||
timeout = Duration.ofSeconds(15)
|
timeout = Duration.ofSeconds(15)
|
||||||
@ -34,7 +51,66 @@ val server = embeddedServer(Netty, port = 8080) {
|
|||||||
anyHost()
|
anyHost()
|
||||||
allowHeader(HttpHeaders.ContentType)
|
allowHeader(HttpHeaders.ContentType)
|
||||||
}
|
}
|
||||||
|
install(Sessions) {
|
||||||
|
cookie<UserSession>("user_session", storage = SessionStorageMemory()) {}
|
||||||
|
}
|
||||||
|
install(Authentication) {
|
||||||
|
oauth("auth-oauth-naver") {
|
||||||
|
urlProvider = { "${dotenv["HOST"]}/auth/callback" }
|
||||||
|
providerLookup = { OAuthServerSettings.OAuth2ServerSettings(
|
||||||
|
name = "naver",
|
||||||
|
authorizeUrl = "https://nid.naver.com/oauth2.0/authorize",
|
||||||
|
accessTokenUrl = "https://nid.naver.com/oauth2.0/token",
|
||||||
|
requestMethod = HttpMethod.Post,
|
||||||
|
clientId = dotenv["NAVER_CLIENT_ID"],
|
||||||
|
clientSecret = dotenv["NAVER_CLIENT_SECRET"],
|
||||||
|
defaultScopes = listOf(""),
|
||||||
|
extraAuthParameters = listOf(),
|
||||||
|
onStateCreated = { call, state ->
|
||||||
|
//saves new state with redirect url value
|
||||||
|
call.request.queryParameters["redirectUrl"]?.let {
|
||||||
|
redirects[state] = it
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)}
|
||||||
|
client = applicationHttpClient
|
||||||
|
}
|
||||||
|
}
|
||||||
routing {
|
routing {
|
||||||
|
route("/auth") {
|
||||||
|
authenticate("auth-oauth-naver") {
|
||||||
|
get("/login") {
|
||||||
|
|
||||||
|
}
|
||||||
|
get("/callback") {
|
||||||
|
val currentPrincipal = call.principal<OAuthAccessTokenResponse.OAuth2>()
|
||||||
|
currentPrincipal?.let { principal ->
|
||||||
|
principal.state?.let { state ->
|
||||||
|
val userInfo: NaverAPI<NaverMeAPI> = applicationHttpClient.get(naverMeAPIURL) {
|
||||||
|
headers{
|
||||||
|
append(HttpHeaders.Authorization, "Bearer ${principal.accessToken}")
|
||||||
|
}
|
||||||
|
}.body()
|
||||||
|
|
||||||
|
call.sessions.set(userInfo.response?.let { it1 ->
|
||||||
|
UserSession(state,
|
||||||
|
it1.id, it1.nickname, it1.profile_image)
|
||||||
|
})
|
||||||
|
|
||||||
|
redirects[state]?.let { redirect ->
|
||||||
|
call.respondRedirect(redirect)
|
||||||
|
return@get
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
call.respondRedirect(dotenv["FRONTEND"])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
get("/logout") {
|
||||||
|
call.sessions.clear<UserSession>()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
apiRoutes()
|
apiRoutes()
|
||||||
apiSongRoutes()
|
apiSongRoutes()
|
||||||
wsTimerRoutes()
|
wsTimerRoutes()
|
||||||
@ -55,3 +131,21 @@ fun start() {
|
|||||||
fun stop() {
|
fun stop() {
|
||||||
server.stop()
|
server.stop()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class UserSession(
|
||||||
|
val state: String,
|
||||||
|
val id: String,
|
||||||
|
val nickname: String,
|
||||||
|
val profileImage: String
|
||||||
|
)
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class NaverMeAPI(
|
||||||
|
val id: String,
|
||||||
|
val nickname: String,
|
||||||
|
val profile_image: String
|
||||||
|
)
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class NaverAPI<T>(val resultcode: String, val message: String, val response: T?)
|
@ -0,0 +1,10 @@
|
|||||||
|
import io.ktor.client.*
|
||||||
|
import io.ktor.client.engine.cio.*
|
||||||
|
import io.ktor.client.plugins.contentnegotiation.*
|
||||||
|
import io.ktor.serialization.kotlinx.json.*
|
||||||
|
|
||||||
|
val applicationHttpClient = HttpClient(CIO) {
|
||||||
|
install(ContentNegotiation) {
|
||||||
|
json()
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user