diff --git a/Sources/pom.xml b/Sources/pom.xml
index f4258f4..6107ebe 100644
--- a/Sources/pom.xml
+++ b/Sources/pom.xml
@@ -68,6 +68,11 @@
ktor-server-content-negotiation-jvm
${ktor_version}
+
+ io.ktor
+ ktor-server-auth-jwt
+ ${ktor_version}
+
io.ktor
ktor-server-html-builder-jvm
@@ -105,6 +110,23 @@
ktor-server-content-negotiation-jvm
${ktor_version}
+
+ io.ktor
+ ktor-server-auth-jvm
+ 2.3.4
+ implementation
+
+
+ io.ktor
+ ktor-server-auth-jwt-jvm
+ 2.3.4
+ implementation
+
+
+ com.auth0
+ java-jwt
+ 4.4.0
+
${project.basedir}/src/main/kotlin
diff --git a/Sources/src/main/kotlin/allin/Application.kt b/Sources/src/main/kotlin/allin/Application.kt
index 15afe0f..cde6981 100644
--- a/Sources/src/main/kotlin/allin/Application.kt
+++ b/Sources/src/main/kotlin/allin/Application.kt
@@ -2,22 +2,47 @@ package allin
import allin.routing.BasicRouting
import allin.routing.UserRouter
+import allin.routing.tokenManager
+import com.auth0.jwt.JWT
+import com.auth0.jwt.algorithms.Algorithm
+import com.typesafe.config.ConfigFactory
import io.ktor.http.*
import io.ktor.serialization.kotlinx.json.*
import io.ktor.server.application.*
+import io.ktor.server.application.*
+import io.ktor.server.auth.*
+import io.ktor.server.auth.*
+import io.ktor.server.auth.jwt.*
+import io.ktor.server.config.*
import io.ktor.server.engine.*
import io.ktor.server.netty.*
import io.ktor.server.plugins.contentnegotiation.*
import io.ktor.server.response.*
+import io.ktor.server.response.*
import io.ktor.server.routing.*
+import io.ktor.server.routing.*
+import allin.utils.TokenManager
fun main() {
- embeddedServer(Netty,port=8080,host="0.0.0.0"){
+ embeddedServer(Netty, port = 8080, host = "0.0.0.0") {
extracted()
}.start(wait = true)
}
private fun Application.extracted() {
+ val config=HoconApplicationConfig(ConfigFactory.load())
+ val tokenManager= TokenManager(config)
+ authentication {
+ jwt {
+ verifier(tokenManager.verifyJWTToken())
+ realm=config.property("realm").getString()
+ validate { jwtCredential ->
+ if(jwtCredential.payload.getClaim("username").asString().isNotEmpty())
+ JWTPrincipal(jwtCredential.payload)
+ else null
+ }
+ }
+ }
install(ContentNegotiation) {
json()
}
diff --git a/Sources/src/main/kotlin/allin/model/User.kt b/Sources/src/main/kotlin/allin/model/User.kt
index 503ebda..418c230 100644
--- a/Sources/src/main/kotlin/allin/model/User.kt
+++ b/Sources/src/main/kotlin/allin/model/User.kt
@@ -3,12 +3,7 @@ package allin.model
import kotlinx.serialization.Serializable
@Serializable
-data class User(val username: String, val email: String, val password: String, var nbCoins: Int = 1000)
+data class User(val username: String, val email: String, val password: String, var nbCoins: Int = 1000, var token: String? = null)
@Serializable
-data class CheckUser(val login: String,val password: String)
-
-fun isEmailValid(email: String): Boolean {
- val emailRegex = Regex("^[A-Za-z0-9+_.-]+@(.+)$")
- return !emailRegex.matches(email)
-}
+data class CheckUser(val login: String,val password: String)
\ No newline at end of file
diff --git a/Sources/src/main/kotlin/allin/routing/UserRouter.kt b/Sources/src/main/kotlin/allin/routing/UserRouter.kt
index 3cbf1a8..0630642 100644
--- a/Sources/src/main/kotlin/allin/routing/UserRouter.kt
+++ b/Sources/src/main/kotlin/allin/routing/UserRouter.kt
@@ -2,23 +2,28 @@ package allin.routing
import allin.model.CheckUser
import allin.model.User
-import allin.model.isEmailValid
-import io.ktor.client.utils.*
+import com.typesafe.config.ConfigFactory
import io.ktor.http.*
import io.ktor.server.application.*
+import io.ktor.server.auth.*
+import io.ktor.server.auth.jwt.*
+import io.ktor.server.config.*
import io.ktor.server.request.*
import io.ktor.server.response.*
import io.ktor.server.routing.*
+import allin.utils.RegexChecker
+import allin.utils.TokenManager
val users = mutableListOf()
-
+val tokenManager= TokenManager(HoconApplicationConfig(ConfigFactory.load()))
+val RegexChecker= RegexChecker()
fun Application.UserRouter() {
routing {
route("/users/register"){
post {
val TempUser = call.receive()
- if (isEmailValid(TempUser.email)){
+ if (RegexChecker.isEmailInvalid(TempUser.email)){
call.respond(HttpStatusCode.Forbidden,"Input a valid mail !")
}
val user = users.find { it.username == TempUser.username || it.email == TempUser.email }
@@ -35,6 +40,7 @@ fun Application.UserRouter() {
val checkUser = call.receive()
val user = users.find { it.username == checkUser.login || it.email == checkUser.login }
if (user != null && user.password == checkUser.password) {
+ user.token=tokenManager.generateJWTToken(user)
call.respond(HttpStatusCode.OK, user)
} else {
call.respond(HttpStatusCode.NotFound,"Login and/or password incorrect.")
@@ -54,7 +60,19 @@ fun Application.UserRouter() {
}
}
}
+
+ authenticate {
+ get("/users/token") {
+ val principal = call.principal()
+ val username = principal!!.payload.getClaim("username").asString()
+ val user = users.find { it.username == username }
+ if (user != null) {
+ call.respond(HttpStatusCode.OK, user)
+ } else {
+ call.respond(HttpStatusCode.NotFound, "User not found with the valid token !")
+ }
+ }
+ }
+
}
}
-// REGISTER 201 created 400 bad request
-// LOGIN 200 OK 404
diff --git a/Sources/src/main/kotlin/allin/utils/RegexChecker.kt b/Sources/src/main/kotlin/allin/utils/RegexChecker.kt
new file mode 100644
index 0000000..8a70a90
--- /dev/null
+++ b/Sources/src/main/kotlin/allin/utils/RegexChecker.kt
@@ -0,0 +1,13 @@
+package allin.utils
+
+class RegexChecker {
+
+ private val emailRegex="^[A-Za-z0-9+_.-]+@(.+)$"
+
+
+ fun isEmailInvalid(email: String): Boolean {
+ val emailRegex = Regex(emailRegex)
+ return !emailRegex.matches(email)
+ }
+
+}
\ No newline at end of file
diff --git a/Sources/src/main/kotlin/allin/utils/TokenManager.kt b/Sources/src/main/kotlin/allin/utils/TokenManager.kt
new file mode 100644
index 0000000..3a9824c
--- /dev/null
+++ b/Sources/src/main/kotlin/allin/utils/TokenManager.kt
@@ -0,0 +1,33 @@
+package allin.utils
+
+import allin.model.User
+import com.auth0.jwt.JWT
+import com.auth0.jwt.JWTVerifier
+import com.auth0.jwt.algorithms.Algorithm
+import io.ktor.server.config.*
+import java.util.*
+
+class TokenManager (val config: HoconApplicationConfig){
+
+ val audience=config.property("audience").getString()
+ val secret=config.property("secret").getString()
+ val issuer=config.property("issuer").getString()
+ val expirationDate = System.currentTimeMillis() + 60000
+ fun generateJWTToken(user : User): String {
+
+ val token = JWT.create()
+ .withAudience(audience)
+ .withIssuer(issuer)
+ .withClaim("username", user.username)
+ .withExpiresAt(Date(expirationDate))
+ .sign(Algorithm.HMAC256(secret))
+ return token
+ }
+
+ fun verifyJWTToken(): JWTVerifier{
+ return JWT.require(Algorithm.HMAC256(secret))
+ .withAudience(audience)
+ .withIssuer(issuer)
+ .build()
+ }
+}
\ No newline at end of file
diff --git a/Sources/src/main/resources/application.conf b/Sources/src/main/resources/application.conf
new file mode 100644
index 0000000..e69de29