Skip to main content
Version: 2.0.x

Authentication Example

Authentication Server Example

zio-http-example/src/main/scala/example/AuthenticationServer.scala
package example

import java.time.Clock

import zio._

import zio.http.Middleware.bearerAuth
import zio.http._
import zio.http.codec.PathCodec.string

import pdi.jwt.{Jwt, JwtAlgorithm, JwtClaim}

object AuthenticationServer extends ZIOAppDefault {

/**
* This is an example to demonstrate barer Authentication middleware. The
* Server has 2 routes. The first one is for login,Upon a successful login, it
* will return a jwt token for accessing protected routes. The second route is
* a protected route that is accessible only if the request has a valid jwt
* token. AuthenticationClient example can be used to makes requests to this
* server.
*/

// Secret Authentication key
val SECRET_KEY = "secretKey"

implicit val clock: Clock = Clock.systemUTC

// Helper to encode the JWT token
def jwtEncode(username: String): String = {
val json = s"""{"user": "${username}"}"""
val claim = JwtClaim {
json
}.issuedNow.expiresIn(300)
Jwt.encode(claim, SECRET_KEY, JwtAlgorithm.HS512)
}

// Helper to decode the JWT token
def jwtDecode(token: String): Option[JwtClaim] = {
Jwt.decode(token, SECRET_KEY, Seq(JwtAlgorithm.HS512)).toOption
}

// Http app that is accessible only via a jwt token
def user: HttpApp[Any] = Routes(
Method.GET / "user" / string("name") / "greet" -> handler { (name: String, _: Request) =>
Response.text(s"Welcome to the ZIO party! ${name}")
},
).toHttpApp @@ bearerAuth(jwtDecode(_).isDefined)

// App that let's the user login
// Login is successful only if the password is the reverse of the username
def login: HttpApp[Any] =
Routes(
Method.GET / "login" / string("username") / string("password") ->
handler { (username: String, password: String, _: Request) =>
if (password.reverse.hashCode == username.hashCode) Response.text(jwtEncode(username))
else Response.text("Invalid username or password.").status(Status.Unauthorized)
},
).toHttpApp

// Composing all the HttpApps together
val app: HttpApp[Any] = login ++ user

// Run it like any simple app
override val run = Server.serve(app).provide(Server.default)
}

Authentication Client Example

zio-http-example/src/main/scala/example/AuthenticationClient.scala
package example

import zio._

import zio.http._

object AuthenticationClient extends ZIOAppDefault {

/**
* This example is trying to access a protected route in AuthenticationServer
* by first making a login request to obtain a jwt token and use it to access
* a protected route. Run AuthenticationServer before running this example.
*/
val url = "http://localhost:8090"

val loginUrl = URL.decode(s"${url}/login/username/emanresu").toOption.get
val greetUrl = URL.decode(s"${url}/user/userName/greet").toOption.get

val program = for {
client <- ZIO.service[Client]
// Making a login request to obtain the jwt token. In this example the password should be the reverse string of username.
token <- client(Request.get(loginUrl)).flatMap(_.body.asString)
// Once the jwt token is procured, adding it as a Bearer token in Authorization header while accessing a protected route.
response <- client(Request.get(greetUrl).addHeader(Header.Authorization.Bearer(token)))
body <- response.body.asString
_ <- Console.printLine(body)
} yield ()

override val run = program.provide(Client.default, Scope.default)

}

Middleware Basic Authentication Example

zio-http-example/src/main/scala/example/BasicAuth.scala
package example

import zio._

import zio.http.Middleware.basicAuth
import zio.http._
import zio.http.codec.PathCodec.string

object BasicAuth extends ZIOAppDefault {

// Http app that requires a JWT claim
val user: HttpApp[Any] = Routes(
Method.GET / "user" / string("name") / "greet" ->
handler { (name: String, _: Request) =>
Response.text(s"Welcome to the ZIO party! ${name}")
},
).toHttpApp

// Composing all the HttpApps together
val app: HttpApp[Any] = user @@ basicAuth("admin", "admin")

// Run it like any simple app
val run = Server.serve(app).provide(Server.default)
}