https://kotlinlang.org logo
Title
g

Guilherme Delgado

04/26/2021, 4:38 PM
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
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
@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
@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
@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 :thread-please: 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

Big Chungus

04/28/2021, 8:59 AM
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

Guilherme Delgado

04/28/2021, 9:01 AM
yes of course, I’ll change it, that’s why I’ve questioned, I don’t want to break rules 🙂
b

Big Chungus

04/28/2021, 9:01 AM
It's more of an unwritten rure, really. So don't fret! 😀
g

Guilherme Delgado

04/28/2021, 9:02 AM
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

Big Chungus

04/28/2021, 9:02 AM
Don't bother, leave those as is. Just keep this in mind for the future
👍 1