@@ -3,7 +3,7 @@ package org.thp.scalligraph.auth
33import org .thp .scalligraph .controllers .AuthenticatedRequest
44import org .thp .scalligraph .services .config .ApplicationConfig .configurationFormat
55import org .thp .scalligraph .services .config .{ApplicationConfig , ConfigItem }
6- import org .thp .scalligraph .{AuthenticationError , AuthorizationError , BadConfigurationError , EntityIdOrName , RichSeq , ScalligraphApplication }
6+ import org .thp .scalligraph .{AuthenticationError , AuthorizationError , BadConfigurationError , BadRequestError , EntityIdOrName , RichSeq , ScalligraphApplication }
77import play .api .mvc .{ActionFunction , Request , RequestHeader , Result }
88import play .api .{Configuration , Logger }
99
@@ -49,18 +49,22 @@ class MultiAuthSrv(configuration: Configuration, appConfig: ApplicationConfig, a
4949
5050 override def capabilities : Set [AuthCapability .Value ] = authProviders.flatMap(_.capabilities).toSet
5151
52- private def forAllAuthProviders [A ](providers : Seq [AuthSrv ])(body : AuthSrv => Try [A ]): Try [A ] =
53- providers.foldLeft[Either [Seq [(String , Throwable )], A ]](Left (Seq ())) {
54- case (right : Right [_, _], _) => right
55- case (Left (errors), auth) =>
52+ private def forAllAuthProviders [A ](providers : Seq [AuthSrv ])(body : AuthSrv => Try [A ]): Try [A ] = {
53+ providers.foldLeft[MultiAuthProviderResponse [A ]](MultiAuthProviderResponse .Errors (Seq .empty)) {
54+ case (ok : MultiAuthProviderResponse .Ok [_], _) => ok
55+ case (stopping : MultiAuthProviderResponse .StoppingError , _) => stopping
56+ case (MultiAuthProviderResponse .Errors (errors), auth) =>
5657 body(auth).fold(
57- error => Left (errors :+ ((auth.name, error))),
58- success => Right (success)
58+ {
59+ case bre : BadRequestError => MultiAuthProviderResponse .StoppingError (auth.name -> bre, errors)
60+ case error => MultiAuthProviderResponse .Errors (errors :+ (auth.name -> error))
61+ },
62+ success => MultiAuthProviderResponse .Ok (success)
5963 )
6064 } match {
61- case Right (auth ) => Success (auth )
62- case Left (Seq ()) => Failure (AuthorizationError (" no authentication provider found" ))
63- case Left (errors) =>
65+ case MultiAuthProviderResponse . Ok (value ) => Success (value )
66+ case MultiAuthProviderResponse . Errors (Seq ()) => Failure (AuthorizationError (" no authentication provider found" ))
67+ case MultiAuthProviderResponse . Errors (errors) =>
6468 errors.foreach {
6569 case (authName, AuthenticationError (_, cause)) if cause != null => logAuthError(authName, cause)
6670 case (authName, AuthorizationError (_, cause)) if cause != null => logAuthError(authName, cause)
@@ -70,7 +74,15 @@ class MultiAuthSrv(configuration: Configuration, appConfig: ApplicationConfig, a
7074 Failure (AuthorizationError (" Operation not permitted" ))
7175 else
7276 Failure (AuthenticationError (" Authentication failure" ))
77+ case MultiAuthProviderResponse .StoppingError (error, previousErrors) =>
78+ (previousErrors :+ error).foreach {
79+ case (authName, AuthenticationError (_, cause)) if cause != null => logAuthError(authName, cause)
80+ case (authName, AuthorizationError (_, cause)) if cause != null => logAuthError(authName, cause)
81+ case (authName, error) => logAuthError(authName, error)
82+ }
83+ Failure (error._2)
7384 }
85+ }
7486
7587 private def logAuthError (authName : String , error : Throwable ): Unit = {
7688 logger.warn(s " $authName fails: $error" )
@@ -113,6 +125,13 @@ class MultiAuthSrv(configuration: Configuration, appConfig: ApplicationConfig, a
113125 forAllAuthProviders(authProviders)(_.removeKey(username))
114126}
115127
128+ sealed trait MultiAuthProviderResponse [+ A ]
129+ object MultiAuthProviderResponse {
130+ case class Ok [A ](value : A ) extends MultiAuthProviderResponse [A ]
131+ case class Errors (errors : Seq [(String , Throwable )]) extends MultiAuthProviderResponse [Nothing ]
132+ case class StoppingError (error : (String , Throwable ), previousErrors : Seq [(String , Throwable )]) extends MultiAuthProviderResponse [Nothing ]
133+ }
134+
116135class MultiAuthSrvProvider (appConfig : ApplicationConfig , authProviders : Seq [AuthSrvProvider ]) extends AuthSrvProvider {
117136 def this (app : ScalligraphApplication ) = this (app.applicationConfig, app.authSrvProviders)
118137
0 commit comments