Skip to content

Commit

Permalink
Unfinished changes 2
Browse files Browse the repository at this point in the history
  • Loading branch information
Ellet committed Dec 20, 2023
1 parent 4f22efa commit d588214
Show file tree
Hide file tree
Showing 18 changed files with 289 additions and 121 deletions.
4 changes: 2 additions & 2 deletions example/src/main/kotlin/plugins/AppCheck.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ package plugins

import io.ktor.server.application.*
import net.freshplatform.ktor_server.firebase_app_check.FirebaseAppCheckPlugin
import net.freshplatform.ktor_server.firebase_app_check.core.FirebaseAppCheckSecureStrategy
import net.freshplatform.ktor_server.firebase_app_check.services.FirebaseAppCheckTokenVerifierServiceImpl
import net.freshplatform.ktor_server.firebase_app_check.configurations.FirebaseAppCheckSecureStrategy
import net.freshplatform.ktor_server.firebase_app_check.FirebaseAppCheckTokenVerifierServiceImpl
import net.freshplatform.ktor_server.firebase_app_check.utils.FirebaseAppCheckMessages

fun Application.configureAppCheck() {
Expand Down
2 changes: 1 addition & 1 deletion example/src/main/kotlin/plugins/Routing.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import io.ktor.server.application.*
import io.ktor.server.plugins.statuspages.*
import io.ktor.server.response.*
import io.ktor.server.routing.*
import net.freshplatform.ktor_server.firebase_app_check.utils.extensions.protectRouteWithAppCheck
import net.freshplatform.ktor_server.firebase_app_check.utils.protectRouteWithAppCheck

class MissingEnvironmentVariableException(variableName: String) :
RuntimeException("The required environment variable '$variableName' is missing.")
Expand Down
11 changes: 0 additions & 11 deletions library/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
plugins {
alias(libs.plugins.kotlin.multiplatform)
// application
id("maven-publish")
}

Expand All @@ -12,10 +11,6 @@ version = libs.versions.library.get()
description =
"A Ktor server plugin for configuring Firebase App Check easily and with simplicity. It is not affiliated with Firebase or Google and may not be suitable for production use yet."

//application {
// mainClass.set("${group}.ktor_server.firebase_app_check.FirebaseAppCheckKt")
//}

kotlin {
jvm()
linuxX64()
Expand Down Expand Up @@ -46,12 +41,6 @@ kotlin {
implementation("io.ktor:ktor-server-tests-jvm:$ktorVersion")
}
}
// val nativeMain by creating {
// dependsOn(commonMain)
// }
// val nativeTest by creating {
// dependsOn(nativeMain)
// }
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@ package net.freshplatform.ktor_server.firebase_app_check
import io.ktor.server.application.*
import io.ktor.server.request.*
import io.ktor.util.*
import net.freshplatform.ktor_server.firebase_app_check.core.FirebaseAppCheckPluginConfiguration
import net.freshplatform.ktor_server.firebase_app_check.core.FirebaseAppCheckSecureStrategy
import net.freshplatform.ktor_server.firebase_app_check.service.FirebaseAppCheckTokenVerifierServiceUnimplemented
import net.freshplatform.ktor_server.firebase_app_check.utils.extensions.verifyAppTokenRequest
import net.freshplatform.ktor_server.firebase_app_check.configurations.FirebaseAppCheckPluginConfiguration
import net.freshplatform.ktor_server.firebase_app_check.configurations.FirebaseAppCheckSecureStrategy
import net.freshplatform.ktor_server.firebase_app_check.service.FirebaseAppCheckTokenVerifierServiceImpl
import net.freshplatform.ktor_server.firebase_app_check.utils.verifyAppTokenRequest

/**
* A Ktor server plugin for configuring Firebase App Check easily and with simplicity.
Expand All @@ -29,7 +29,7 @@ class FirebaseAppCheckPlugin(
configure: FirebaseAppCheckPluginConfiguration.() -> Unit
): FirebaseAppCheckPlugin {
val configuration = FirebaseAppCheckPluginConfiguration(
serviceImpl = FirebaseAppCheckTokenVerifierServiceUnimplemented()
serviceImpl = FirebaseAppCheckTokenVerifierServiceImpl()
)
.apply(configure)
require(configuration.firebaseProjectNumber.isNotBlank()) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package net.freshplatform.ktor_server.firebase_app_check.exceptions
package net.freshplatform.ktor_server.firebase_app_check

/**
* A custom exception class for Firebase App Check-related errors.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
package net.freshplatform.ktor_server.firebase_app_check.core
package net.freshplatform.ktor_server.firebase_app_check.configurations

import io.ktor.http.*
import io.ktor.server.application.*
import io.ktor.server.response.*
import net.freshplatform.ktor_server.firebase_app_check.exceptions.FirebaseAppCheckFetchPublicKeyErrorType
import net.freshplatform.ktor_server.firebase_app_check.exceptions.FirebaseAppCheckFetchPublicKeyErrorType.*
import net.freshplatform.ktor_server.firebase_app_check.exceptions.FirebaseAppCheckFetchPublicKeyException
import net.freshplatform.ktor_server.firebase_app_check.exceptions.FirebaseAppCheckVerifyJwtErrorType
import net.freshplatform.ktor_server.firebase_app_check.exceptions.FirebaseAppCheckVerifyJwtErrorType.*
import net.freshplatform.ktor_server.firebase_app_check.exceptions.FirebaseAppCheckVerifyJwtException
import net.freshplatform.ktor_server.firebase_app_check.FirebaseAppCheckFetchPublicKeyErrorType
import net.freshplatform.ktor_server.firebase_app_check.FirebaseAppCheckFetchPublicKeyErrorType.*
import net.freshplatform.ktor_server.firebase_app_check.FirebaseAppCheckFetchPublicKeyException
import net.freshplatform.ktor_server.firebase_app_check.FirebaseAppCheckVerifyJwtErrorType
import net.freshplatform.ktor_server.firebase_app_check.FirebaseAppCheckVerifyJwtErrorType.*
import net.freshplatform.ktor_server.firebase_app_check.FirebaseAppCheckVerifyJwtException
import net.freshplatform.ktor_server.firebase_app_check.service.FirebaseAppCheckTokenVerifierService
import net.freshplatform.ktor_server.firebase_app_check.services.jwt.DecodedJwt
import net.freshplatform.ktor_server.firebase_app_check.service.jwt.DecodedJwt
import net.freshplatform.ktor_server.firebase_app_check.utils.FirebaseAppCheckMessages
import net.freshplatform.ktor_server.firebase_app_check.utils.extensions.protectRouteWithAppCheck
import net.freshplatform.ktor_server.firebase_app_check.utils.protectRouteWithAppCheck

/**
* Configuration class for Firebase App Check plugin.
Expand Down Expand Up @@ -45,7 +45,7 @@ class FirebaseAppCheckPluginConfiguration(
var isShouldVerifyToken: Boolean? = null,
var firebaseAppCheckHeaderName: String = "X-Firebase-AppCheck",
var firebaseAppCheckApiBaseUrl: String = "https://firebaseappcheck.googleapis.com",
var firebaseAppCheckPublicJwtSetUrl: String = "${firebaseAppCheckApiBaseUrl}/v1/jwks",
var firebaseAppCheckPublicKeyUrl: String = "${firebaseAppCheckApiBaseUrl}/v1/jwks",
var secureStrategy: FirebaseAppCheckSecureStrategy = FirebaseAppCheckSecureStrategy.ProtectSpecificRoutes,
var additionalSecurityCheck: suspend (decodedJwt: DecodedJwt) -> Boolean = {
true
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package net.freshplatform.ktor_server.firebase_app_check.core
package net.freshplatform.ktor_server.firebase_app_check.configurations

import net.freshplatform.ktor_server.firebase_app_check.utils.extensions.protectRouteWithAppCheck
import net.freshplatform.ktor_server.firebase_app_check.utils.protectRouteWithAppCheck

/**
* A sealed class that defines different strategies for securing routes with Firebase App Check.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
package net.freshplatform.ktor_server.firebase_app_check.service

import net.freshplatform.ktor_server.firebase_app_check.services.jwt.DecodedJwt
import net.freshplatform.ktor_server.firebase_app_check.service.jwt.DecodedJwt
import kotlin.time.Duration
import kotlin.time.Duration.Companion.hours
import kotlin.time.Duration.Companion.minutes


/**
Expand Down Expand Up @@ -36,41 +35,30 @@ data class FetchFirebaseAppCheckPublicKeyCacheConfig(
* @param enabled
*/
data class FetchFirebaseAppCheckPublicKeyRateLimitedConfig(
val enabled: Boolean
val enabled: Boolean = true
)

/**
* Object containing functions for fetching and verifying Firebase App Check tokens.
*/
interface FirebaseAppCheckTokenVerifierService {
/**
* Suspended function to fetch a Firebase App Check a public key.
*
* @param jwtString to get the kid which is the Key ID.
* @param url The URL for fetching the public key.
* @param config Configuration for public key fetching.
* @return The fetched public key.
*/
suspend fun fetchFirebaseAppCheckPublicKey(
jwtString: String, url: String,
config: FetchFirebaseAppCheckPublicKeyConfig = FetchFirebaseAppCheckPublicKeyConfig()
): PublicKey

/**
* Suspended function to verify a Firebase App Check token.
*
* @param jwtString The JWT string to be verified.
* @param publicKey The public key used for verification.
* @param firebaseAppCheckTokenJwt The JWT string to be verified.
* @param firebaseProjectId The Firebase project ID.
* @param firebaseProjectNumber The Firebase project number.
* @param issuerBaseUrl The base URL of the Firebase App Check issuer.
* @return The verified Decoded JWT.
*/
suspend fun verifyFirebaseAppCheckToken(
jwtString: String,
publicKey: PublicKey,
firebaseAppCheckTokenJwt: String,
firebaseProjectId: String,
firebaseProjectNumber: String,
issuerBaseUrl: String
issuerBaseUrl: String,
publicKeyUrl: String
): DecodedJwt
}
}

