WYSIWYG

http://kufli.blogspot.com
http://github.com/karthik20522

Saturday, August 17, 2013

Spray.io REST service - Authentication - Lesson 5

View the lessons list at https://github.com/karthik20522/SprayLearning

"Directives" are small building blocks of which you can construct arbitrarily complex route structures. A directive does one or more of the following:
  • Transform the incoming RequestContext before passing it on to its inner route
  • Filter the RequestContext according to some logic, i.e. only pass on certain requests and reject all others
  • Apply some logic to the incoming RequestContext and create objects that are made available to inner routes as "extractions"
  • Complete the request
More detailed information on directives can be found at http://spray.io/documentation/1.2-M8/ or here Spray-routing/predefined-directives-alphabetically/. In future examples, I would be using Directives so basic understanding would be useful. For this example I would be using Authentication directive to validate the request with a username and password as part of the header.

So, for authentication a new UserAuthentication trait is created which has a function that returns a ContextAuthenticator. The authenticate directive expects either a ContextAuthenticator or a Future[Authenication[T]]. At the crust of ContextAuthenticator is basically Future[Authenication[T]].

Below code that describes the authentication directive basically takes in a ContextAuthenticator and returns a Future of Authentication type of Either Rejection or an Object of type T. What this means is that Either a Rejection is returned (Left) like FailedAuthenticationRejection when credentials are missing or failed; or when successful an object is returned (Right)

The UserAuthentication trait has two functions, one that returns a ContextAuthentication and other that returns a Future. In this example, I am reading the username and password from the application.conf file and validating against it.
Note that I am importing "scala.concurrent.ExecutionContext.Implicits.global", this is because futures require an ExecutionContext and I letting spray to use the default actor ExecutingContext. //implicit val system = ActorSystem("on-spray-can")

Now that we have the authentication setup, we need to inherit the UserAuthenticationTrait using "with" and use the "authentication" directive by passing the "authenticateUser" function that we defined.


Further readings on this topic:
Spray/routing/authentication/HttpAuthenticator.scala
Spray/routing/SecurityDirectivesSpec.scala
https://groups.google.com/forum/#!topic/spray-user/5DBEZUXbjtw
Spray/routing/RejectionHandler.scala

Labels: , ,