diff --git a/view-webapp/pom.xml b/view-webapp/pom.xml index dfc2938..6e51093 100644 --- a/view-webapp/pom.xml +++ b/view-webapp/pom.xml @@ -92,6 +92,7 @@ ${pairgoth.logger.format} debug ${pairgoth.auth} + ${pairgoth.auth.sesame} debug diff --git a/view-webapp/src/main/kotlin/org/jeudego/pairgoth/web/AuthFilter.kt b/view-webapp/src/main/kotlin/org/jeudego/pairgoth/web/AuthFilter.kt index d0de1b7..39e4774 100644 --- a/view-webapp/src/main/kotlin/org/jeudego/pairgoth/web/AuthFilter.kt +++ b/view-webapp/src/main/kotlin/org/jeudego/pairgoth/web/AuthFilter.kt @@ -29,22 +29,31 @@ class AuthFilter: Filter { val session: HttpSession? = request.getSession(false) val auth = WebappManager.getProperty("auth") ?: throw Error("authentication not configured") - if (auth == "none" || whitelist.contains(uri) || uri.contains(Regex("\\.(?!html)")) || session?.getAttribute("logged") != null) { + if (auth == "none" || whitelisted(uri) || session?.getAttribute("logged") != null) { chain.doFilter(req, resp) } else { // TODO - configure if unauth requests are redirected and/or forwarded // TODO - protection against brute force attacks - if (uri == "/index") { + if (uri.endsWith("/index")) { request.getRequestDispatcher("/index-ffg").forward(req, resp) } else { response.sendRedirect("/login") } } } + companion object { private val whitelist = setOf( "/index-ffg", - "/login" + "/login", + "/api/login" ) + + fun whitelisted(uri: String): Boolean { + if (uri.contains(Regex("\\.(?!html)"))) return true + val nolangUri = uri.replace(Regex("^/../"), "/") + return whitelist.contains(nolangUri) + } + } -} \ No newline at end of file +} diff --git a/view-webapp/src/main/kotlin/org/jeudego/pairgoth/web/LoginServlet.kt b/view-webapp/src/main/kotlin/org/jeudego/pairgoth/web/LoginServlet.kt new file mode 100644 index 0000000..3fe3022 --- /dev/null +++ b/view-webapp/src/main/kotlin/org/jeudego/pairgoth/web/LoginServlet.kt @@ -0,0 +1,41 @@ +package org.jeudego.pairgoth.web + +import com.republicate.kson.Json +import org.slf4j.LoggerFactory +import javax.servlet.http.HttpServlet +import javax.servlet.http.HttpServletRequest +import javax.servlet.http.HttpServletResponse + +class LoginServlet: HttpServlet() { + + override fun doPost(req: HttpServletRequest, resp: HttpServletResponse) { + try { + val contentType = req.contentType + val sep = contentType.indexOf(';') + val mimeType = if (sep == -1) contentType else contentType.substring(0, sep).trim { it <= ' ' } + if (!isJson(mimeType)) throw Error("expecting json") + val payload = Json.Companion.parse(req.reader.readText())?.asObject() ?: throw Error("null json") + val user = when (WebappManager.getProperty("auth")) { + "sesame" -> checkSesame(payload) + else -> null + } ?: throw Error("authentication failed") + req.session.setAttribute("logged", user) + val ret = Json.Object("status" to "ok") + resp.contentType = "application/json" + resp.writer.println(ret.toString()) + } catch (t: Throwable) { + logger.error("exception while logging in", t) + resp.sendError(HttpServletResponse.SC_BAD_REQUEST) + } + } + + fun checkSesame(payload: Json.Object): Boolean? { + val expected = WebappManager.getProperty("auth.sesame") ?: throw Error("sesame wrongly configured") + return if (payload.getString("sesame")?.equals(expected) == true) true else null + } + + companion object { + fun isJson(mimeType: String) = "text/json" == mimeType || "application/json" == mimeType || mimeType.endsWith("+json") + val logger = LoggerFactory.getLogger("login") + } +} diff --git a/view-webapp/src/main/webapp/WEB-INF/web.xml b/view-webapp/src/main/webapp/WEB-INF/web.xml index 0806011..d36618f 100644 --- a/view-webapp/src/main/webapp/WEB-INF/web.xml +++ b/view-webapp/src/main/webapp/WEB-INF/web.xml @@ -88,6 +88,12 @@ 1 true + + login + org.jeudego.pairgoth.web.LoginServlet + 1 + true + @@ -110,6 +116,10 @@ import /api/import/* + + login + /api/login + diff --git a/view-webapp/src/main/webapp/js/main.js b/view-webapp/src/main/webapp/js/main.js index cd41608..6059fd3 100644 --- a/view-webapp/src/main/webapp/js/main.js +++ b/view-webapp/src/main/webapp/js/main.js @@ -219,7 +219,7 @@ onLoad(() => { break; } case 'ArrowDown': { - if (searchResultShown()) { + if (typeof(searchResultShown) === 'function' && searchResultShown()) { let lines = $('.result-line'); if (typeof (searchHighlight) === 'undefined') searchHighlight = 0; else ++searchHighlight; @@ -230,7 +230,7 @@ onLoad(() => { break; } case 'ArrowUp': { - if (searchResultShown()) { + if (typeof(searchResultShown) === 'function' && searchResultShown()) { let lines = $('.result-line'); if (typeof (searchHighlight) === 'undefined') searchHighlight = 0; else --searchHighlight; @@ -241,10 +241,12 @@ onLoad(() => { break; } case 'Enter': { - if (searchResultShown()) { - fillPlayer(searchResult[searchHighlight]); - } else { - $('#register')[0].click(); + if (typeof(searchResultShown) === 'function') { + if (searchResultShown()) { + fillPlayer(searchResult[searchHighlight]); + } else { + $('#register')[0].click(); + } } break; } diff --git a/view-webapp/src/main/webapp/login.html b/view-webapp/src/main/webapp/login.html index 753ce72..5564d8c 100644 --- a/view-webapp/src/main/webapp/login.html +++ b/view-webapp/src/main/webapp/login.html @@ -1,8 +1,8 @@
-
+
- +
@@ -10,9 +10,9 @@