expect class FirebaseAppCheckTokenVerifierServiceImpl(): FirebaseAppCheckTokenVerifierService
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package net.freshplatform.ktor_server.firebase_app_check.services.jwt
package net.freshplatform.ktor_server.firebase_app_check.service.jwt


data class DecodedJwt(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
package net.freshplatform.ktor_server.firebase_app_check.utils.extensions
package net.freshplatform.ktor_server.firebase_app_check.utils

import io.ktor.http.*
import io.ktor.server.application.*
import io.ktor.server.request.*
import io.ktor.server.response.*
import io.ktor.server.routing.*
import net.freshplatform.ktor_server.firebase_app_check.FirebaseAppCheckPlugin
import net.freshplatform.ktor_server.firebase_app_check.core.FirebaseAppCheckSecureStrategy
import net.freshplatform.ktor_server.firebase_app_check.service.FetchFirebaseAppCheckPublicKeyConfig
import net.freshplatform.ktor_server.firebase_app_check.configurations.FirebaseAppCheckSecureStrategy

/**
* A suspended function that verifies an incoming Firebase App Check token for an [ApplicationCall].
Expand Down Expand Up @@ -38,17 +37,12 @@ suspend fun ApplicationCall.verifyAppTokenRequest() {

try {

val publicKey = pluginConfig.serviceImpl.fetchFirebaseAppCheckPublicKey(
jwtString = firebaseAppCheckToken,
url = pluginConfig.firebaseAppCheckPublicJwtSetUrl,
config = FetchFirebaseAppCheckPublicKeyConfig()
)
val verifiedJwt = pluginConfig.serviceImpl.verifyFirebaseAppCheckToken(
firebaseProjectId = pluginConfig.firebaseProjectId,
firebaseProjectNumber = pluginConfig.firebaseProjectNumber,
jwtString = firebaseAppCheckToken,
publicKey = publicKey,
issuerBaseUrl = pluginConfig.firebaseAppCheckApiBaseUrl
firebaseAppCheckTokenJwt = firebaseAppCheckToken,
issuerBaseUrl = pluginConfig.firebaseAppCheckApiBaseUrl,
publicKeyUrl = pluginConfig.firebaseAppCheckPublicKeyUrl
)
// Optional: Check that the token’s subject matches your app’s App ID.
val isShouldContinue = pluginConfig.additionalSecurityCheck(verifiedJwt)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package net.freshplatform.ktor_server.firebase_app_check.utils

import net.freshplatform.ktor_server.firebase_app_check.core.FirebaseAppCheckPluginConfiguration
import net.freshplatform.ktor_server.firebase_app_check.configurations.FirebaseAppCheckPluginConfiguration

/**
* Data class containing messages related to Firebase App Check.
Expand Down
Empty file.
Original file line number Diff line number Diff line change
@@ -1,26 +1,42 @@
package net.freshplatform.ktor_server.firebase_app_check.services
package net.freshplatform.ktor_server.firebase_app_check

import com.auth0.jwk.*
import com.auth0.jwt.JWT
import com.auth0.jwt.algorithms.Algorithm
import com.auth0.jwt.exceptions.*
import com.auth0.jwt.interfaces.DecodedJWT
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import net.freshplatform.ktor_server.firebase_app_check.exceptions.FirebaseAppCheckFetchPublicKeyErrorType
import net.freshplatform.ktor_server.firebase_app_check.exceptions.FirebaseAppCheckFetchPublicKeyException
import net.freshplatform.ktor_server.firebase_app_check.exceptions.FirebaseAppCheckVerifyJwtErrorType
import net.freshplatform.ktor_server.firebase_app_check.exceptions.FirebaseAppCheckVerifyJwtException
import net.freshplatform.ktor_server.firebase_app_check.service.FetchFirebaseAppCheckPublicKeyConfig
import net.freshplatform.ktor_server.firebase_app_check.service.FirebaseAppCheckTokenVerifierService
import net.freshplatform.ktor_server.firebase_app_check.services.jwt.DecodedJwt
import net.freshplatform.ktor_server.firebase_app_check.service.jwt.DecodedJwt
import java.net.URL
import java.security.PublicKey
import java.security.interfaces.RSAPublicKey
import kotlin.time.toJavaDuration

class FirebaseAppCheckTokenVerifierServiceImpl : FirebaseAppCheckTokenVerifierService {
override suspend fun fetchFirebaseAppCheckPublicKey(
override suspend fun verifyFirebaseAppCheckToken(
firebaseAppCheckTokenJwt: String,
firebaseProjectId: String,
firebaseProjectNumber: String,
issuerBaseUrl: String,
publicKeyUrl: String
): DecodedJwt {
val publicKey = fetchFirebaseAppCheckPublicKey(
jwtString = firebaseAppCheckTokenJwt,
url = publicKeyUrl,
config = FetchFirebaseAppCheckPublicKeyConfig()
)
val verifiedJwt = verifyFirebaseAppCheckToken(
firebaseProjectId = firebaseProjectId,
firebaseProjectNumber = firebaseProjectNumber,
jwtString = firebaseAppCheckTokenJwt,
publicKey = publicKey,
issuerBaseUrl = issuerBaseUrl
)
return verifiedJwt
}
private suspend fun fetchFirebaseAppCheckPublicKey(
jwtString: String,
url: String,
config: FetchFirebaseAppCheckPublicKeyConfig
Expand Down Expand Up @@ -102,7 +118,7 @@ class FirebaseAppCheckTokenVerifierServiceImpl : FirebaseAppCheckTokenVerifierSe
}
}

override suspend fun verifyFirebaseAppCheckToken(
private suspend fun verifyFirebaseAppCheckToken(
jwtString: String,
publicKey: PublicKey,
firebaseProjectId: String,
Expand Down Expand Up @@ -168,4 +184,5 @@ class FirebaseAppCheckTokenVerifierServiceImpl : FirebaseAppCheckTokenVerifierSe
}
}
}

}
Loading

0 comments on commit d588214

Please sign in to comment.