Merge pull request #87 from flecomte/jwt-token-into-env
move JWT secret into ENV
This commit was merged in pull request #87.
This commit is contained in:
@@ -38,6 +38,9 @@ services:
|
|||||||
REDIS_CONNECTION: ${REDIS_CONNECTION}
|
REDIS_CONNECTION: ${REDIS_CONNECTION}
|
||||||
RABBITMQ_CONNECTION: ${RABBITMQ_CONNECTION}
|
RABBITMQ_CONNECTION: ${RABBITMQ_CONNECTION}
|
||||||
ELASTICSEARCH_CONNECTION: ${ELASTICSEARCH_CONNECTION}
|
ELASTICSEARCH_CONNECTION: ${ELASTICSEARCH_CONNECTION}
|
||||||
|
JWT_SECRET: ${JWT_SECRET}
|
||||||
|
JWT_ISSUER: ${JWT_ISSUER}
|
||||||
|
JWT_VALIDITY: ${JWT_VALIDITY}
|
||||||
depends_on:
|
depends_on:
|
||||||
- elasticsearch
|
- elasticsearch
|
||||||
- db
|
- db
|
||||||
|
|||||||
@@ -124,7 +124,7 @@ fun Application.module(env: Env = PROD) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
install(Authentication, jwtInstallation(get()))
|
install(Authentication, jwtInstallation(get(), get()))
|
||||||
|
|
||||||
install(AutoHeadResponse)
|
install(AutoHeadResponse)
|
||||||
|
|
||||||
|
|||||||
@@ -43,4 +43,15 @@ class Configuration(val config: Config) {
|
|||||||
val rabbitmq: String = config.getString("rabbitmq.connection")
|
val rabbitmq: String = config.getString("rabbitmq.connection")
|
||||||
val exchangeNotificationName = "notification"
|
val exchangeNotificationName = "notification"
|
||||||
val sendGridKey: String = config.getString("mail.sendGrid.key")
|
val sendGridKey: String = config.getString("mail.sendGrid.key")
|
||||||
|
|
||||||
|
interface Jwt {
|
||||||
|
val secret: String
|
||||||
|
val issuer: String
|
||||||
|
val validityInMs: Int
|
||||||
|
}
|
||||||
|
val jwt = object : Jwt {
|
||||||
|
override val secret = config.getString("jwt.secret")
|
||||||
|
override val issuer = config.getString("jwt.issuer")
|
||||||
|
override val validityInMs = config.getInt("jwt.validity")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import com.fasterxml.jackson.datatype.joda.JodaModule
|
|||||||
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
|
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
|
||||||
import com.rabbitmq.client.ConnectionFactory
|
import com.rabbitmq.client.ConnectionFactory
|
||||||
import fr.dcproject.common.email.Mailer
|
import fr.dcproject.common.email.Mailer
|
||||||
|
import fr.dcproject.component.auth.jwt.JwtConfig
|
||||||
import fr.dcproject.component.notification.NotificationConsumer
|
import fr.dcproject.component.notification.NotificationConsumer
|
||||||
import fr.dcproject.component.notification.NotificationEmailSender
|
import fr.dcproject.component.notification.NotificationEmailSender
|
||||||
import fr.dcproject.component.notification.NotificationsPush
|
import fr.dcproject.component.notification.NotificationsPush
|
||||||
@@ -25,6 +26,19 @@ import org.koin.dsl.module
|
|||||||
|
|
||||||
@KtorExperimentalAPI
|
@KtorExperimentalAPI
|
||||||
val KoinModule = module {
|
val KoinModule = module {
|
||||||
|
// JWT
|
||||||
|
single {
|
||||||
|
val config: Configuration = get()
|
||||||
|
JwtConfig(
|
||||||
|
config.jwt.secret,
|
||||||
|
config.jwt.issuer,
|
||||||
|
config.jwt.validityInMs,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
// JWT Verifier
|
||||||
|
single {
|
||||||
|
get<JwtConfig>().verifier
|
||||||
|
}
|
||||||
// SQL connection
|
// SQL connection
|
||||||
single {
|
single {
|
||||||
val config: Configuration = get()
|
val config: Configuration = get()
|
||||||
|
|||||||
@@ -2,13 +2,16 @@ package fr.dcproject.component.auth.jwt
|
|||||||
|
|
||||||
import com.auth0.jwt.JWT
|
import com.auth0.jwt.JWT
|
||||||
import fr.dcproject.component.auth.database.UserI
|
import fr.dcproject.component.auth.database.UserI
|
||||||
|
import org.koin.core.context.GlobalContext
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Produce a token for this combination of User and Account
|
* Produce a token for this combination of User and Account
|
||||||
*/
|
*/
|
||||||
fun UserI.makeToken(): String = JWT.create()
|
fun UserI.makeToken(): String = GlobalContext.get().koin.get<JwtConfig>().run {
|
||||||
|
JWT.create()
|
||||||
.withSubject("Authentication")
|
.withSubject("Authentication")
|
||||||
.withIssuer(JwtConfig.issuer)
|
.withIssuer(issuer)
|
||||||
.withClaim("id", id.toString())
|
.withClaim("id", id.toString())
|
||||||
.withExpiresAt(JwtConfig.getExpiration())
|
.withExpiresAt(getExpiration())
|
||||||
.sign(JwtConfig.algorithm)
|
.sign(algorithm)
|
||||||
|
}
|
||||||
|
|||||||
@@ -5,11 +5,11 @@ import com.auth0.jwt.JWTVerifier
|
|||||||
import com.auth0.jwt.algorithms.Algorithm
|
import com.auth0.jwt.algorithms.Algorithm
|
||||||
import java.util.Date
|
import java.util.Date
|
||||||
|
|
||||||
object JwtConfig {
|
class JwtConfig(
|
||||||
private const val secret = "zAP5MBA4B4Ijz0MZaS48"
|
private val secret: String,
|
||||||
const val issuer = "dc-project.fr"
|
val issuer: String,
|
||||||
private const val validityInMs = 3_600_000 * 10 // 10 hours
|
private val validityInMs: Int,
|
||||||
|
) {
|
||||||
// TODO change to RSA512
|
// TODO change to RSA512
|
||||||
val algorithm: Algorithm = Algorithm.HMAC512(secret)
|
val algorithm: Algorithm = Algorithm.HMAC512(secret)
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package fr.dcproject.component.auth.jwt
|
package fr.dcproject.component.auth.jwt
|
||||||
|
|
||||||
|
import com.auth0.jwt.JWTVerifier
|
||||||
import fr.dcproject.component.auth.database.User
|
import fr.dcproject.component.auth.database.User
|
||||||
import fr.dcproject.component.auth.database.UserRepository
|
import fr.dcproject.component.auth.database.UserRepository
|
||||||
import io.ktor.application.ApplicationCall
|
import io.ktor.application.ApplicationCall
|
||||||
@@ -9,14 +10,14 @@ import io.ktor.http.auth.HttpAuthHeader
|
|||||||
import io.ktor.routing.Routing
|
import io.ktor.routing.Routing
|
||||||
import java.util.UUID
|
import java.util.UUID
|
||||||
|
|
||||||
fun jwtInstallation(userRepo: UserRepository): Authentication.Configuration.() -> Unit = {
|
fun jwtInstallation(userRepo: UserRepository, verifier: JWTVerifier): Authentication.Configuration.() -> Unit = {
|
||||||
/**
|
/**
|
||||||
* Setup the JWT authentication to be used in [Routing].
|
* Setup the JWT authentication to be used in [Routing].
|
||||||
* If the token is valid, the corresponding [User] is fetched from the database.
|
* If the token is valid, the corresponding [User] is fetched from the database.
|
||||||
* The [User] can then be accessed in each [ApplicationCall].
|
* The [User] can then be accessed in each [ApplicationCall].
|
||||||
*/
|
*/
|
||||||
jwt {
|
jwt {
|
||||||
verifier(JwtConfig.verifier)
|
verifier(verifier)
|
||||||
realm = "dc-project.fr"
|
realm = "dc-project.fr"
|
||||||
validate {
|
validate {
|
||||||
it.payload.getClaim("id").asString()?.let { id ->
|
it.payload.getClaim("id").asString()?.let { id ->
|
||||||
@@ -27,7 +28,7 @@ fun jwtInstallation(userRepo: UserRepository): Authentication.Configuration.() -
|
|||||||
|
|
||||||
/* Token in URL */
|
/* Token in URL */
|
||||||
jwt("url") {
|
jwt("url") {
|
||||||
verifier(JwtConfig.verifier)
|
verifier(verifier)
|
||||||
realm = "dc-project.fr"
|
realm = "dc-project.fr"
|
||||||
authHeader { call ->
|
authHeader { call ->
|
||||||
call.request.queryParameters["token"]?.let {
|
call.request.queryParameters["token"]?.let {
|
||||||
|
|||||||
@@ -42,3 +42,11 @@ mail {
|
|||||||
key = ${?SEND_GRID_KEY}
|
key = ${?SEND_GRID_KEY}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
jwt {
|
||||||
|
secret = ${?JWT_SECRET}
|
||||||
|
issuer = "dc-project.fr"
|
||||||
|
issuer = ${?JWT_ISSUER}
|
||||||
|
validity = 36000000
|
||||||
|
validity = ${?JWT_VALIDITY}
|
||||||
|
}
|
||||||
@@ -144,5 +144,4 @@ class `Check auth on all routes` : BaseTest() {
|
|||||||
listOf("example123")
|
listOf("example123")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,10 +15,11 @@ fun TestApplicationRequest.`authenticated as`(
|
|||||||
val username = "$firstName-$lastName".toLowerCase()
|
val username = "$firstName-$lastName".toLowerCase()
|
||||||
val repo: CitizenRepository by lazy<CitizenRepository> { GlobalContext.get().koin.get() }
|
val repo: CitizenRepository by lazy<CitizenRepository> { GlobalContext.get().koin.get() }
|
||||||
val citizen = repo.findByUsername(username) ?: error("Citizen not exist with username $username")
|
val citizen = repo.findByUsername(username) ?: error("Citizen not exist with username $username")
|
||||||
|
val algorithm = GlobalContext.get().koin.get<JwtConfig>().algorithm
|
||||||
val jwtAsString: String = JWT.create()
|
val jwtAsString: String = JWT.create()
|
||||||
.withIssuer("dc-project.fr")
|
.withIssuer("dc-project.fr")
|
||||||
.withClaim("id", citizen.user.id.toString())
|
.withClaim("id", citizen.user.id.toString())
|
||||||
.sign(JwtConfig.algorithm)
|
.sign(algorithm)
|
||||||
|
|
||||||
addHeader(HttpHeaders.Authorization, "Bearer $jwtAsString")
|
addHeader(HttpHeaders.Authorization, "Bearer $jwtAsString")
|
||||||
|
|
||||||
|
|||||||
@@ -37,3 +37,9 @@ mail {
|
|||||||
key = "abcd"
|
key = "abcd"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
jwt {
|
||||||
|
secret = "zAP5MBA4B4Ijz0MZaS48"
|
||||||
|
issuer = "dc-project.fr"
|
||||||
|
validity = 36000000
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user