Secure cookies

This commit is contained in:
Hubert Van De Walle 2020-07-18 20:41:42 +02:00
parent cdfe1d14ef
commit 9216696b1a
6 changed files with 34 additions and 8 deletions

View File

@ -7,3 +7,5 @@ JWT_SECRET=
JWT_REFRESH_SECRET= JWT_REFRESH_SECRET=
CORS=false CORS=false
PORT=8081 PORT=8081
HOST=
SECURE_COOKIES=

View File

@ -19,3 +19,6 @@ jwt:
secret: ${JWT_REFRESH_SECRET=-wWchkx44YGig4Q5Z7b7+E/3ymGEGd6PS7UGedMul3bg=} # Can be generated with `openssl rand -base64 32` secret: ${JWT_REFRESH_SECRET=-wWchkx44YGig4Q5Z7b7+E/3ymGEGd6PS7UGedMul3bg=} # Can be generated with `openssl rand -base64 32`
validity: 15 validity: 15
unit: DAYS unit: DAYS
cookies:
secure: ${SECURE_COOKIES:-false}

View File

@ -1,4 +1,6 @@
{% set title = "Notes" %} {% extends "__base__.html" %} {% block content %} {% set title = "Notes" %}
{% extends "__base__.html" %}
{% block content %}
<div class="container mx-auto"> <div class="container mx-auto">
<h1 class="text-2xl">{{ method }}</h1> <h1 class="text-2xl">{{ method }}</h1>
@ -24,8 +26,7 @@
title: '' title: ''
--- ---
{% endif -%}</textarea {% endif -%}</textarea>
>
<div class="mt-2"> <div class="mt-2">
<button <button

View File

@ -3,13 +3,14 @@ package be.vandewalleh
import com.sksamuel.hoplite.Masked import com.sksamuel.hoplite.Masked
import java.util.concurrent.TimeUnit import java.util.concurrent.TimeUnit
data class Config(val database: DatabaseConfig, val server: ServerConfig, val jwt: JwtConfig) { data class Config(val database: DatabaseConfig, val server: ServerConfig, val jwt: JwtConfig, val cookies: Cookies) {
override fun toString(): String { override fun toString(): String {
return """ return """
Config( Config(
database=$database, database=$database,
server=$server, server=$server,
jwt=$jwt jwt=$jwt,
cookies=$cookies
) )
""".trimIndent() """.trimIndent()
} }
@ -19,3 +20,4 @@ data class DatabaseConfig(val host: String, val port: Int, val name: String, val
data class ServerConfig(val host: String, val port: Int, val cors: Boolean) data class ServerConfig(val host: String, val port: Int, val cors: Boolean)
data class JwtConfig(val auth: Jwt, val refresh: Jwt) data class JwtConfig(val auth: Jwt, val refresh: Jwt)
data class Jwt(val validity: Long, val unit: TimeUnit, val secret: Masked) data class Jwt(val validity: Long, val unit: TimeUnit, val secret: Masked)
data class Cookies(val secure: Boolean)

View File

@ -79,7 +79,8 @@ val mainModule = DI.Module("main") {
userRepository = instance(), userRepository = instance(),
authJWT = instance(tag = "auth"), authJWT = instance(tag = "auth"),
templates = instance(), templates = instance(),
passwordHash = instance() passwordHash = instance(),
useSecureCookies = instance<Config>().cookies.secure
) )
} }

View File

@ -6,6 +6,7 @@ import be.vandewalleh.extensions.respondKorte
import be.vandewalleh.features.PasswordHash import be.vandewalleh.features.PasswordHash
import be.vandewalleh.repositories.UserRepository import be.vandewalleh.repositories.UserRepository
import be.vandewalleh.validation.registerValidator import be.vandewalleh.validation.registerValidator
import com.auth0.jwt.JWT
import com.soywiz.korte.Templates import com.soywiz.korte.Templates
import io.ktor.application.* import io.ktor.application.*
import io.ktor.http.* import io.ktor.http.*
@ -13,12 +14,14 @@ import io.ktor.http.HttpStatusCode.Companion.Unauthorized
import io.ktor.http.content.* import io.ktor.http.content.*
import io.ktor.request.* import io.ktor.request.*
import io.ktor.response.* import io.ktor.response.*
import io.ktor.util.date.GMTDate
class UserController( class UserController(
private val userRepository: UserRepository, private val userRepository: UserRepository,
private val templates: Templates, private val templates: Templates,
private val authJWT: SimpleJWT, private val authJWT: SimpleJWT,
private val passwordHash: PasswordHash private val passwordHash: PasswordHash,
private val useSecureCookies: Boolean
) { ) {
suspend fun login(call: ApplicationCall) { suspend fun login(call: ApplicationCall) {
@ -58,7 +61,21 @@ class UserController(
val token = authJWT.sign(user.id, user.username) val token = authJWT.sign(user.id, user.username)
call.response.cookies.append("Authorization", "Bearer $token", path = "/") // FIXME
val expiresAt = JWT.decode(token).expiresAt
val gmtDate = GMTDate(expiresAt.time)
call.response.cookies.append(
name = "Authorization",
value = "Bearer $token",
secure = useSecureCookies,
path = "/",
httpOnly = true,
expires = gmtDate,
extensions = mapOf(
"SameSite" to "Lax"
)
)
call.respondRedirect("/notes") call.respondRedirect("/notes")
} }