Skip to content
This repository has been archived by the owner on Apr 24, 2024. It is now read-only.

Commit

Permalink
! routing: AuthenticationFailedRejection now directly contains challe…
Browse files Browse the repository at this point in the history
…nge headers to return, fixes #538

This has two consequences:
  * it's easier to implement a custom authenticators which can now
    supply the challenge headers directly instead of needing a detour
    through HttpAuthenticator.getChallengeHeaders
  * AuthenticationFailedRejection is now serializable
  • Loading branch information
jrudolph committed Sep 27, 2013
1 parent b05dc16 commit 9c9b976
Show file tree
Hide file tree
Showing 4 changed files with 7 additions and 6 deletions.
Expand Up @@ -26,6 +26,7 @@ import AuthenticationFailedRejection._
class SecurityDirectivesSpec extends RoutingSpec {

val dontAuth = BasicAuth(UserPassAuthenticator[BasicUserContext](_ Future.successful(None)), "Realm")
val challenge = `WWW-Authenticate`(HttpChallenge("basic", "Realm"))

val doAuth = BasicAuth(UserPassAuthenticator[BasicUserContext] { userPassOption
Future.successful(Some(BasicUserContext(userPassOption.get.user)))
Expand All @@ -35,12 +36,12 @@ class SecurityDirectivesSpec extends RoutingSpec {
"reject requests without Authorization header with an AuthenticationFailedRejection" in {
Get() ~> {
authenticate(dontAuth) { echoComplete }
} ~> check { rejection === AuthenticationFailedRejection(CredentialsMissing, dontAuth) }
} ~> check { rejection === AuthenticationFailedRejection(CredentialsMissing, List(challenge)) }
}
"reject unauthenticated requests with Authorization header with an AuthenticationFailedRejection" in {
Get() ~> Authorization(BasicHttpCredentials("Bob", "")) ~> {
authenticate(dontAuth) { echoComplete }
} ~> check { rejection === AuthenticationFailedRejection(CredentialsRejected, dontAuth) }
} ~> check { rejection === AuthenticationFailedRejection(CredentialsRejected, List(challenge)) }
}
"reject requests with illegal Authorization header with 401" in {
Get() ~> RawHeader("Authorization", "bob alice") ~> handleRejections(RejectionHandler.Default) {
Expand Down
2 changes: 1 addition & 1 deletion spray-routing/src/main/scala/spray/routing/Rejection.scala
Expand Up @@ -127,7 +127,7 @@ case class UnacceptedResponseEncodingRejection(supported: HttpEncoding) extends
* specified in the cause.
*/
case class AuthenticationFailedRejection(cause: AuthenticationFailedRejection.Cause,
authenticator: HttpAuthenticator[_]) extends Rejection
challengeHeaders: List[HttpHeader]) extends Rejection

object AuthenticationFailedRejection {
/**
Expand Down
Expand Up @@ -36,12 +36,12 @@ object RejectionHandler {
implicit val Default = apply {
case Nil complete(NotFound, "The requested resource could not be found.")

case AuthenticationFailedRejection(cause, authenticator) :: _
case AuthenticationFailedRejection(cause, challengeHeaders) :: _
val rejectionMessage = cause match {
case CredentialsMissing "The resource requires authentication, which was not supplied with the request"
case CredentialsRejected "The supplied authentication is invalid"
}
ctx ctx.complete(Unauthorized, authenticator.getChallengeHeaders(ctx.request), rejectionMessage)
ctx ctx.complete(Unauthorized, challengeHeaders, rejectionMessage)

case AuthorizationFailedRejection :: _
complete(Forbidden, "The supplied authentication is not authorized to access this resource")
Expand Down
Expand Up @@ -37,7 +37,7 @@ trait HttpAuthenticator[U] extends ContextAuthenticator[U] {
case Some(userContext) Right(userContext)
case None
val cause = if (authHeader.isEmpty) CredentialsMissing else CredentialsRejected
Left(AuthenticationFailedRejection(cause, this))
Left(AuthenticationFailedRejection(cause, getChallengeHeaders(ctx.request)))
}
}

Expand Down

0 comments on commit 9c9b976

Please sign in to comment.