Everything is working but, I have the following q...
# ktor
g
Everything is working but, I have the following questions: 1 - How can I setup refreshToken logic? I’ve searched in the docs/samples but I must have missed, can you point me to it? Btw, Google sends a null refreshToken, how will I manage auth-refresh in this case? 2 - Is authentication well configured? I thought I should incapsulate both Route.data and Route.dataApi with authenticate but if I wrap Route.dataApi for some reason I’ll receive a “400. That’s an error. Your client has issued a malformed or illegal request. ” from Google 😕 (both with SESSION_AUTH or GOOGLE_OAUTH). Why? 3 - How can I redirect to the page that asked for authentication in the client webApp? For instance, if I try to go to /data it asks for authentication (Route.login) and after success it fires call.redirect(Home()), how can I redirect to the Location that asked for auth? Thanks for you time! 🙏
🧵 4
Regarding question number 3, I solved it by doing the following: webApp/Auth.kt
Copy code
const val REDIRECT_LOCATION = "redirectLocation"

@KtorExperimentalLocationsAPI
@Location("/login/{provider?}/{redirectLocation?}")
class Login(val provider: String = "google", val redirectLocation: String = "")

@KtorExperimentalLocationsAPI
fun Route.login(client: HttpClient) {
    authenticate(GOOGLE_OAUTH) {
        get<Login> { params ->
            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 ?: ""))
                val to: Any = when(params.redirectLocation) {
                    AuthenticationRedirect.Reservations.toString() -> Reservations()
                    else -> Home()
                }
                call.redirect(to)
            } else {
                call.respond(status = HttpStatusCode.Unauthorized, "Unauthorized, no token issued")
            }
        }.param("error") {
            handle {
                call.respond(status = HttpStatusCode.Unauthorized, call.parameters.getAll("error").orEmpty().joinToString(", "))
            }
        }
    }
}
Added this class since I could not pass Any as a parameter of
@Location
Copy code
sealed class AuthenticationRedirect {
    object Home : AuthenticationRedirect() {
        override fun toString(): String = "home"
    }

    object Reservations : AuthenticationRedirect() {
        override fun toString(): String = "reservations"
    }
}
Application.kt
Copy code
urlProvider = { p -> redirectUrl(Login(p.name, request.call.parameters[REDIRECT_LOCATION] ?: ""), false) }
Finally, had to add the same redirect locations in my Project web client configurations in Cloud Console. Don’t know if this is the best approach, but it’s working 🤔