authenticateBasicPFAsync • Akka HTTP (original) (raw)

Signature

type AsyncAuthenticatorPF[T] = PartialFunction[Credentials, Future[T]]
def authenticateBasicPFAsync[T](realm: String, authenticator: AsyncAuthenticatorPF[T]): AuthenticationDirective[T]

Description

Wraps the inner route with Http Basic authentication support using a given AsyncAuthenticatorPF[T]AsyncAuthenticatorPF<T> - Partial function from Optional<ProvidedCredentials> to CompletionStage<User>.

Provides support for handling HTTP Basic Authentication.

Refer to 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 AuthenticationFailedRejectionAuthenticationFailedRejection rejection.

See Credentials and password timing attacks for details about verifying the secret.

Warning

Make sure to use basic authentication only over SSL/TLS because credentials are transferred in plaintext.

Example

Scala

source`` 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}'") } } }

// tests: 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", Some("secure site"), Map("charset" -> "UTF-8")) }

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", Some("secure site"), Map("charset" -> "UTF-8")) } ``

Java

source`import akka.http.javadsl.server.directives.SecurityDirectives.ProvidedCredentials;

import static akka.http.javadsl.server.Directives.authenticateBasicPFAsync; import static akka.http.javadsl.server.Directives.complete; import static akka.http.javadsl.server.Directives.path;

class User { private final String id; public User(String id) { this.id = id; } public String getId() { return id; } }

final PartialFunction<Optional, CompletionStage> myUserPassAuthenticator = new JavaPartialFunction<Optional,CompletionStage>() { @Override public CompletionStage apply(Optional opt, boolean isCheck) throws Exception { if (opt.filter(c -> (c != null) && c.verify("p4ssw0rd")).isPresent()) { if (isCheck) return CompletableFuture.completedFuture(null); else return CompletableFuture.completedFuture(new User(opt.get().identifier())); } else { throw noMatch(); } } };

final Route route = path("secured", () -> authenticateBasicPFAsync("secure site", myUserPassAuthenticator, user -> complete("The user is '" + user.getId() + "'")) ).seal();

// tests: testRoute(route).run(HttpRequest.GET("/secured")) .assertStatusCode(StatusCodes.UNAUTHORIZED) .assertEntity("The resource requires authentication, which was not supplied with the request") .assertHeaderExists("WWW-Authenticate", "Basic realm="secure site",charset=UTF-8");

final HttpCredentials validCredentials = BasicHttpCredentials.createBasicHttpCredentials("John", "p4ssw0rd"); testRoute(route).run(HttpRequest.GET("/secured").addCredentials(validCredentials)) .assertEntity("The user is 'John'");

final HttpCredentials invalidCredentials = BasicHttpCredentials.createBasicHttpCredentials("Peter", "pan"); testRoute(route).run(HttpRequest.GET("/secured").addCredentials(invalidCredentials)) .assertStatusCode(StatusCodes.UNAUTHORIZED) .assertEntity("The supplied authentication is invalid") .assertHeaderExists("WWW-Authenticate", "Basic realm="secure site",charset=UTF-8");`

Found an error in this documentation? The source code for this page can be found here. Please feel free to edit and contribute a pull request.