Implemented basic support for OAuth2 authentication/authorization.
h3rald h3rald@h3rald.com
Sun, 14 Oct 2018 14:12:57 +0200
5 files changed,
40 insertions(+),
3 deletions(-)
M
.gitignore
→
.gitignore
@@ -4,6 +4,7 @@ *.db
*.db-journal http_api test.nim +auth.json html5 css3 sqlite3_analyzer
M
litestore.nimble
→
litestore.nimble
@@ -23,7 +23,7 @@ skipDirs = @["test"]
# Dependencies -requires "nim >= 0.18.0" +requires "nim >= 0.18.0", "https://github.com/h3rald/nim-jwt" # Build
M
src/litestorepkg/lib/cli.nim
→
src/litestorepkg/lib/cli.nim
@@ -1,7 +1,8 @@
import parseopt, strutils, - strtabs + strtabs, + json import logger, config,@@ -16,6 +17,7 @@ directory:string = ""
readonly = false logLevel = "warn" mount = false + auth = newJNull() exOperation:string = "" exFile:string = "" exBody:string = ""@@ -129,6 +131,10 @@ of "type", "t":
if val == "": fail(113, "Content type not specified.") exType = val + of "auth": + if val == "": + fail(114, "Authentication/Authorization configuration file not specified.") + auth = val.parseFile of "mount", "m": mount = true of "version", "v":@@ -166,6 +172,7 @@ LS.directory = directory
LS.readonly = readonly LS.favicon = favicon LS.loglevel = loglevel +LS.auth = auth LS.mount = mount LS.execution.file = exFile LS.execution.body = exBody
M
src/litestorepkg/lib/server.nim
→
src/litestorepkg/lib/server.nim
@@ -7,7 +7,10 @@ pegs,
strtabs, logger, cgi, - os + os, + json, + tables, + jwt import types, utils,@@ -33,6 +36,30 @@ LOG.info("Exiting...")
quit() proc processApiUrl(req: LSRequest, LS: LiteStore, info: ResourceInfo): LSResponse = + let reqUri = info.resource & "/" & info.id + let uriParts = reqUri.split("/") + let uri = "/" & uriParts[0..uriParts.len-2].join("/") & "/" + let reqMethod = $req.reqMethod + # Authentication/Authorization + if LS.auth != newJNull(): + if LS.auth["access"].hasKey(uri): + let access = LS.auth["access"][uri] + if access.hasKey(reqMethod): + if not req.headers.hasKey("Authorization"): + return resError(Http401, "Unauthorized - No token") + let token = req.headers["Authorization"].replace(peg"^ 'Bearer '", "") + # Validate token + try: + let jwt = token.toJwt() + var sig = LS.auth["signature"].getStr + discard verify(jwt, sig) + verifyTimeClaims(jwt) + # Validate scope + let scopes = $jwt.claims["scope"].node.str.split(peg"\s+") + if not scopes.contains access[reqMethod].getStr: + return resError(Http403, "Forbidden - You are not permitted to access this resource") + except: + return resError(Http401, "Unauthorized - Invalid token") if info.version == "v4": if info.resource.match(peg"^docs / info / tags$"): return api_v4.route(req, LS, info.resource, info.id)
M
src/litestorepkg/lib/types.nim
→
src/litestorepkg/lib/types.nim
@@ -2,6 +2,7 @@ import
x_db_sqlite, asynchttpserver, pegs, + json, strtabs import config@@ -76,6 +77,7 @@ mount*: bool
readonly*: bool appname*: string appversion*: string + auth*: JsonNode favicon*:string loglevel*:string LSRequest* = asynchttpserver.Request