authenticateBasic
Signature
type Authenticator[T] = Credentials => Option[T]
def authenticateBasic[T](realm: String, authenticator: Authenticator[T]): AuthenticationDirective[T] Description
Wraps the inner route with Http Basic authentication support using a given Authenticator[T]Authenticator<T> - function from Optional<ProvidedCredentials> to Optional<T>.
Provides support for handling HTTP Basic Authentication.
Given a function returning Some[T]an Optional<T> with a value upon successful authentication and Nonean empty Optional<T> otherwise, respectively applies the inner route or rejects the request with a AuthenticationFailedRejectionAuthenticationFailedRejection 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 authenticateBasicAsync variant of this directive which allows it to run without blocking routing layer of Apache Pekko HTTP, freeing it for other requests.
Standard HTTP-based authentication which uses the WWW-Authenticate header containing challenge data and AuthorizationAuthorization header for receiving credentials is implemented in authenticateOrRejectWithChallenge.
See Credentials and password timing attacks for details about verifying the secret.
Make sure to use basic authentication only over SSL/TLS because credentials are transferred in plaintext.
Example
- Scala
-
source
def myUserPassAuthenticator(credentials: Credentials): Option[String] = credentials match { case p @ Credentials.Provided(id) if p.verify("p4ssw0rd") => Some(id) case _ => None } val route = Route.seal { path("secured") { authenticateBasic(realm = "secure site", myUserPassAuthenticator) { userName => complete(s"The user is '$userName'") } } } // 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 org.apache.pekko.http.javadsl.server.directives.SecurityDirectives.ProvidedCredentials; import static org.apache.pekko.http.javadsl.server.Directives.authenticateBasic; import static org.apache.pekko.http.javadsl.server.Directives.complete; import static org.apache.pekko.http.javadsl.server.Directives.path; final Function<Optional<ProvidedCredentials>, Optional<String>> myUserPassAuthenticator = credentials -> credentials.filter(c -> c.verify("p4ssw0rd")).map(ProvidedCredentials::identifier); final Route route = path( "secured", () -> authenticateBasic( "secure site", myUserPassAuthenticator, userName -> complete("The user is '" + userName + "'"))) .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");