Hi All, In this blog, I will try to explain what is Authentication and why we need this and how you can do authentication in Akka HTTP
What is Authentication:- Authentication is the process of establishing a known identity for the user, whereby ‘identity’ is defined in the context of the application. This may be done with a username/password combination, a cookie, a pre-defined IP or some other mechanism. After authentication, the system believes that it knows who the user is.
Why Authentication:- Authentication is a security mechanism designed to ensure that only authorized users can connect to a given service.
Authenticating both the user and the device can provide two-factor authentication (2FA). For a smartphone, there are apps that provide one-time password tokens, allowing the phone itself to serve as the physical device to satisfy the possession factor. The password response sent from the registered device verifies that the user is connecting from an authorized endpoint.
How Akka HTTP provides Authentication:- Akka HTTP uses the many prebuild SecurityDirectives for authenticating the users.
Let’s take an example of Bearer token authentication.
Most of the time what we do is, we write the code for authentication at a single place but perform the corresponding action on the basis of response of authentication in every route (if token is valid then fetch the users details by token and if not then send the response as bad request) we fetch the user details by token on every route but why ?
we should have a type of mechanism that, if the token is valid then the user data should be fetched at one place and provided to my routes and if the token is invalid then the request should be rejected from my authentication code, we don’t need to check the authentication response in every route.
So for handling that type of mechanism, Akka HTTP provides many directives, in these directives you just need to provide your authentication code for validating the token and if the token is invalid then just reject the request.
Let’s take an example of a directive extractCredentials that is used for extracting the credentials from the request headers
def authenticatedWithHeader: Directive1[User] = for { credentials <- extractCredentials result <- { credentials match { case Some(c) if c.scheme.equalsIgnoreCase("Bearer") => authenticate(c.token) case _ => rejectUnauthenticated(AuthenticationFailedRejection.CredentialsMissing) } } } yield result
In this code we get the token in the request header and check if it’s type is Bearer or not.
If it is Bearer type then we fetch the user and if it’s not then we reject the request by rejectUnauthenticated(AuthenticationFailedRejection.CredentialsMissing)
def authenticate(token: String): Directive1[User] = { validateAccessToken(token) match { case Some(user) => provide(user) case None => rejectUnauthenticated(AuthenticationFailedRejection.CredentialsRejected) } }
def validateAccessToken(token):Option[User] = ??? // Your business logic that will fetch the user by Token
Let’s take an example that how you can call it from the route
val route = path("Authentication") { authenticated { user => get { complete("This is authorized user") } } }
In this route authenticated will authenticate the user by the token and will provide it if the token is valid.
Hope this blog will help you more in authentication part. 🙂