diff --git a/modules/restserver/src/main/resources/reference.conf b/modules/restserver/src/main/resources/reference.conf index 29b63dc1..074c4e39 100644 --- a/modules/restserver/src/main/resources/reference.conf +++ b/modules/restserver/src/main/resources/reference.conf @@ -47,8 +47,9 @@ docspell.server { # The secret for this server that is used to sign the authenicator # tokens. If multiple servers are running, all must share the same # secret. You can use base64 or hex strings (prefix with b64: and - # hex:, respectively). - server-secret = "hex:caffee" + # hex:, respectively). If empty, a random secret is generated. + # Example: b64:YRx77QujCGkHSvll0TVEmtTaw3Z5eXr+nWMsEJowgKg= + server-secret = "" # How long an authentication token is valid. The web application # will get a new one periodically. diff --git a/modules/restserver/src/main/scala/docspell/restserver/ConfigFile.scala b/modules/restserver/src/main/scala/docspell/restserver/ConfigFile.scala index 7bebe31e..3dff82e9 100644 --- a/modules/restserver/src/main/scala/docspell/restserver/ConfigFile.scala +++ b/modules/restserver/src/main/scala/docspell/restserver/ConfigFile.scala @@ -6,6 +6,8 @@ package docspell.restserver +import java.security.SecureRandom + import cats.Semigroup import cats.data.{Validated, ValidatedNec} import cats.effect.Async @@ -20,12 +22,14 @@ import docspell.restserver.auth.OpenId import pureconfig._ import pureconfig.generic.auto._ +import scodec.bits.ByteVector object ConfigFile { + private[this] val unsafeLogger = org.log4s.getLogger import Implicits._ def loadConfig[F[_]: Async](args: List[String]): F[Config] = { - val logger = Logger.log4s(org.log4s.getLogger) + val logger = Logger.log4s(unsafeLogger) ConfigFactory .default[F, Config](logger, "docspell.server")(args) .map(cfg => Validate(cfg)) @@ -57,12 +61,25 @@ object ConfigFile { def all(cfg: Config) = List( duplicateOpenIdProvider(cfg), - signKeyVsUserUrl(cfg) + signKeyVsUserUrl(cfg), + generateSecretIfEmpty(cfg) ) private def valid(cfg: Config): ValidatedNec[String, Config] = Validated.validNec(cfg) + def generateSecretIfEmpty(cfg: Config): ValidatedNec[String, Config] = + if (cfg.auth.serverSecret.isEmpty) { + unsafeLogger.warn( + "No serverSecret specified. Generating a random one. It is recommended to add a server-secret in the config file." + ) + val random = new SecureRandom() + val buffer = new Array[Byte](32) + random.nextBytes(buffer) + val secret = ByteVector.view(buffer) + valid(cfg.copy(auth = cfg.auth.copy(serverSecret = secret))) + } else valid(cfg) + def duplicateOpenIdProvider(cfg: Config): ValidatedNec[String, Config] = { val dupes = cfg.openid