=doc,htpi #18496 more security directives docs
This commit is contained in:
parent
92e2ac21f0
commit
ea49e7624c
11 changed files with 203 additions and 39 deletions
|
|
@ -5,12 +5,12 @@
|
|||
package docs.http.scaladsl.server
|
||||
package directives
|
||||
|
||||
import akka.http.scaladsl.model._
|
||||
import akka.http.scaladsl.model.headers._
|
||||
import akka.http.scaladsl.server.Route
|
||||
import akka.http.scaladsl.server.directives.Credentials
|
||||
import akka.stream.scaladsl.{ FlowGraph, Flow, FlattenStrategy }
|
||||
|
||||
import scala.concurrent.Future
|
||||
import akka.http.scaladsl.model._
|
||||
import headers._
|
||||
|
||||
class SecurityDirectivesExamplesSpec extends RoutingSpec {
|
||||
|
||||
|
|
@ -51,6 +51,90 @@ class SecurityDirectivesExamplesSpec extends RoutingSpec {
|
|||
header[`WWW-Authenticate`].get.challenges.head shouldEqual HttpChallenge("Basic", "secure site")
|
||||
}
|
||||
}
|
||||
"authenticateBasicPF-0" in {
|
||||
val myUserPassAuthenticator: AuthenticatorPF[String] = {
|
||||
case p @ Credentials.Provided(id) if p.verify("p4ssw0rd") => id
|
||||
case p @ Credentials.Provided(id) if p.verify("p4ssw0rd-special") => s"$id-admin"
|
||||
}
|
||||
|
||||
val route =
|
||||
Route.seal {
|
||||
path("secured") {
|
||||
authenticateBasicPF(realm = "secure site", myUserPassAuthenticator) { userName =>
|
||||
complete(s"The user is '$userName'")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Get("/secured") ~> route ~> check {
|
||||
status shouldEqual StatusCodes.Unauthorized
|
||||
responseAs[String] shouldEqual "The resource requires authentication, which was not supplied with the request"
|
||||
header[`WWW-Authenticate`].get.challenges.head shouldEqual HttpChallenge("Basic", "secure site")
|
||||
}
|
||||
|
||||
val validCredentials = BasicHttpCredentials("John", "p4ssw0rd")
|
||||
Get("/secured") ~> addCredentials(validCredentials) ~> // adds Authorization header
|
||||
route ~> check {
|
||||
responseAs[String] shouldEqual "The user is 'John'"
|
||||
}
|
||||
|
||||
val validAdminCredentials = BasicHttpCredentials("John", "p4ssw0rd-special")
|
||||
Get("/secured") ~> addCredentials(validAdminCredentials) ~> // adds Authorization header
|
||||
route ~> check {
|
||||
responseAs[String] shouldEqual "The user is 'John-admin'"
|
||||
}
|
||||
|
||||
val invalidCredentials = BasicHttpCredentials("Peter", "pan")
|
||||
Get("/secured") ~>
|
||||
addCredentials(invalidCredentials) ~> // adds Authorization header
|
||||
route ~> check {
|
||||
status shouldEqual StatusCodes.Unauthorized
|
||||
responseAs[String] shouldEqual "The supplied authentication is invalid"
|
||||
header[`WWW-Authenticate`].get.challenges.head shouldEqual HttpChallenge("Basic", "secure site")
|
||||
}
|
||||
}
|
||||
"authenticateBasicPFAsync-0" in {
|
||||
case class User(id: String)
|
||||
def fetchUser(id: String): Future[User] = {
|
||||
// some fancy logic to obtain a User
|
||||
Future.successful(User(id))
|
||||
}
|
||||
|
||||
val myUserPassAuthenticator: AsyncAuthenticatorPF[User] = {
|
||||
case p @ Credentials.Provided(id) if p.verify("p4ssw0rd") =>
|
||||
fetchUser(id)
|
||||
}
|
||||
|
||||
val route =
|
||||
Route.seal {
|
||||
path("secured") {
|
||||
authenticateBasicPFAsync(realm = "secure site", myUserPassAuthenticator) { user =>
|
||||
complete(s"The user is '${user.id}'")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Get("/secured") ~> route ~> check {
|
||||
status shouldEqual StatusCodes.Unauthorized
|
||||
responseAs[String] shouldEqual "The resource requires authentication, which was not supplied with the request"
|
||||
header[`WWW-Authenticate`].get.challenges.head shouldEqual HttpChallenge("Basic", "secure site")
|
||||
}
|
||||
|
||||
val validCredentials = BasicHttpCredentials("John", "p4ssw0rd")
|
||||
Get("/secured") ~> addCredentials(validCredentials) ~> // adds Authorization header
|
||||
route ~> check {
|
||||
responseAs[String] shouldEqual "The user is 'John'"
|
||||
}
|
||||
|
||||
val invalidCredentials = BasicHttpCredentials("Peter", "pan")
|
||||
Get("/secured") ~>
|
||||
addCredentials(invalidCredentials) ~> // adds Authorization header
|
||||
route ~> check {
|
||||
status shouldEqual StatusCodes.Unauthorized
|
||||
responseAs[String] shouldEqual "The supplied authentication is invalid"
|
||||
header[`WWW-Authenticate`].get.challenges.head shouldEqual HttpChallenge("Basic", "secure site")
|
||||
}
|
||||
}
|
||||
"authenticateBasicAsync-0" in {
|
||||
def myUserPassAuthenticator(credentials: Credentials): Future[Option[String]] =
|
||||
credentials match {
|
||||
|
|
|
|||
|
|
@ -14,6 +14,14 @@ Directive Description
|
|||
``AuthenticatorPF[T]``
|
||||
:ref:`-authenticateBasicPFAsync-` Wraps the inner route with Http Basic authentication support using a given
|
||||
``AsyncAuthenticatorPF[T]``
|
||||
:ref:`-authenticateOAuth2-` Wraps the inner route with OAuth Bearer Token authentication support using
|
||||
a given ``AuthenticatorPF[T]``
|
||||
:ref:`-authenticateOAuth2Async-` Wraps the inner route with OAuth Bearer Token authentication support using
|
||||
a given ``AsyncAuthenticator[T]``
|
||||
:ref:`-authenticateOAuth2PF-` Wraps the inner route with OAuth Bearer Token authentication support using
|
||||
a given ``AuthenticatorPF[T]``
|
||||
:ref:`-authenticateOAuth2AsyncPF-` Wraps the inner route with OAuth Bearer Token authentication support using
|
||||
a given ``AsyncAuthenticatorPF[T]``
|
||||
:ref:`-authenticateOrRejectWithChallenge-` Lifts an authenticator function into a directive
|
||||
:ref:`-authorize-` Applies the given authorization check to the request
|
||||
:ref:`-cancelRejection-` Adds a ``TransformationRejection`` cancelling all rejections equal to the
|
||||
|
|
|
|||
|
|
@ -25,14 +25,11 @@ which by default is mapped to an ``401 Unauthorized`` response.
|
|||
Longer-running authentication tasks (like looking up credentials in a database) should use the :ref:`-authenticateBasicAsync-`
|
||||
variant of this directive which allows it to run without blocking routing layer of Akka HTTP, freeing it for other requests.
|
||||
|
||||
The ``authenticate*`` directives themselfs are not tied to any HTTP-specific
|
||||
details so that various authentication schemes can be implemented on top of authenticate.
|
||||
|
||||
Standard HTTP-based authentication which uses the ``WWW-Authenticate`` header containing challenge data and
|
||||
``Authorization`` header for receiving credentials is implemented in subclasses of ``HttpAuthenticator``.
|
||||
|
||||
.. warning::
|
||||
Make sure to use basic authentication only over SSL because credentials are transferred in plaintext.
|
||||
Make sure to use basic authentication only over SSL/TLS because credentials are transferred in plaintext.
|
||||
|
||||
.. _HTTP Basic Authentication: https://en.wikipedia.org/wiki/Basic_auth
|
||||
|
||||
|
|
|
|||
|
|
@ -23,14 +23,11 @@ a longer amount of time (e.g. looking up the user in a database).
|
|||
In case the returned option is ``None`` the request is rejected with a :class:`AuthenticationFailedRejection`,
|
||||
which by default is mapped to an ``401 Unauthorized`` response.
|
||||
|
||||
The ``authenticate*`` directives themselfs are not tied to any HTTP-specific
|
||||
details so that various authentication schemes can be implemented on top of authenticate.
|
||||
|
||||
Standard HTTP-based authentication which uses the ``WWW-Authenticate`` header containing challenge data and
|
||||
``Authorization`` header for receiving credentials is implemented in subclasses of ``HttpAuthenticator``.
|
||||
|
||||
.. warning::
|
||||
Make sure to use basic authentication only over SSL because credentials are transferred in plaintext.
|
||||
Make sure to use basic authentication only over SSL/TLS because credentials are transferred in plaintext.
|
||||
|
||||
.. _HTTP Basic Authentication: https://en.wikipedia.org/wiki/Basic_auth
|
||||
|
||||
|
|
|
|||
|
|
@ -18,15 +18,16 @@ Description
|
|||
|
||||
Provides support for handling `HTTP Basic Authentication`_.
|
||||
|
||||
Refer to :ref:`-authenticateBasic-` for a detailed description of this dictive.
|
||||
It's semantics are equivalent to ``authenticateBasicPF`` 's, where not handling a case in the Partial Function (PF)
|
||||
Refer to :ref:`-authenticateBasic-` for a detailed description of this directive.
|
||||
|
||||
Its semantics are equivalent to ``authenticateBasicPF`` 's, where not handling a case in the Partial Function (PF)
|
||||
leaves the request to be rejected with a :class:`AuthenticationFailedRejection` rejection.
|
||||
|
||||
Longer-running authentication tasks (like looking up credentials in a database) should use :ref:`authenticateBasicAsync`
|
||||
or :ref:`-authenticateBasicPFAsync-` if you prefer to use the ``PartialFunction`` syntax.
|
||||
|
||||
.. warning::
|
||||
Make sure to use basic authentication only over SSL because credentials are transferred in plaintext.
|
||||
Make sure to use basic authentication only over SSL/TLS because credentials are transferred in plaintext.
|
||||
|
||||
.. _HTTP Basic Authentication: https://en.wikipedia.org/wiki/Basic_auth
|
||||
|
||||
|
|
@ -34,4 +35,4 @@ Example
|
|||
-------
|
||||
|
||||
.. includecode2:: ../../../../code/docs/http/scaladsl/server/directives/SecurityDirectivesExamplesSpec.scala
|
||||
:snippet: 0authenticateBasicPF
|
||||
:snippet: authenticateBasicPF-0
|
||||
|
|
|
|||
|
|
@ -18,15 +18,13 @@ Description
|
|||
|
||||
Provides support for handling `HTTP Basic Authentication`_.
|
||||
|
||||
Refer to :ref:`-authenticateBasic-` for a detailed description of this dictive.
|
||||
It's semantics are equivalent to ``authenticateBasicPF`` 's, where not handling a case in the Partial Function (PF)
|
||||
Refer to :ref:`-authenticateBasic-` for a detailed description of this directive.
|
||||
|
||||
Its semantics are equivalent to ``authenticateBasicPF`` 's, where not handling a case in the Partial Function (PF)
|
||||
leaves the request to be rejected with a :class:`AuthenticationFailedRejection` rejection.
|
||||
|
||||
Longer-running authentication tasks (like looking up credentials in a database) should use :ref:`authenticateBasicAsync`
|
||||
or :ref:`-authenticateBasicPFAsync-` if you prefer to use the ``PartialFunction`` syntax.
|
||||
|
||||
.. warning::
|
||||
Make sure to use basic authentication only over SSL because credentials are transferred in plaintext.
|
||||
Make sure to use basic authentication only over SSL/TLS because credentials are transferred in plaintext.
|
||||
|
||||
.. _HTTP Basic Authentication: https://en.wikipedia.org/wiki/Basic_auth
|
||||
|
||||
|
|
@ -34,4 +32,4 @@ Example
|
|||
-------
|
||||
|
||||
.. includecode2:: ../../../../code/docs/http/scaladsl/server/directives/SecurityDirectivesExamplesSpec.scala
|
||||
:snippet: 0authenticateBasicPFAsync
|
||||
:snippet: authenticateBasicPFAsync-0
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
authenticateOAuth2
|
||||
==================
|
||||
|
||||
...
|
||||
Wraps the inner route with OAuth Bearer Token authentication support using a given ``AuthenticatorPF[T]``
|
||||
|
||||
Signature
|
||||
---------
|
||||
|
|
@ -16,10 +16,26 @@ Signature
|
|||
Description
|
||||
-----------
|
||||
|
||||
...
|
||||
Provides support for extracting the so-called "*Bearer Token*" from the :class:`Authorization` HTTP Header,
|
||||
which is used to initiate an OAuth2 authorization.
|
||||
|
||||
.. warning::
|
||||
This directive does not implement the complete OAuth2 protocol, but instead enables implementing it,
|
||||
by extracting the needed token from the HTTP headers.
|
||||
|
||||
Given a function returning ``Some[T]`` upon successful authentication and ``None`` otherwise,
|
||||
respectively applies the inner route or rejects the request with a :class:`AuthenticationFailedRejection` rejection,
|
||||
which by default is mapped to an ``401 Unauthorized`` response.
|
||||
|
||||
Longer-running authentication tasks (like looking up credentials in a database) should use the :ref:`-authenticateOAuth2Async-`
|
||||
variant of this directive which allows it to run without blocking routing layer of Akka HTTP, freeing it for other requests.
|
||||
|
||||
For more information on how OAuth2 works see `RFC 6750`_.
|
||||
|
||||
.. _RFC 6750: https://tools.ietf.org/html/rfc6750
|
||||
|
||||
Example
|
||||
-------
|
||||
|
||||
.. includecode2:: ../../../../code/docs/http/scaladsl/server/directives/SecurityDirectivesExamplesSpec.scala
|
||||
:snippet: authenticateOAuth2-0
|
||||
Usage in code is exactly the same as :ref:`-authenticateBasic-`,
|
||||
with the difference that one must validate the token as OAuth2 dictates (which is currently not part of Akka HTTP itself).
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
authenticateOAuth2Async
|
||||
=======================
|
||||
|
||||
...
|
||||
Wraps the inner route with OAuth Bearer Token authentication support using a given ``AsyncAuthenticator[T]``.
|
||||
|
||||
Signature
|
||||
---------
|
||||
|
|
@ -16,10 +16,26 @@ Signature
|
|||
Description
|
||||
-----------
|
||||
|
||||
...
|
||||
Provides support for extracting the so-called "*Bearer Token*" from the :class:`Authorization` HTTP Header,
|
||||
which is used to initiate an OAuth2 authorization.
|
||||
|
||||
.. warning::
|
||||
This directive does not implement the complete OAuth2 protocol, but instead enables implementing it,
|
||||
by extracting the needed token from the HTTP headers.
|
||||
|
||||
Given a function returning ``Some[T]`` upon successful authentication and ``None`` otherwise,
|
||||
respectively applies the inner route or rejects the request with a :class:`AuthenticationFailedRejection` rejection,
|
||||
which by default is mapped to an ``401 Unauthorized`` response.
|
||||
|
||||
See also :ref:`-authenticateOAuth2-` if the authorization operation is rather quick, and does not have to execute asynchronously.
|
||||
|
||||
For more information on how OAuth2 works see `RFC 6750`_.
|
||||
|
||||
.. _RFC 6750: https://tools.ietf.org/html/rfc6750
|
||||
|
||||
|
||||
Example
|
||||
-------
|
||||
|
||||
.. includecode2:: ../../../../code/docs/http/scaladsl/server/directives/SecurityDirectivesExamplesSpec.scala
|
||||
:snippet: authenticateOAuth2Async-0
|
||||
Usage in code is exactly the same as :ref:`-authenticateBasicAsync-`,
|
||||
with the difference that one must validate the token as OAuth2 dictates (which is currently not part of Akka HTTP itself).
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
authenticateOAuth2AsyncPF
|
||||
=========================
|
||||
|
||||
...
|
||||
Wraps the inner route with OAuth Bearer Token authentication support using a given ``AsyncAuthenticatorPF[T]``.
|
||||
|
||||
Signature
|
||||
---------
|
||||
|
|
@ -16,10 +16,27 @@ Signature
|
|||
Description
|
||||
-----------
|
||||
|
||||
...
|
||||
Provides support for extracting the so-called "*Bearer Token*" from the :class:`Authorization` HTTP Header,
|
||||
which is used to initiate an OAuth2 authorization.
|
||||
|
||||
.. warning::
|
||||
This directive does not implement the complete OAuth2 protocol, but instead enables implementing it,
|
||||
by extracting the needed token from the HTTP headers.
|
||||
|
||||
Refer to :ref:`-authenticateOAuth2-` for a detailed description of this directive.
|
||||
|
||||
Its semantics are equivalent to ``authenticateOAuth2PF`` 's, where not handling a case in the Partial Function (PF)
|
||||
leaves the request to be rejected with a :class:`AuthenticationFailedRejection` rejection.
|
||||
|
||||
See also :ref:`-authenticateOAuth2PF-` if the authorization operation is rather quick, and does not have to execute asynchronously.
|
||||
|
||||
For more information on how OAuth2 works see `RFC 6750`_.
|
||||
|
||||
.. _RFC 6750: https://tools.ietf.org/html/rfc6750
|
||||
|
||||
|
||||
Example
|
||||
-------
|
||||
|
||||
.. includecode2:: ../../../../code/docs/http/scaladsl/server/directives/SecurityDirectivesExamplesSpec.scala
|
||||
:snippet: authenticateOAuth2AsyncPF-0
|
||||
Usage in code is exactly the same as :ref:`-authenticateBasicAsyncPF-`,
|
||||
with the difference that one must validate the token as OAuth2 dictates (which is currently not part of Akka HTTP itself).
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
authenticateOAuth2PF
|
||||
====================
|
||||
|
||||
...
|
||||
Wraps the inner route with OAuth Bearer Token authentication support using a given ``AuthenticatorPF[T]``.
|
||||
|
||||
Signature
|
||||
---------
|
||||
|
|
@ -16,10 +16,27 @@ Signature
|
|||
Description
|
||||
-----------
|
||||
|
||||
...
|
||||
Provides support for extracting the so-called "*Bearer Token*" from the :class:`Authorization` HTTP Header,
|
||||
which is used to initiate an OAuth2 authorization.
|
||||
|
||||
.. warning::
|
||||
This directive does not implement the complete OAuth2 protocol, but instead enables implementing it,
|
||||
by extracting the needed token from the HTTP headers.
|
||||
|
||||
Refer to :ref:`-authenticateOAuth2-` for a detailed description of this directive.
|
||||
|
||||
Its semantics are equivalent to ``authenticateOAuth2PF`` 's, where not handling a case in the Partial Function (PF)
|
||||
leaves the request to be rejected with a :class:`AuthenticationFailedRejection` rejection.
|
||||
|
||||
Longer-running authentication tasks (like looking up credentials in a database) should use the :ref:`-authenticateOAuth2Async-`
|
||||
variant of this directive which allows it to run without blocking routing layer of Akka HTTP, freeing it for other requests.
|
||||
|
||||
For more information on how OAuth2 works see `RFC 6750`_.
|
||||
|
||||
.. _RFC 6750: https://tools.ietf.org/html/rfc6750
|
||||
|
||||
Example
|
||||
-------
|
||||
|
||||
.. includecode2:: ../../../../code/docs/http/scaladsl/server/directives/SecurityDirectivesExamplesSpec.scala
|
||||
:snippet: authenticateOAuth2PF-0
|
||||
Usage in code is exactly the same as :ref:`-authenticateBasicPF-`,
|
||||
with the difference that one must validate the token as OAuth2 dictates (which is currently not part of Akka HTTP itself).
|
||||
|
|
|
|||
|
|
@ -11,6 +11,11 @@ SecurityDirectives
|
|||
authenticateBasicPF
|
||||
authenticateBasicPFAsync
|
||||
authenticateOrRejectWithChallenge
|
||||
authenticateOAuth2
|
||||
authenticateOAuth2Async
|
||||
authenticateOAuth2PF
|
||||
authenticateOAuth2PFAsync
|
||||
authenticateOrRejectWithChallenge
|
||||
authorize
|
||||
extractCredentials
|
||||
|
||||
|
|
@ -50,4 +55,12 @@ credentials. You can see the currently registered schemes at http://www.iana.org
|
|||
At this point Akka HTTP only implements the "'Basic' HTTP Authentication Scheme" whose most current specification can be
|
||||
found here: https://datatracker.ietf.org/doc/draft-ietf-httpauth-basicauth-update/.
|
||||
|
||||
.. _RFC 7235: http://tools.ietf.org/html/rfc7235
|
||||
.. _RFC 7235: http://tools.ietf.org/html/rfc7235
|
||||
|
||||
Low-level OAuth2 "Bearer Token" directives
|
||||
------------------------------------------
|
||||
The OAuth2 directives currently provided in Akka HTTP are not a full OAuth2 protocol implementation,
|
||||
they are only a means of extracting the so called ``Bearer Token`` from the ``Authorization`` HTTP Header,
|
||||
as defined in `RFC 6750`_, and allow users to validate and complete the protocol.
|
||||
|
||||
.. _RFC 6750: https://tools.ietf.org/html/rfc6750
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue