diff --git a/api/pom.xml b/api/pom.xml
index ef64834..32470b9 100644
--- a/api/pom.xml
+++ b/api/pom.xml
@@ -16,6 +16,7 @@
2.6.0
6.5.4
6.3.3
+ 3.10.2
official
UTF-8
@@ -79,6 +80,11 @@
ktor-jackson
${ktor_version}
+
+ io.ktor
+ ktor-auth-jwt
+ ${ktor_version}
+
io.ktor
ktor-client-core
diff --git a/api/resources/application.conf b/api/resources/application.conf
index 04a5dd7..4b934ce 100644
--- a/api/resources/application.conf
+++ b/api/resources/application.conf
@@ -14,4 +14,9 @@ database {
name = "Notes"
user = "test"
password = "test"
+}
+
+jwt {
+ secret = "thisisasecret"
+ secret = ${?SECRET}
}
\ No newline at end of file
diff --git a/api/src/auth/AuthenticationModule.kt b/api/src/auth/AuthenticationModule.kt
new file mode 100644
index 0000000..1a9de0f
--- /dev/null
+++ b/api/src/auth/AuthenticationModule.kt
@@ -0,0 +1,21 @@
+package be.vandewalleh.auth
+
+import be.vandewalleh.kodein
+import io.ktor.application.Application
+import io.ktor.application.install
+import io.ktor.auth.Authentication
+import io.ktor.auth.UserIdPrincipal
+import io.ktor.auth.jwt.jwt
+import org.kodein.di.generic.instance
+
+fun Application.authenticationModule() {
+ install(Authentication) {
+ jwt {
+ val simpleJwt: SimpleJWT by kodein.instance()
+ verifier(simpleJwt.verifier)
+ validate {
+ UserIdPrincipal(it.payload.getClaim("name").asString())
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/api/src/auth/SimpleJWT.kt b/api/src/auth/SimpleJWT.kt
new file mode 100644
index 0000000..173a5c1
--- /dev/null
+++ b/api/src/auth/SimpleJWT.kt
@@ -0,0 +1,19 @@
+package be.vandewalleh.auth
+
+import com.auth0.jwt.JWT
+import com.auth0.jwt.JWTVerifier
+import com.auth0.jwt.algorithms.Algorithm
+import java.util.*
+
+class SimpleJWT(secret: String) {
+ private val validityInMs = 36_000_00 * 1
+ private val algorithm = Algorithm.HMAC256(secret)
+
+ val verifier: JWTVerifier = JWT.require(algorithm).build()
+ fun sign(name: String): String = JWT.create()
+ .withClaim("name", name)
+ .withExpiresAt(getExpiration())
+ .sign(algorithm)
+
+ private fun getExpiration() = Date(System.currentTimeMillis() + validityInMs)
+}
\ No newline at end of file
diff --git a/api/src/features/ConfigurationFeature.kt b/api/src/features/ConfigurationFeature.kt
index 9dc02d2..4a2f0ad 100644
--- a/api/src/features/ConfigurationFeature.kt
+++ b/api/src/features/ConfigurationFeature.kt
@@ -1,5 +1,6 @@
package be.vandewalleh.features
+import be.vandewalleh.auth.SimpleJWT
import io.ktor.application.Application
import org.kodein.di.Kodein
import org.kodein.di.generic.bind
@@ -27,7 +28,11 @@ fun Application.configurationFeature() {
setPassword(password)
}
}
+
+ val simpleJwt = SimpleJWT(environment.config.property("jwt.secret").getString())
+
configurationModule = Kodein.Module("Configuration") {
bind() with instance(dataSource)
+ bind() with instance(simpleJwt)
}
}
\ No newline at end of file
diff --git a/api/src/features/Features.kt b/api/src/features/Features.kt
index 3003579..b594a0f 100644
--- a/api/src/features/Features.kt
+++ b/api/src/features/Features.kt
@@ -1,14 +1,18 @@
package be.vandewalleh.features
+import be.vandewalleh.auth.authenticationModule
import io.ktor.application.Application
import org.kodein.di.Kodein
import org.kodein.di.KodeinAware
fun Application.features() {
+ // must be first to be loaded
+ configurationFeature()
+
locationFeature()
corsFeature()
contentNegotiationFeature()
- configurationFeature()
+ authenticationModule()
}
abstract class Feature(override val kodein: Kodein) : KodeinAware {