Warm tip: This article is reproduced from stackoverflow.com, please click
lift scala

Scala Lift: uniform authentication with form based login and HTTP basic auth?

发布于 2020-12-22 01:32:44

I use Lift (Scala Webframework) with RestHelper to provide a web-application as well as a web-service. Users may use the HTML forms of the webapplication or they may alternativly write their own service clients using the REST API. The html forms will be mainly implemented with JQuery using the REST API with AJAX to avoid duplicate functionality. I would like to protect the REST API using HTTP Basic Auth (or something similar). I also want to see that users who sign in to the web-application using lifts default login form don't need to perform additional basic authentication (since they already have a session created during form based login). How would I make this possible with Lift?

Currently, I do setup HTTP Basic Auth:

// Use Basic Authentication
LiftRules.authentication = HttpBasicAuthentication("lift") { 
  case (email, password, req) => {
User.find(By(User.email, email)) match {
      case Full(user) if user.password.match_?(password) => {
    userRoles(List(AuthRole("user"), AuthRole(user.id.toString)))
    User.logUserIn(user)
        true
      }
      case _ => false
} 
  }
} 

And define my protected REST API resources as follows:

// Protect REST API resources with Basic Auth (but only if user has no Session)
LiftRules.httpAuthProtectedResource.prepend{
  case Req("api" :: "users" :: userId :: _, _, _) =>
User.currentUser match {
  // if the user has already signed in per form we grant access
  case Full(user) => Empty 
  case _ => Full(AuthRole(userId))
}
} 

Unfortunately this does not work and the User.currentUser always returns no user. I have read somewhere that this is due to the fact that the users session is not yet initialized in this phase of the request lifecycle.

Is there any way in Lift to just protect resources indenpendtly of which authentication method is used? In principle I don't care how the user has authenticated (form auth, basic auth, digest auth). And if he did authenticate with form based login I dont want to challenge him with basic auth when he tries to access REST API resources (e.g. the web-application html forms will do this when making AJAX calls to the REST API).

Questioner
gruenewa
Viewed
0
rfreytag 2014-03-25 21:36

The code executed in LiftRules.httpAuthProtectedResource is executed in a stateless scope. Therefore you do not have access to any SessionVars generated earlier.

One way of implementing your case in my eyes is:

  1. Create a RESTful API in the stateless scope that uses basic-auth
  2. Create a second API in the stateful scope that checks the session-authentication.

You can propably use rewrite-rules to map one to the other, after you did the authentication.