Hello, I’ve a few questions regarding authenticati...
# ktor
g
Hello, I’ve a few questions regarding authentication with Google oAuth. I’m developing a Server and a webApp. For now the Server acts like a proxy between webApp and a Google API (down the road I’ll add some custom logic to justify the existence of the SS, but for now existis for the purpose of the exercise). The idea is: - webApp has a few .ftl pages and respective Routing Locations. One of this .ftl needs authentication (to fetch data from Google Api through Server) - Server communicates with Google API using the AccessToken provided by Google OAuth to the webApp This is my configuration: Application.kt
Copy code
install(Sessions) {
    cookie<Session>(SESSION_COOKIE) {
        cookie.extensions["SameSite"] = "lax"
        transform(SessionTransportTransformerMessageAuthentication(hex(...)))
    }
}
install(Authentication) {
    session<Session>(SESSION_AUTH) {
        challenge { throw AuthenticationException() }
        validate { session -> if (session.accessToken.isEmpty()) null else session }
    }
    oauth(GOOGLE_OAUTH) {
        client = httpClient
        providerLookup = {
            OAuthServerSettings.OAuth2ServerSettings(
                name = "google",
                authorizeUrl = "<https://accounts.google.com/o/oauth2/auth>",
                accessTokenUrl = "<https://www.googleapis.com/oauth2/v3/token>",
                requestMethod = <http://HttpMethod.Post|HttpMethod.Post>,
                ...
            )
        }
        urlProvider = { p -> redirectUrl(Login(p.name), false) }
    }
}
webApp/Auth.kt
Copy code
@KtorExperimentalLocationsAPI
@Location("/login/{provider?}")
class Login(val provider: String = "google")

@KtorExperimentalLocationsAPI
fun Route.login(client: HttpClient) {
    authenticate(GOOGLE_OAUTH) {
        location<Login> {
            param("error") { handle {...} }
            handle {
                val principal = call.authentication.principal<OAuthAccessTokenResponse>()
                if (principal != null) {
                    val oauth = call.authentication.principal<OAuthAccessTokenResponse.OAuth2>()!!
                    val response = client.get<UserInfo>("<https://www.googleapis.com/oauth2/v1/userinfo>") {
                        header(HttpHeaders.Authorization, "Bearer ${oauth.accessToken}")
                    }
                    call.sessions.set(Session(response, oauth.accessToken, oauth.refreshToken?: ""))
                    call.redirect(Home())
                } else {
                    call.respond(status = HttpStatusCode.Unauthorized, "Unauthorized, no token issued")
                }
            }
        }
    }
}
webApp/Data.kt
Copy code
@KtorExperimentalLocationsAPI
@Location("/data")
class Data

@KtorExperimentalLocationsAPI
fun Route.data(client: HttpClient) {
    authenticate(SESSION_AUTH) {
        get<Data> {
        	val response = client.get<Info>("<http://localhost:8080>${application.locationToUrl(DataApi())}") {
                    header(HttpHeaders.Authorization, "Bearer ${call.getSession()?.accessToken}")
                    ...
            }
            ...
        }
        post<Data> {...}
    }
}
api/DataApi.kt
Copy code
@KtorExperimentalLocationsAPI
@Location("$API_VERSION/data")
class DataApi

@KtorExperimentalLocationsAPI
fun Route.dataApi(client: HttpClient) {
//    authenticate(SESSION_AUTH) {
        get<DataApi> {
        	...
            val response = client.get<SomeApiData>("<https://www.googleapis.com/>...") {
                    parameter("key", params.apiKey)
                    header(HttpHeaders.Authorization, call.request.headers[HttpHeaders.Authorization])
            }
            ...
        }
        post<DataApi> {...}
//    }
}
Hello @Big Chungus , I’m new in kotlinlang 😅, so let me ask if your 🧵 reaction means to encourage people to respond in thread and not on “the open”, or if I should place my question in a different format.
b
Given the length of your post it's basically an invitation to only leave the summary in the main post and move elaboration in a thread. That way you don't take up as much screen real estate. Remember, there's shitloads of us here, so we need to be respectful of each other and try and avoid spamming main channel.
Also any further clarifications should also go to thread and not as a separate message
g
yes of course, I’ll change it, that’s why I’ve questioned, I don’t want to break rules 🙂
b
It's more of an unwritten rure, really. So don't fret! 😀
g
eheh i’m new to “global slack” that’s why I’m still getting used to it ^^
should I delete my question and create a new one, or edit? 🤔
b
Don't bother, leave those as is. Just keep this in mind for the future
👍 1