Skip to content

Commit

Permalink
Restore flank auth login
Browse files Browse the repository at this point in the history
  • Loading branch information
bootstraponline committed Feb 23, 2019
1 parent fcb2cec commit 2dc554c
Show file tree
Hide file tree
Showing 6 changed files with 131 additions and 75 deletions.
10 changes: 5 additions & 5 deletions test_runner/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -127,13 +127,13 @@ dependencies {
testImplementation("com.github.stefanbirkner:system-rules:1.19.0")

// https://github.com/ktorio/ktor/releases
val ktorVersion = "1.1.1"
testImplementation("io.ktor:ktor-server-core:$ktorVersion")
testImplementation("io.ktor:ktor-server-netty:$ktorVersion")
testImplementation("io.ktor:ktor-gson:$ktorVersion")
val ktorVersion = "1.1.3"
compile("io.ktor:ktor-server-core:$ktorVersion")
compile("io.ktor:ktor-server-netty:$ktorVersion")
compile("io.ktor:ktor-gson:$ktorVersion")

// https://github.com/qos-ch/logback/releases
testImplementation("ch.qos.logback:logback-classic:1.2.3")
compile("ch.qos.logback:logback-classic:1.2.3")
// mockito-inline is used to mock final classes
// https://github.com/mockito/mockito/releases
testImplementation("org.mockito:mockito-inline:2.23.4")
Expand Down
2 changes: 2 additions & 0 deletions test_runner/src/main/kotlin/ftl/cli/auth/LoginCommand.kt
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package ftl.cli.auth

import ftl.gc.UserAuth
import picocli.CommandLine

@CommandLine.Command(
Expand All @@ -15,6 +16,7 @@ import picocli.CommandLine
)
class LoginCommand : Runnable {
override fun run() {
UserAuth().request()
}

@CommandLine.Option(
Expand Down
12 changes: 8 additions & 4 deletions test_runner/src/main/kotlin/ftl/config/FtlConstants.kt
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import com.google.auth.oauth2.ServiceAccountCredentials
import ftl.args.AndroidArgs
import ftl.args.IArgs
import ftl.args.IosArgs
import ftl.gc.UserAuth
import ftl.http.HttpTimeoutIncrease
import java.nio.file.Path
import java.nio.file.Paths
Expand Down Expand Up @@ -48,15 +49,18 @@ object FtlConstants {
if (useMock) {
HttpRequestInitializer {}
} else {
val credential = if (UserAuth.exists()) {
UserAuth.load()
} else {
ServiceAccountCredentials.getApplicationDefault()
}

// Authenticate with https://github.com/googleapis/google-auth-library-java
// Scope is required.
// https://developers.google.com/identity/protocols/googlescopes
// https://developers.google.com/identity/protocols/application-default-credentials
// https://cloud.google.com/sdk/gcloud/reference/alpha/compute/instances/set-scopes
HttpTimeoutIncrease(
ServiceAccountCredentials.getApplicationDefault()
.createScoped(listOf("https://www.googleapis.com/auth/cloud-platform"))
)
HttpTimeoutIncrease(credential.createScoped(listOf("https://www.googleapis.com/auth/cloud-platform")))
}
}

Expand Down
57 changes: 0 additions & 57 deletions test_runner/src/main/kotlin/ftl/gc/GcAuth.kt

This file was deleted.

112 changes: 112 additions & 0 deletions test_runner/src/main/kotlin/ftl/gc/UserAuth.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
package ftl.gc

import ch.qos.logback.classic.Level
import ch.qos.logback.classic.Logger
import com.google.auth.oauth2.ClientId
import com.google.auth.oauth2.MemoryTokensStorage
import com.google.auth.oauth2.UserAuthorizer
import com.google.auth.oauth2.UserCredentials
import io.ktor.application.call
import io.ktor.response.respondText
import io.ktor.routing.get
import io.ktor.routing.routing
import io.ktor.server.engine.embeddedServer
import io.ktor.server.netty.Netty
import java.io.FileInputStream
import java.io.FileOutputStream
import java.io.ObjectInputStream
import java.io.ObjectOutputStream
import java.net.URI
import java.nio.file.Path
import java.nio.file.Paths
import java.util.concurrent.TimeUnit
import kotlinx.coroutines.delay
import kotlinx.coroutines.runBlocking
import org.slf4j.LoggerFactory

class UserAuth {

companion object {
private val home = System.getProperty("user.home")!!
private val dotFlank = Paths.get(home, ".flank/")!!
val userToken: Path = Paths.get(dotFlank.toString(), "UserToken")

fun exists() = userToken.toFile().exists()
fun load(): UserCredentials {
return ObjectInputStream(FileInputStream(userToken.toFile())).use {
it.readObject() as UserCredentials
}
}
}

// Silence Jetty logging.
private val logger = LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME) as Logger

init {
logger.level = Level.OFF
}

private var waitingForUserAuth = true

private val server = embeddedServer(Netty, 8085) {
routing {
// 'code' and 'scope' are passed back into the callback as parameters
get("/oauth2callback") {
authCode = call.parameters["code"] ?: ""
call.respondText { "User authorized. Close the browser window." }

waitingForUserAuth = false
}
}
}

var authCode = ""

// https://github.com/bootstraponline/gcloud_cli/blob/40521a6e297830b9f652a9ab4d8002e309b4353a/google-cloud-sdk/platform/gsutil/gslib/utils/system_util.py#L177
private val clientId = ClientId.newBuilder()
.setClientId("32555940559.apps.googleusercontent.com")
.setClientSecret("ZmssLNjJy2998hD4CTg2ejr2")
.build()!!

// https://github.com/bootstraponline/gcloud_cli/blob/e4b5e01610abad2e31d8a6edb20b17b2f84c5395/google-cloud-sdk/lib/googlecloudsdk/core/config.py#L167
private val scopes = listOf("https://www.googleapis.com/auth/cloud-platform")

private val tokenStore = MemoryTokensStorage()
private val authorizer = UserAuthorizer.newBuilder()
.setClientId(clientId)
.setScopes(scopes)
.setTokenStore(tokenStore)
.build()!!
private val userId = "flank"
val uri: URI = URI.create("http://localhost:8085")

private fun printAuthorizationUrl() {
val url = authorizer.getAuthorizationUrl(userId, null, uri)
println("Visit the following URL in your browser:")
println(url)
}

fun request() {
printAuthorizationUrl()

server.start(wait = false)

while (waitingForUserAuth) {
runBlocking { delay(1000) }
}

// trade OAuth2 authorization code for tokens.
//
// https://developers.google.com/gdata/docs/auth/oauth#NoLibrary
authorizer.getAndStoreCredentialsFromCode(userId, authCode, uri)

server.stop(0, 0, TimeUnit.SECONDS)

val userCredential = authorizer.getCredentials(userId)

dotFlank.toFile().mkdirs()
ObjectOutputStream(FileOutputStream(userToken.toFile())).use {
it.writeObject(userCredential)
}
}
}
13 changes: 4 additions & 9 deletions test_runner/src/test/kotlin/Debug.kt
Original file line number Diff line number Diff line change
@@ -1,14 +1,9 @@
import ftl.Main
import picocli.CommandLine

object Debug {
fun main() {
// GoogleApiLogger.logAllToStdout()

@JvmStatic
@Suppress("UnusedPrivateMember") // Suppress detekt rule
fun main(args: Array<String>) {
// GoogleApiLogger.logAllToStdout()

val arguments = arrayOf("firebase", "test", "android", "run") // for debugging. run test from IntelliJ IDEA
CommandLine.run<Runnable>(Main(), System.out, *arguments)
}
val arguments = arrayOf("firebase", "test", "android", "run") // for debugging. run test from IntelliJ IDEA
CommandLine.run<Runnable>(Main(), System.out, *arguments)
}

0 comments on commit 2dc554c

Please sign in to comment.