Last active
December 8, 2017 13:56
-
-
Save casualjim/4400115 to your computer and use it in GitHub Desktop.
Session token strategy example for scalatra auth (scentry)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package org.example | |
package auth | |
import org.scalatra.auth.ScentryStrategy | |
import org.scalatra.{CookieSupport, ScalatraBase} | |
trait RedisClient { | |
def get(key: String): Option[String] | |
} | |
object User { | |
def apply(userString: String) = // create user from string stored in redis | |
} | |
case class User(id: Int, login: String, password: String, token: String = UUID.create.toString) | |
object UsersDao { | |
private[this] val client: RedisClient = // create redis client here | |
def fromToken(token: String): Option[User] = client.get("users:*:token", token) map User | |
def fromLoginPassword(login: String, password: String) = client.get("users:*:login", login) map User filter (_.password == password) | |
} | |
object SessionTokenStrategy { | |
val HeaderKey = "X-API-KEY" | |
val ParamsKey = "api_key" | |
val CookieKey = "scalatra.auth" | |
} | |
class SessionTokenStrategy(protected val app: ScalatraBase with CookieSupport) extends ScentryStrategy[User] { | |
import SessionTokenStrategy._ | |
override def isValid: Boolean = | |
((app.request.header(HeaderKey) orElse app.params.get(ParamsKey) orElse app.cookies.get(CookieKey)) flatMap (_.blankOption)).isDefined | |
def authenticate(): Option[User] = { | |
val token = (app.request.header(HeaderKey) orElse app.params.get(ParamsKey) orElse app.cookies.get(CookieKey)) flatMap (_.blankOption) | |
token flatMap { UsersDao.fromToken(token) } | |
} | |
} | |
class PasswordStrategy(protected val app: ScalatraBase) extends ScentryStrategy[User] { | |
override def isValid = app.params.get("login").isDefined && app.params.get("password").isDefined | |
def authenticate(): Option[User] = UsersDao.fromLoginPassword(app.params("login"), app.params("password")) | |
} | |
trait MyAuthentication extends ScentrySupport[User] { | |
protected def fromSession = { case id: String ⇒ UsersDao.fromToken } | |
protected def toSession = { case usr: User ⇒ usr.token } | |
/** | |
* Registers authentication strategies. | |
*/ | |
override protected def configureScentry { | |
val authCookieOptions = CookieOptions(httpOnly = true) | |
scentry.store = new CookieAuthStore(self)(authCookieOptions) { | |
override def set(value: String) { | |
super.set(value) | |
response.headers("X-SCALATRA-AUTH") = value | |
} | |
override def get: String = { | |
val cookie = super.get | |
if (cookie == null || cookie.trim.isEmpty) request.header("X-SCALATRA-AUTH").orNull | |
else cookie | |
} | |
override def invalidate() { | |
cookies.update(Scentry.scentryAuthKey, "")(authCookieOptions.copy(maxAge = 0)) | |
response.headers("X-SCALATRA-AUTH") = null | |
} | |
} | |
scentry.unauthenticated { unauthenticated() } | |
} | |
override protected def registerAuthStrategies = { | |
scentry.register("user_password", _ ⇒ new PasswordStrategy(self)) | |
scentry.register("session_token", _ ⇒ new SessionTokenStrategy(self)) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment