mirror of
https://github.com/TheAnachronism/docspell.git
synced 2025-06-22 02:18:26 +00:00
Authenticate with external accounts using OIDC
After successful authentication at the provider, an account is automatically created at docspell and the user is logged in.
This commit is contained in:
@ -6,12 +6,10 @@
|
||||
|
||||
package docspell.oidc
|
||||
|
||||
import cats.data.OptionT
|
||||
import cats.data.{Kleisli, OptionT}
|
||||
import cats.effect._
|
||||
import cats.implicits._
|
||||
|
||||
import docspell.common._
|
||||
|
||||
import org.http4s.HttpRoutes
|
||||
import org.http4s._
|
||||
import org.http4s.client.Client
|
||||
@ -22,7 +20,16 @@ import org.log4s.getLogger
|
||||
object CodeFlowRoutes {
|
||||
private[this] val log4sLogger = getLogger
|
||||
|
||||
def apply[F[_]: Async, A](
|
||||
def apply[F[_]: Async](
|
||||
enabled: Boolean,
|
||||
onUserInfo: OnUserInfo[F],
|
||||
config: CodeFlowConfig[F],
|
||||
client: Client[F]
|
||||
): HttpRoutes[F] =
|
||||
if (enabled) route[F](onUserInfo, config, client)
|
||||
else Kleisli(_ => OptionT.pure(Response.notFound[F]))
|
||||
|
||||
def route[F[_]: Async](
|
||||
onUserInfo: OnUserInfo[F],
|
||||
config: CodeFlowConfig[F],
|
||||
client: Client[F]
|
||||
|
@ -20,21 +20,26 @@ object UserInfoDecoder {
|
||||
findSomeId("preferred_username")
|
||||
|
||||
/** Looks recursively in the JSON for the first attribute with name `key` and returns
|
||||
* its value (expecting an Ident).
|
||||
* its value.
|
||||
*/
|
||||
def findSomeId(key: String): Decoder[Ident] =
|
||||
def findSomeString(key: String): Decoder[String] =
|
||||
Decoder.instance { cursor =>
|
||||
cursor.value
|
||||
.findAllByKey(key)
|
||||
.find(_.isString)
|
||||
.flatMap(_.asString)
|
||||
.toRight(s"No value found in JSON for key '$key'")
|
||||
.flatMap(normalizeUid)
|
||||
.left
|
||||
.map(msg => DecodingFailure(msg, Nil))
|
||||
}
|
||||
|
||||
private def normalizeUid(uid: String): Either[String, Ident] =
|
||||
/** Looks recursively in the JSON for the first attribute with name `key` and returns
|
||||
* its value (expecting an Ident).
|
||||
*/
|
||||
def findSomeId(key: String): Decoder[Ident] =
|
||||
findSomeString(key).emap(normalizeUid)
|
||||
|
||||
def normalizeUid(uid: String): Either[String, Ident] =
|
||||
Ident(uid.filter(Ident.chars.contains))
|
||||
.flatMap(id =>
|
||||
if (id.nonEmpty) Right(id) else Left(s"Id '$uid' empty after normalizing!'")
|
||||
|
Reference in New Issue
Block a user