0

I am trying a basic authentication on post request in spray.io 1.3.2 using authenticate directive. My code looks following:

  val route: Route = {
    pathPrefix("ato") {
      pathPrefix("v1") {
        path("orders" / "updateStatus") {
          post {
            authenticate(BasicAuth(userPasswordAuthenticator _, realm = "bd ato import api")) {
              user =>
                entity(as[String]) {e =>
                  complete {
                    s"Hello $e "
                  }
                }
            }
          }

        }
      }
    }
  }

  def userPasswordAuthenticator(userPass: Option[UserPass]): Future[Option[String]] =
    Future {
      if (userPass.exists(up => up.user == ato_import_v1_usr && up.pass == ato_import_v1_pwd)) Some("ato_v1")
      else None
    }

This works perfectly fine, authorized Status Ok 200, unauthorized 401. However when the order of directives is changed as follows:

  val route: Route = {
    pathPrefix("ato") {
      pathPrefix("v1") {
        authenticate(BasicAuth(userPasswordAuthenticator _, realm = "bd ato import api")) {
          user =>
        path("orders" / "updateStatus") {
          post {
                entity(as[String]) {e =>
                  complete {
                    s"Hello $e "

                  }
                }
            }
          }

        }
      }
    }
  }

I am getting Status 405, HTTP method not allowed for unauthorized access. I am not sure why that happens. From certain point it make sense, path is not matched because of missing credentials etc.

Could someone please clarify that?

The reason why I wanted to put authorization at v1 level is that I wanted to make every version protected by different password. Is there a way how to achieve that? What is the best practice in chaining directives?

I would like to follow DRY principle.

Thanks

jaksky
  • 3,305
  • 4
  • 35
  • 68
  • That's probably because of another route part that you use in front of what you show here. If you only have `get`-routes before the given one, spray-routing has to decide if the problem is that the request wasn't a `get` request or that it was missing authentication. It chooses that based on the order in which route parts are chained together. – jrudolph May 17 '15 at 11:49
  • For DRYness, you can always extract directives into extra defs: E.g. create `def requireAuthentication = authenticate(BasicAuth(userPasswordAuthenticator _, realm = "bd ato import api"))` and use it everywhere in your route where it is needed. – jrudolph May 17 '15 at 11:50

0 Answers0