Merge pull request #20010 from ktoso/wip-authorizeAsync-ktoso

+htp #20002 add authorizeAsync
This commit is contained in:
Konrad Malawski 2016-03-17 10:57:18 +01:00
commit f679c9f0b1
8 changed files with 140 additions and 4 deletions

View file

@ -219,7 +219,7 @@ class SecurityDirectivesExamplesSpec extends RoutingSpec {
}
}
"0authorize" in {
"0authorize-0" in {
case class User(name: String)
// authenticate the user:
@ -260,6 +260,48 @@ class SecurityDirectivesExamplesSpec extends RoutingSpec {
}
}
"0authorizeAsync" in {
case class User(name: String)
// authenticate the user:
def myUserPassAuthenticator(credentials: Credentials): Option[User] =
credentials match {
case Credentials.Provided(id) => Some(User(id))
case _ => None
}
// check if user is authorized to perform admin actions,
// this could potentially be a long operation so it would return a Future
val admins = Set("Peter")
def hasAdminPermissions(user: User): Future[Boolean] =
Future.successful(admins.contains(user.name))
val route =
Route.seal {
authenticateBasic(realm = "secure site", myUserPassAuthenticator) { user =>
path("peters-lair") {
authorizeAsync(_ => hasAdminPermissions(user)) {
complete(s"'${user.name}' visited Peter's lair")
}
}
}
}
// tests:
val johnsCred = BasicHttpCredentials("John", "p4ssw0rd")
Get("/peters-lair") ~> addCredentials(johnsCred) ~> // adds Authorization header
route ~> check {
status shouldEqual StatusCodes.Forbidden
responseAs[String] shouldEqual "The supplied authentication is not authorized to access this resource"
}
val petersCred = BasicHttpCredentials("Peter", "pan")
Get("/peters-lair") ~> addCredentials(petersCred) ~> // adds Authorization header
route ~> check {
responseAs[String] shouldEqual "'Peter' visited Peter's lair"
}
}
"0extractCredentials" in {
val route =
extractCredentials { creds =>

View file

@ -24,6 +24,7 @@ Directive Description
a given ``AsyncAuthenticatorPF[T]``
:ref:`-authenticateOrRejectWithChallenge-` Lifts an authenticator function into a directive
:ref:`-authorize-` Applies the given authorization check to the request
:ref:`-authorizeAsync-` Applies the given asynchronous authorization check to the request
:ref:`-cancelRejection-` Adds a ``TransformationRejection`` cancelling all rejections equal to the
given one to the rejections potentially coming back from the inner route.
:ref:`-cancelRejections-` Adds a ``TransformationRejection`` cancelling all matching rejections

View file

@ -24,6 +24,7 @@ If the check returns ``true`` the request is passed on to the inner route unchan
In a common use-case you would check if a user (e.g. supplied by any of the ``authenticate*`` family of directives,
e.g. :ref:`-authenticateBasic-`) is allowed to access the inner routes, e.g. by checking if the user has the needed permissions.
See also :ref:`-authorize-` for the asynchronous version of this directive.
.. note::
See also :ref:`authentication-vs-authorization-scala` to understand the differences between those.
@ -32,4 +33,4 @@ Example
-------
.. includecode2:: ../../../../code/docs/http/scaladsl/server/directives/SecurityDirectivesExamplesSpec.scala
:snippet: 0authorize
:snippet: 0authorize-0

View file

@ -0,0 +1,36 @@
.. _-authorizeAsync-:
authorizeAsync
==============
Signature
---------
.. includecode2:: /../../akka-http/src/main/scala/akka/http/scaladsl/server/directives/SecurityDirectives.scala
:snippet: authorizeAsync
Description
-----------
Applies the given authorization check to the request.
The user-defined authorization check can either be supplied as a ``=> Future[Boolean]`` value which is calculated
just from information out of the lexical scope, or as a function ``RequestContext => Future[Boolean]`` which can also
take information from the request itself into account.
If the check returns ``true`` or the ``Future`` is failed the request is passed on to the inner route unchanged,
otherwise an ``AuthorizationFailedRejection`` is created, triggering a ``403 Forbidden`` response by default
(the same as in the case of an ``AuthenticationFailedRejection``).
In a common use-case you would check if a user (e.g. supplied by any of the ``authenticate*`` family of directives,
e.g. :ref:`-authenticateBasic-`) is allowed to access the inner routes, e.g. by checking if the user has the needed permissions.
See also :ref:`-authorize-` for the synchronous version of this directive.
.. note::
See also :ref:`authentication-vs-authorization-scala` to understand the differences between those.
Example
-------
.. includecode2:: ../../../../code/docs/http/scaladsl/server/directives/SecurityDirectivesExamplesSpec.scala
:snippet: 0authorizeAsync

View file

@ -17,6 +17,7 @@ SecurityDirectives
authenticateOAuth2PFAsync
authenticateOrRejectWithChallenge
authorize
authorizeAsync
extractCredentials