diff --git a/cli/src/main/scala/acab/devcon0/dtos/TrileCli.scala b/cli/src/main/scala/acab/devcon0/dtos/TrileCli.scala
index ccc19b16c2400e20ab152bcbc3e5f74df1221a15..c9f4918e10b54ec6af20c347ffbfa82908491ae8 100644
--- a/cli/src/main/scala/acab/devcon0/dtos/TrileCli.scala
+++ b/cli/src/main/scala/acab/devcon0/dtos/TrileCli.scala
@@ -36,6 +36,7 @@ object TrileCli {
     val TFC_CERTBOT_STAGING                 = "TRILE_FEDERATION_CONTROLLER_CERTBOT_STAGING"
     val TFC_CONFIGURATION_FOLDER            = "TRILE_FEDERATION_CONTROLLER_CONFIGURATION_FOLDER"
     val TFC_FEDVARS_ABSOLUTE_PATH           = "TRILE_FEDERATION_CONTROLLER_FEDVARS_ABSOLUTE_PATH"
+    val TFC_JOIN_TOKEN                      = "TRILE_FEDERATION_CONTROLLER_JOIN_TOKEN"
     val TFC_IPFS_ADDRESS                    = "TRILE_FEDERATION_CONTROLLER_IPFS_ADDRESS"
     val TFC_IPFS_CLUSTER_ADDRESS            = "TRILE_FEDERATION_CONTROLLER_IPFS_CLUSTER_ADDRESS"
     val TFC_IPFS_CLUSTER_PEER_ID            = "TRILE_FEDERATION_CONTROLLER_IPFS_CLUSTER_PEER_ID"
diff --git a/cli/src/main/scala/acab/devcon0/files/templates/dev/federationcontroller/DockerCompose.scala b/cli/src/main/scala/acab/devcon0/files/templates/dev/federationcontroller/DockerCompose.scala
index 6f373e37f138e0d11399333151dea6b89ec168ef..09d47415e39277c6a6726fb86b6cad9e8e6fa55e 100644
--- a/cli/src/main/scala/acab/devcon0/files/templates/dev/federationcontroller/DockerCompose.scala
+++ b/cli/src/main/scala/acab/devcon0/files/templates/dev/federationcontroller/DockerCompose.scala
@@ -53,6 +53,7 @@ services:
       TRILE_FEDERATION_CONTROLLER_FEDVARS_ABSOLUTE_PATH: /data/.fedvars
       TRILE_FEDERATION_CONTROLLER_P2P_PRIVATE_KEY: ${TRILE_FEDERATION_CONTROLLER_P2P_PRIVATE_KEY}
       TRILE_FEDERATION_CONTROLLER_REDIS_HOST: trile-dev-federation-controller-redis-stack
+      TRILE_FEDERATION_CONTROLLER_JOIN_TOKEN: ${TRILE_FEDERATION_CONTROLLER_JOIN_TOKEN}
     volumes:
       - ${TRILE_FEDERATION_CONTROLLER_FEDVARS_ABSOLUTE_PATH}:/data/.fedvars
       - /var/run/docker.sock:/var/run/docker.sock
diff --git a/cli/src/main/scala/acab/devcon0/files/templates/production/federationcontroller/DockerCompose.scala b/cli/src/main/scala/acab/devcon0/files/templates/production/federationcontroller/DockerCompose.scala
index 30b12451227779470665abe881a162a5cb2ef8c2..1097e4c3944e8556dfb478ec3756431d0a7c2288 100644
--- a/cli/src/main/scala/acab/devcon0/files/templates/production/federationcontroller/DockerCompose.scala
+++ b/cli/src/main/scala/acab/devcon0/files/templates/production/federationcontroller/DockerCompose.scala
@@ -77,6 +77,7 @@ services:
       TRILE_FEDERATION_CONTROLLER_IPFS_SWARM_KEY_VALUE: ${TRILE_FEDERATION_IPFS_SWARM_KEY_VALUE}
       TRILE_FEDERATION_CONTROLLER_P2P_PRIVATE_KEY: ${TRILE_FEDERATION_CONTROLLER_P2P_PRIVATE_KEY}
       TRILE_FEDERATION_CONTROLLER_REDIS_HOST: trile-federation-controller-redis-stack
+      TRILE_FEDERATION_CONTROLLER_JOIN_TOKEN: ${TRILE_FEDERATION_CONTROLLER_JOIN_TOKEN}
     volumes:
       - /var/run/docker.sock:/var/run/docker.sock
 
diff --git a/cli/src/main/scala/acab/devcon0/program/commands/InstallFederationMemberCommand.scala b/cli/src/main/scala/acab/devcon0/program/commands/InstallFederationMemberCommand.scala
index b526b9fffd1f876359ab8e610f69906221a61cb1..6a6775e66c039ab9b3ed668ddaa2a287c827ae64 100644
--- a/cli/src/main/scala/acab/devcon0/program/commands/InstallFederationMemberCommand.scala
+++ b/cli/src/main/scala/acab/devcon0/program/commands/InstallFederationMemberCommand.scala
@@ -6,7 +6,7 @@ import acab.devcon0.dtos.TrileCli.Environment
 import acab.devcon0.dtos.TrileCli.Environment.*
 import acab.devcon0.dtos.TrileCli.EnvironmentVariables.*
 import acab.devcon0.program.opts.{TrileOptsFederation, TrileOptsFederationMember}
-import acab.devcon0.services.{EnvVarsFileLoader, FederationControllerService}
+import acab.devcon0.services.FederationControllerService
 import acab.devcon0.services.command.install.InstallMemberCommandHandler
 import acab.devcon0.services.shell.{Clear, ConfirmAndRun, Greeter, PrintLn}
 import cats.effect.IO
@@ -27,7 +27,8 @@ object InstallFederationMemberCommand {
         TrileOptsFederationMember.nicknameOpt,
         TrileOptsFederationMember.sharedDiskSpaceGBMandatoryOpt,
         TrileOptsFederationMember.sharingFolderMandatoryOpt,
-        TrileOptsFederation.federationUrl,
+        TrileOptsFederationMember.federationUrl,
+        TrileOptsFederationMember.joinToken,
         TrileOptsFederation.assumeYesFlag
       ).mapN {
         (
@@ -36,10 +37,11 @@ object InstallFederationMemberCommand {
             sharedDiskSpaceGBMandatory,
             sharingFolderMandatory,
             federationUrl,
+            joinToken,
             assumeYes
         ) =>
           {
-            for fedvarsMap <- FederationControllerService.getFedvars(environment, federationUrl)
+            for fedvarsMap <- FederationControllerService.getFedvars(environment, federationUrl, joinToken)
             yield {
               Greeter(action = s"join the '${fedvarsMap(TRILE_FEDERATION_NAME)}'")
 
@@ -61,7 +63,7 @@ object InstallFederationMemberCommand {
               )
             }
           }
-            .attemptTap(_.fold(throwable => IO(println(throwable)), result => IO(println(result))))
+            .attemptTap(_.fold(throwable => IO(println(throwable)), _ => IO(println())))
             .unsafeToFuture()(TrileCommand.trileRuntime)
             .wait()
       }
diff --git a/cli/src/main/scala/acab/devcon0/program/opts/TrileOptsFederation.scala b/cli/src/main/scala/acab/devcon0/program/opts/TrileOptsFederation.scala
index b1f00ba75dcabbf4669dfb8110262addd002dd08..2d671b2c534de2c3209de8922d706f5ae1d23b3a 100644
--- a/cli/src/main/scala/acab/devcon0/program/opts/TrileOptsFederation.scala
+++ b/cli/src/main/scala/acab/devcon0/program/opts/TrileOptsFederation.scala
@@ -16,13 +16,6 @@ object TrileOptsFederation {
   val federationNameOpt: Opts[String] = Opts
     .option[String](long = "federation-name", short = "f", help = s"The name you want to use in the federation")
 
-  val federationUrl: Opts[String] = Opts
-    .option[String](
-      "federation-url",
-      help = s"URL of the federation. For instance: demo.trile.link"
-    )
-    .map(PathSanitizer.expandHome)
-
   val assumeYesFlag: Opts[Boolean] = Opts
     .flag(
       long = "assume-yes",
diff --git a/cli/src/main/scala/acab/devcon0/program/opts/TrileOptsFederationMember.scala b/cli/src/main/scala/acab/devcon0/program/opts/TrileOptsFederationMember.scala
index 8a36d8d15166a543fe42bff99a03a5e958bde2f2..5bcda9e88534ea7579cc70d10bae4798742f7fa3 100644
--- a/cli/src/main/scala/acab/devcon0/program/opts/TrileOptsFederationMember.scala
+++ b/cli/src/main/scala/acab/devcon0/program/opts/TrileOptsFederationMember.scala
@@ -1,6 +1,7 @@
 package acab.devcon0.program.opts
 
 import acab.devcon0.dtos.TrileCli.Defaults
+import acab.devcon0.services.PathSanitizer
 import com.monovore.decline.*
 
 object TrileOptsFederationMember {
@@ -22,4 +23,14 @@ object TrileOptsFederationMember {
 
   val sharingFolderMandatoryOpt: Opts[Option[String]] =
     Opts.option[String]("sharing-folder", help = "Location of your sharing folder").orNone
+
+  val joinToken: Opts[String] = Opts
+    .option[String](long = "join-token", short = "j", help = s"The join token the federation controller shall provide")
+
+  val federationUrl: Opts[String] = Opts
+    .option[String](
+      "federation-url",
+      help = s"URL of the federation. For instance: demo.trile.link"
+    )
+    .map(PathSanitizer.expandHome)
 }
diff --git a/cli/src/main/scala/acab/devcon0/services/FederationControllerEnvironmentVariables.scala b/cli/src/main/scala/acab/devcon0/services/FederationControllerEnvironmentVariables.scala
index 05ae801e1caea0c02097f426b3a8362a8e6916b0..7fec3331b415f4557d565301d0758048f1b5bc2d 100644
--- a/cli/src/main/scala/acab/devcon0/services/FederationControllerEnvironmentVariables.scala
+++ b/cli/src/main/scala/acab/devcon0/services/FederationControllerEnvironmentVariables.scala
@@ -7,6 +7,7 @@ import acab.devcon0.dtos.TrileCli.{Defaults, Environment}
 import acab.devcon0.services.shell.{Ed25519KeyGeneration, GroupId, UserId}
 
 import java.net.InetAddress
+import scala.util.Random
 
 object FederationControllerEnvironmentVariables {
 
@@ -51,6 +52,7 @@ object FederationControllerEnvironmentVariables {
       TFC_CERTBOT_SERVICE_NAME                           -> certbotServiceName,
       TFC_CERTBOT_STAGING                                -> inputVariables.stagingSSL,
       TFC_CONFIGURATION_FOLDER                           -> controllerConfigurationFolder,
+      TFC_JOIN_TOKEN                                     -> Random.alphanumeric.take(32).mkString("").toUpperCase,
       TFC_FEDVARS_ABSOLUTE_PATH                          -> s"$controllerConfigurationFolder/.fedvars",
       TFC_IPFS_CLUSTER_ADDRESS -> getIpfsClusterAddress(controllerNetworkAddress, environment, ipfsClusterSwarmPort),
       TFC_IPFS_CLUSTER_REPLICA_FACTOR_MAX -> inputVariables.ipfsClusterReplicaFactorMax.toString,
diff --git a/cli/src/main/scala/acab/devcon0/services/FederationControllerService.scala b/cli/src/main/scala/acab/devcon0/services/FederationControllerService.scala
index 47e9f12c42fa7cda0e78648b088b75c40633a7c7..b237e70cf0fb41ef206e612aef679cc8fbfc1e7d 100644
--- a/cli/src/main/scala/acab/devcon0/services/FederationControllerService.scala
+++ b/cli/src/main/scala/acab/devcon0/services/FederationControllerService.scala
@@ -17,9 +17,9 @@ import scala.concurrent.duration.Duration
 object FederationControllerService {
   private val backend: SyncBackend = CurlBackend()
 
-  def getFedvars(environment: Environment, networkAddress: String): IO[TrileFederationEnvVars] = {
+  def getFedvars(environment: Environment, networkAddress: String, joinToken: String): IO[TrileFederationEnvVars] = {
     val uri: Uri = getFedvarsUri(environment, networkAddress)
-    triggerFedvarsRequest(uri)
+    triggerFedvarsRequest(uri, joinToken)
       .map(
         _.split("\\\\n")
           .map { line =>
@@ -57,8 +57,8 @@ object FederationControllerService {
     }
   }
 
-  private def triggerFedvarsRequest(uri: Uri): IO[String] = {
-    triggerRequest(IO(quickRequest.get(uri).header(HeaderNames.Authorization, "Bearer TOKEN").send(backend)))
+  private def triggerFedvarsRequest(uri: Uri, joinToken: String): IO[String] = {
+    triggerRequest(IO(quickRequest.get(uri).header(HeaderNames.Authorization, s"Bearer $joinToken").send(backend)))
   }
 
   private def triggerRequest(uri: Uri): IO[String] = {
diff --git a/cli/src/main/scala/acab/devcon0/services/command/install/InstallControllerCommandHandler.scala b/cli/src/main/scala/acab/devcon0/services/command/install/InstallControllerCommandHandler.scala
index 7731e1a7e6d740bc54ae79805ac3a276eeefb9ac..9f513038a99c97cf96809d269fa725d53cbbc212 100644
--- a/cli/src/main/scala/acab/devcon0/services/command/install/InstallControllerCommandHandler.scala
+++ b/cli/src/main/scala/acab/devcon0/services/command/install/InstallControllerCommandHandler.scala
@@ -9,6 +9,7 @@ import acab.devcon0.services.shell.*
 import acab.devcon0.services.{FederationControllerEnvironmentVariables, FederationControllerService}
 import acab.devcon0.{files, services}
 import cats.effect.IO
+import cats.implicits.catsSyntaxMonadError
 import ujson.Value.Value
 
 import java.nio.charset.StandardCharsets
@@ -31,25 +32,30 @@ object InstallControllerCommandHandler {
       generateConfigurationFilesPostSsl(inputVariables, environmentVariables) >>
       DockerComposeUp(dockerComposeAbsolutePath) >>
       generateFedVars(inputVariables, environmentVariables) >>
-      generateInstallationEnvVars(environmentVariables)
+      generateInstallationEnvVars(environmentVariables) >>
+      printJoinToken(environmentVariables)
+  }
+
+  private def printJoinToken(environmentVariables: TrileFederationEnvVars): IO[Unit] = {
+    PrintLn.subStepInfo(s"Federation join token: ${environmentVariables(TFC_JOIN_TOKEN)}")
   }
 
   private def generateFedVars(
       inputVariables: FederationControllerInstallInputVariables,
-      environmentVariablesMap: TrileFederationEnvVars
+      environmentVariables: TrileFederationEnvVars
   ): IO[Unit] = {
-    val networkAddress: String   = environmentVariablesMap(TFC_NETWORK_ADDRESS)
+    val networkAddress: String   = environmentVariables(TFC_NETWORK_ADDRESS)
     val environment: Environment = inputVariables.environment
     for peerId <- FederationControllerService.getPeerId(environment, networkAddress)
     yield {
-      val fedvarsAbsolutePath = environmentVariablesMap(TFC_FEDVARS_ABSOLUTE_PATH)
+      val fedvarsAbsolutePath = environmentVariables(TFC_FEDVARS_ABSOLUTE_PATH)
       val map: TrileFederationEnvVars = Map(
-        TRILE_FEDERATION_IPFS_SWARM_KEY_VALUE -> getIpfsSwarmKeyValue(environmentVariablesMap),
+        TRILE_FEDERATION_IPFS_SWARM_KEY_VALUE -> getIpfsSwarmKeyValue(environmentVariables),
         TFC_NETWORK_ADDRESS                   -> networkAddress,
-        TRILE_FEDERATION_NAME                 -> environmentVariablesMap(TRILE_FEDERATION_NAME),
-        TFC_IPFS_PEER_ID                      -> getIpfsPeerId(environmentVariablesMap),
-        TFC_IPFS_CLUSTER_PEER_ID              -> getIpfsClusterPeerId(environmentVariablesMap),
-        TFC_IPFS_CLUSTER_SECRET               -> getIpfsClusterSecret(environmentVariablesMap),
+        TRILE_FEDERATION_NAME                 -> environmentVariables(TRILE_FEDERATION_NAME),
+        TFC_IPFS_PEER_ID                      -> getIpfsPeerId(environmentVariables),
+        TFC_IPFS_CLUSTER_PEER_ID              -> getIpfsClusterPeerId(environmentVariables),
+        TFC_IPFS_CLUSTER_SECRET               -> getIpfsClusterSecret(environmentVariables),
         TFC_IPFS_CLUSTER_SWARM_PORT           -> Defaults.ipfsClusterSwarmPort,
         TFC_IPFS_CLUSTER_SWARM_PORT           -> Defaults.ipfsClusterSwarmPort,
         TFC_IPFS_SWARM_PORT                   -> Defaults.ipfsSwarmPort,
@@ -60,7 +66,7 @@ object InstallControllerCommandHandler {
       val fedVarsContent: String = map.view.toList.map { case (key, value) => s"$key=$value" }.mkString("\n")
       Files.write(Paths.get(fedvarsAbsolutePath), fedVarsContent.getBytes(StandardCharsets.UTF_8))
     }
-  }
+  }.attemptTap(PrintLn.subStepAttemptTap("Saving .fedvars", _)).void
 
   private def generateInstallationEnvVars(envVars: TrileFederationEnvVars): IO[Unit] = IO {
     val configurationFolderAbsolutePath = getConfigurationFolderAbsolutePath(envVars)
@@ -73,7 +79,7 @@ object InstallControllerCommandHandler {
       .map { case (key, value) => s"$key=$value" }
       .mkString("\n")
     Files.write(Paths.get(installationEnvVarsAbsolutePath), envVarsContent.getBytes(StandardCharsets.UTF_8))
-  }
+  }.attemptTap(PrintLn.subStepAttemptTap("Saving configuration", _)).void
 
   private def getIpfsPeerId(envVars: TrileFederationEnvVars): String = {
     val ipfsConfigurationFolderAbsolutePath = getIpfsConfigurationFolderAbsolutePath(envVars)
diff --git a/cli/src/main/scala/acab/devcon0/services/shell/ChmodX.scala b/cli/src/main/scala/acab/devcon0/services/shell/ChmodX.scala
index 9fa24494c20d6cbe79e81236294ad5d0bcd9dfa8..fd354b524cb99265930d27b79615312249bb50e5 100644
--- a/cli/src/main/scala/acab/devcon0/services/shell/ChmodX.scala
+++ b/cli/src/main/scala/acab/devcon0/services/shell/ChmodX.scala
@@ -4,7 +4,7 @@ import cats.effect.IO
 
 object ChmodX {
 
-  private val cmdLabel: String = "Execution permission grant"
+  private val cmdLabel: String = "Granting permissions"
 
   def apply(path: String): IO[Unit] = {
     val cmd: String = getCmd(path)
diff --git a/cli/src/main/scala/acab/devcon0/services/shell/PrintLn.scala b/cli/src/main/scala/acab/devcon0/services/shell/PrintLn.scala
index 5c73f3e34a41c9b2303ef107a5e40d34b97f8307..846286eee392c9b04058bbcecec6e4f4a155a9ce 100644
--- a/cli/src/main/scala/acab/devcon0/services/shell/PrintLn.scala
+++ b/cli/src/main/scala/acab/devcon0/services/shell/PrintLn.scala
@@ -26,6 +26,14 @@ object PrintLn {
       .fold(_ => subStepError(label, isFinal), _ => subStepOk(label, isFinal))
   }
 
+  def subStepInfo(label: String, isFinal: Boolean = false): IO[Unit] = {
+    val str = {
+      if isFinal then s"${Color.Blue("[i]").overlay(Bold.On)} ${Color.Blue(label)}"
+      else s"${Color.Blue("[i]").overlay(Bold.On)} $label"
+    }
+    IO(print(str)).flatMap(_ => IO(println()))
+  }
+
   def subStepOk(label: String, isFinal: Boolean = false): IO[Unit] = {
     val str = {
       if isFinal then s"${Color.Green("[\u2713]").overlay(Bold.On)} ${Color.Green(label)}"
diff --git a/federation-controller-backend/src/main/resources/application.conf b/federation-controller-backend/src/main/resources/application.conf
index bf23dd460ea941e55c32ac65a60be0f15c55e29b..3a11591520b2a89614a9872049103655a772ecfe 100644
--- a/federation-controller-backend/src/main/resources/application.conf
+++ b/federation-controller-backend/src/main/resources/application.conf
@@ -19,6 +19,10 @@ app {
         swarm-key-value = ""
         swarm-key-value = ${?TRILE_FEDERATION_CONTROLLER_IPFS_SWARM_KEY_VALUE}
     }
+    auth {
+        join-token = ""
+        join-token = ${?TRILE_FEDERATION_CONTROLLER_JOIN_TOKEN}
+    }
     fedvars-absolute-path = ""
     fedvars-absolute-path = ${?TRILE_FEDERATION_CONTROLLER_FEDVARS_ABSOLUTE_PATH}
 }
diff --git a/federation-controller-backend/src/main/scala/acab/devcon0/configuration/Configuration.scala b/federation-controller-backend/src/main/scala/acab/devcon0/configuration/Configuration.scala
index 0e5d9fafe223fd82ac46db70e404e682405537b1..47a339a03d1e450e59b92a7d1e0f215efb6c3e4a 100644
--- a/federation-controller-backend/src/main/scala/acab/devcon0/configuration/Configuration.scala
+++ b/federation-controller-backend/src/main/scala/acab/devcon0/configuration/Configuration.scala
@@ -23,6 +23,7 @@ final case class P2pConfiguration(
     swarmPort: Integer,
     topics: P2pTopicsConfiguration
 )
+final case class AuthConfiguration(joinToken: String)
 final case class RedisConfiguration(host: String, port: Integer)
 final case class IpfsClusterConfiguration(apiUrl: String)
 final case class IpfsConfiguration(apiUrl: String)
@@ -33,6 +34,7 @@ final case class Configuration(
     http: HttpConfiguration,
     redis: RedisConfiguration,
     p2p: P2pConfiguration,
+    auth: AuthConfiguration,
     fedvarsAbsolutePath: String
 )
 
@@ -45,6 +47,7 @@ object TrileControllerBackendConfigFactory {
   private val ipfsClusterConfig: Config = appConfig.getConfig("ipfs-cluster")
   private val httpConfig: Config        = appConfig.getConfig("http")
   private val p2pConfig: Config         = appConfig.getConfig("p2p")
+  private val authConfig: Config        = appConfig.getConfig("auth")
 
   def build(): Configuration = {
     val ipfsConfiguration: IpfsConfiguration = IpfsConfiguration(
@@ -66,12 +69,17 @@ object TrileControllerBackendConfigFactory {
 
     val p2pConfiguration: P2pConfiguration = getP2pConfiguration
 
+    val authConfiguration: AuthConfiguration = AuthConfiguration(
+      joinToken = authConfig.getString("join-token")
+    )
+
     Configuration(
       ipfs = ipfsConfiguration,
       ipfsCluster = ipfsClusterConfiguration,
       http = httpConfiguration,
       redis = redisConfiguration,
       p2p = p2pConfiguration,
+      auth = authConfiguration,
       fedvarsAbsolutePath = appConfig.getString("fedvars-absolute-path")
     )
   }
diff --git a/federation-controller-backend/src/main/scala/acab/devcon0/domain/dtos/Federation.scala b/federation-controller-backend/src/main/scala/acab/devcon0/domain/dtos/Federation.scala
index f1a21408b30256cfb3b751afedc5a0dbb77d28b4..d6ee642425186bf2492f6a1d73a426c7c87d658d 100644
--- a/federation-controller-backend/src/main/scala/acab/devcon0/domain/dtos/Federation.scala
+++ b/federation-controller-backend/src/main/scala/acab/devcon0/domain/dtos/Federation.scala
@@ -3,3 +3,8 @@ package acab.devcon0.domain.dtos
 import acab.devcon0.trile.domain.dtos.aliases.IpfsCid
 
 final case class FederationIpfsCidDelta(additions: Set[IpfsCid], removals: Set[IpfsCid])
+
+final case class FederationAuth(
+    visibilityType: String,
+    joinToken: String,
+                               )
diff --git a/federation-controller-backend/src/main/scala/acab/devcon0/input/http/FederationRoute.scala b/federation-controller-backend/src/main/scala/acab/devcon0/input/http/FederationRoute.scala
index a680ee03c9846df45d67ad31e9ec99667c52a5fd..30943e337234cb167bdffc4dee9b3a0b0470d488 100644
--- a/federation-controller-backend/src/main/scala/acab/devcon0/input/http/FederationRoute.scala
+++ b/federation-controller-backend/src/main/scala/acab/devcon0/input/http/FederationRoute.scala
@@ -18,43 +18,34 @@ class FederationRoute(configuration: Configuration) {
   implicit val logger: Logger[IO] = Slf4jLogger.getLogger[IO]
 
   val routes: HttpRoutes[IO] = HttpRoutes
-    .of[IO] {
-      case req @ GET -> Root / ".fedvars" => {
-        validateToken(req)
-          .flatMap {
-            case ok @ Response(Status.Ok, _, _, _, _) => {
-              val filePath: Path = Path(configuration.fedvarsAbsolutePath)
-              Files[IO]
-                .readAll(filePath)
-                .through(fs2.text.utf8.decode)
-                .compile
-                .string
-                .flatMap(fileContent => Ok(fileContent))
-            }
-            case badRequest @ Response(Status.BadRequest, _, _, _, _) => {
-              IO.pure(badRequest)
-            }
-            case unauthorized @ Response(Status.Unauthorized, _, _, _, _) => {
-              IO.pure(unauthorized)
-            }
-          }
-          .attemptTap(EffectsUtils.attemptTLog)
-      }
+    .of[IO] { case req @ GET -> Root / ".fedvars" =>
+      validateToken(req)
+        .flatMap {
+          case ok @ Response(Status.Ok, _, _, _, _) =>
+            val filePath: Path = Path(configuration.fedvarsAbsolutePath)
+            Files[IO]
+              .readAll(filePath)
+              .through(fs2.text.utf8.decode)
+              .compile
+              .string
+              .flatMap(fileContent => Ok(fileContent))
+          case badRequest @ Response(Status.BadRequest, _, _, _, _)     => IO.pure(badRequest)
+          case unauthorized @ Response(Status.Unauthorized, _, _, _, _) => IO.pure(unauthorized)
+        }
+        .attemptTap(EffectsUtils.attemptTLog)
     }
 
   private def validateToken(req: Request[IO]): IO[Response[IO]] = {
     val maybeAuthorization: Option[Authorization] = req.headers.get[Authorization]
     maybeAuthorization match {
-      case Some(Authorization(Credentials.Token(AuthScheme.Bearer, token))) =>
-        if isValidToken(token) then { IO(Response(Status.Ok)) }
+      case Some(Authorization(Credentials.Token(AuthScheme.Bearer, joinToken))) =>
+        if isValidToken(joinToken) then { IO(Response(Status.Ok)) }
         else { IO(Response(Status.Unauthorized)) }
-      case _ => {
-        IO(Response(Status.BadRequest).withEntity("Missing Authorization Header"))
-      }
+      case _ => IO(Response(Status.BadRequest).withEntity("Missing Authorization Header"))
     }
   }
 
-  private def isValidToken(token: String): Boolean = {
-    true
+  private def isValidToken(joinToken: String): Boolean = {
+    configuration.auth.joinToken.equals(joinToken)
   }
 }