Disallow login from TOR exit nodes

pull/339/head^2
Thibault Duplessis 2015-02-28 15:16:39 +01:00
parent 6b33a117a3
commit 5d8607a3eb
5 changed files with 62 additions and 11 deletions

View File

@ -37,14 +37,25 @@ object Auth extends LilaController {
session + ("sessionId" -> sessionId) - api.AccessUri session + ("sessionId" -> sessionId) - api.AccessUri
} }
} }
} recoverWith {
case lila.security.Api.AuthFromTorExitNode => negotiate(
html = Unauthorized(html.auth.tor()).fuccess,
api = _ => Unauthorized(Json.obj(
"error" -> "Can't login from TOR exit node"
)).fuccess
)
} }
) )
} }
def login = Open { implicit ctx => def login = Open { implicit ctx =>
if (Env.security.tor isExitNode ctx.req.remoteAddress)
Unauthorized(html.auth.tor()).fuccess
else {
val referrer = get("referrer") val referrer = get("referrer")
Ok(html.auth.login(api.loginForm, referrer)).fuccess Ok(html.auth.login(api.loginForm, referrer)).fuccess
} }
}
def authenticate = OpenBody { implicit ctx => def authenticate = OpenBody { implicit ctx =>
Firewall { Firewall {
@ -54,7 +65,7 @@ object Auth extends LilaController {
html = Unauthorized(html.auth.login(err, get("referrer"))).fuccess, html = Unauthorized(html.auth.login(err, get("referrer"))).fuccess,
api = _ => Unauthorized(err.errorsAsJson).fuccess api = _ => Unauthorized(err.errorsAsJson).fuccess
), ),
_.fold(InternalServerError("authenticate error").fuccess)(authenticateUser) _.fold(InternalServerError("Authentication error").fuccess)(authenticateUser)
) )
} }
} }
@ -69,10 +80,14 @@ object Auth extends LilaController {
} }
def signup = Open { implicit ctx => def signup = Open { implicit ctx =>
if (Env.security.tor isExitNode ctx.req.remoteAddress)
Unauthorized(html.auth.tor()).fuccess
else {
forms.signup.websiteWithCaptcha map { forms.signup.websiteWithCaptcha map {
case (form, captcha) => Ok(html.auth.signup(form, captcha)) case (form, captcha) => Ok(html.auth.signup(form, captcha))
} }
} }
}
private def doSignup(username: String, password: String)(res: UserModel => Fu[Result])(implicit ctx: lila.api.Context) = private def doSignup(username: String, password: String)(res: UserModel => Fu[Result])(implicit ctx: lila.api.Context) =
Firewall { Firewall {
@ -86,7 +101,15 @@ object Auth extends LilaController {
res(user) map { res(user) map {
_ withCookies LilaCookie.session("sessionId", sessionId) _ withCookies LilaCookie.session("sessionId", sessionId)
} }
} recoverWith {
case lila.security.Api.AuthFromTorExitNode => negotiate(
html = Unauthorized(html.auth.tor()).fuccess,
api = _ => Unauthorized(Json.obj(
"error" -> "Can't register from TOR exit node"
)).fuccess
)
} }
} }
} }

View File

@ -0,0 +1,20 @@
@()(implicit ctx: Context)
@auth.layout(
title = "TOR exit node",
zen = true) {
<div class="content_box small_box signup">
<div class="signup_box">
<h1 class="lichess_title text" data-icon="2">Cannot login from your IP</h1>
<p>
We have detected that you are using TOR to remain anonymous on the Internet.
<br />
<br />
It's a great idea, and we'll make sure you stay Anonymous on lichess as well.
<br />
<br />
As an Anonymous user, you can play, train, and use all lichess features. Enjoy!
</p>
</div>
</div>
}

File diff suppressed because one or more lines are too long

View File

@ -20,11 +20,14 @@ private[security] final class Api(firewall: Firewall, tor: Tor) {
) )
def saveAuthentication(id: String, apiVersion: Option[Int])(implicit req: RequestHeader): Fu[String] = { def saveAuthentication(id: String, apiVersion: Option[Int])(implicit req: RequestHeader): Fu[String] = {
if (tor isExitNode req.remoteAddress) fufail(Api.AuthFromTorExitNode)
else {
val sessionId = Random nextStringUppercase 12 val sessionId = Random nextStringUppercase 12
Store.save( Store.save(
sessionId, id, req, apiVersion, tor isExitNode req.remoteAddress sessionId, id, req, apiVersion, tor isExitNode req.remoteAddress
) inject sessionId ) inject sessionId
} }
}
// blocking function, required by Play2 form // blocking function, required by Play2 form
private def authenticateUser(username: String, password: String): Option[User] = private def authenticateUser(username: String, password: String): Option[User] =
@ -57,3 +60,8 @@ private[security] final class Api(firewall: Firewall, tor: Tor) {
} }
} }
} }
object Api {
case object AuthFromTorExitNode extends Exception
}

View File

@ -13,5 +13,5 @@ final class Tor(providerUrl: String) {
} }
} }
private[security] def isExitNode(ip: String) = ips contains ip def isExitNode(ip: String) = ips contains ip
} }