mirror of
https://github.com/status-im/nimbus-eth1.git
synced 2025-01-12 05:14:14 +00:00
Facilitate http code response on websocket JWT authentication failure (#1043)
* Facilitate http code response on websocket JWT authentication failure * Update JSON-RPC link
This commit is contained in:
parent
737236fd6e
commit
8af5c33ef9
@ -190,7 +190,7 @@ proc localServices(nimbus: NimbusNode, conf: NimbusConf,
|
|||||||
msg = $(rc.unsafeError) # avoid side effects
|
msg = $(rc.unsafeError) # avoid side effects
|
||||||
quit(QuitFailure)
|
quit(QuitFailure)
|
||||||
# Authentcation handler constructor
|
# Authentcation handler constructor
|
||||||
@[rc.value.jwtAuthAsyHook]
|
some(rc.value.jwtAuthHandler)
|
||||||
|
|
||||||
# Creating Websocket RPC Server
|
# Creating Websocket RPC Server
|
||||||
if conf.wsEnabled:
|
if conf.wsEnabled:
|
||||||
|
@ -18,6 +18,7 @@ import
|
|||||||
chronicles,
|
chronicles,
|
||||||
chronos,
|
chronos,
|
||||||
chronos/apps/http/httptable,
|
chronos/apps/http/httptable,
|
||||||
|
json_rpc/servers/websocketserver,
|
||||||
httputils,
|
httputils,
|
||||||
websock/types as ws,
|
websock/types as ws,
|
||||||
nimcrypto/[hmac, utils],
|
nimcrypto/[hmac, utils],
|
||||||
@ -39,19 +40,9 @@ const
|
|||||||
32
|
32
|
||||||
|
|
||||||
type
|
type
|
||||||
# -- currently unused --
|
JwtAuthHandler* = ##\
|
||||||
#
|
## Generic authentication handler, also provided by the web-socket server.
|
||||||
#JwtAuthHandler* = ##\
|
RpcWebSocketServerAuth
|
||||||
# ## JSW authenticator prototype
|
|
||||||
# proc(req: HttpTable): Result[void,(HttpCode,string)]
|
|
||||||
# {.gcsafe, raises: [Defect].}
|
|
||||||
#
|
|
||||||
|
|
||||||
JwtAuthAsyHandler* = ##\
|
|
||||||
## Asynchroneous JSW authenticator prototype. This is the definition
|
|
||||||
## appicable for the `verify` entry of a `ws.Hook`.
|
|
||||||
proc(req: HttpTable): Future[Result[void,string]]
|
|
||||||
{.closure, gcsafe, raises: [Defect].}
|
|
||||||
|
|
||||||
JwtSharedKey* = ##\
|
JwtSharedKey* = ##\
|
||||||
## Convenience type, needed quite often
|
## Convenience type, needed quite often
|
||||||
@ -269,68 +260,29 @@ proc jwtSharedSecret*(rng: ref BrHmacDrbgContext; config: NimbusConf):
|
|||||||
result = rng.jwtGenSecret.jwtSharedSecret(config)
|
result = rng.jwtGenSecret.jwtSharedSecret(config)
|
||||||
|
|
||||||
|
|
||||||
# -- currently unused --
|
proc jwtAuthHandler*(key: JwtSharedKey): JwtAuthHandler =
|
||||||
#
|
## Returns a JWT authentication handler that can be used with an HTTP header
|
||||||
#proc jwtAuthHandler*(key: JwtSharedKey): JwtAuthHandler =
|
## based call back system as the web socket server.
|
||||||
# ## Returns a JWT authentication handler that can be used with an HTTP header
|
|
||||||
# ## based call back system.
|
|
||||||
# ##
|
|
||||||
# ## The argument `key` is captured by the session handler for JWT
|
|
||||||
# ## authentication. The function `jwtSharedSecret()` provides such a key.
|
|
||||||
# result = proc(req: HttpTable): Result[void,(HttpCode,string)] =
|
|
||||||
# let auth = req.getString("Authorization","?")
|
|
||||||
# if auth.len < 9 or auth[0..6].cmpIgnoreCase("Bearer ") != 0:
|
|
||||||
# return err((Http403, "Missing Token"))
|
|
||||||
#
|
|
||||||
# let rc = auth[7..^1].strip.verifyTokenHS256(key)
|
|
||||||
# if rc.isOk:
|
|
||||||
# return ok()
|
|
||||||
#
|
|
||||||
# debug "Could not authenticate",
|
|
||||||
# error = rc.error
|
|
||||||
#
|
|
||||||
# case rc.error:
|
|
||||||
# of jwtTokenValidationError, jwtMethodUnsupported:
|
|
||||||
# return err((Http401, "Unauthorized"))
|
|
||||||
# else:
|
|
||||||
# return err((Http403, "Malformed Token"))
|
|
||||||
#
|
|
||||||
|
|
||||||
proc jwtAuthAsyHandler*(key: JwtSharedKey): JwtAuthAsyHandler =
|
|
||||||
## Returns an asynchroneous JWT authentication handler that can be used with
|
|
||||||
## an HTTP header based call back system.
|
|
||||||
##
|
##
|
||||||
## The argument `key` is captured by the session handler for JWT
|
## The argument `key` is captured by the session handler for JWT
|
||||||
## authentication. The function `jwtSharedSecret()` provides such a key.
|
## authentication. The function `jwtSharedSecret()` provides such a key.
|
||||||
result = proc(req: HttpTable): Future[Result[void,string]] {.async.} =
|
result = proc(req: HttpTable): Result[void,(HttpCode,string)] {.gcsafe.} =
|
||||||
let auth = req.getString("Authorization","?")
|
let auth = req.getString("Authorization","?")
|
||||||
if auth.len < 9 or auth[0..6].cmpIgnoreCase("Bearer ") != 0:
|
if auth.len < 9 or auth[0..6].cmpIgnoreCase("Bearer ") != 0:
|
||||||
return err("Missing Token")
|
return err((Http403, "Missing Token"))
|
||||||
|
|
||||||
let rc = auth[7..^1].strip.verifyTokenHS256(key)
|
let rc = auth[7..^1].strip.verifyTokenHS256(key)
|
||||||
if rc.isOk:
|
if rc.isOk:
|
||||||
return ok()
|
return ok()
|
||||||
|
|
||||||
debug "Could not authenticate",
|
debug "Could not authenticate",
|
||||||
error = rc.error
|
error = rc.error
|
||||||
|
|
||||||
case rc.error:
|
case rc.error:
|
||||||
of jwtTokenValidationError, jwtMethodUnsupported:
|
of jwtTokenValidationError, jwtMethodUnsupported:
|
||||||
return err("Unauthorized")
|
return err((Http401, "Unauthorized"))
|
||||||
else:
|
else:
|
||||||
return err("Malformed Token")
|
return err((Http403, "Malformed Token"))
|
||||||
|
|
||||||
proc jwtAuthAsyHook*(key: JwtSharedKey): ws.Hook =
|
|
||||||
## Variant of `jwtAuthHandler()` (e.g. directly suitable for Json WebSockets.)
|
|
||||||
##
|
|
||||||
## Note that currently there is no meaningful way to send a http 401/403 in
|
|
||||||
## case of an authentication problem.
|
|
||||||
let handler = key.jwtAuthAsyHandler
|
|
||||||
ws.Hook(
|
|
||||||
append: proc(ctx: ws.Hook, req: var HttpTable): Result[void,string] =
|
|
||||||
ok(),
|
|
||||||
verify: proc(ctx: ws.Hook, req: HttpTable): Future[Result[void,string]] =
|
|
||||||
req.handler)
|
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
# End
|
# End
|
||||||
|
@ -224,7 +224,7 @@ proc runJwtAuth(noisy = true; keyFile = jwtKeyFile) =
|
|||||||
secret = fakeKey.fakeGenSecret.jwtSharedSecret(config)
|
secret = fakeKey.fakeGenSecret.jwtSharedSecret(config)
|
||||||
|
|
||||||
# The wrapper contains the handler function with the captured shared key
|
# The wrapper contains the handler function with the captured shared key
|
||||||
asyHandler = secret.value.jwtAuthAsyHandler
|
handler = secret.value.jwtAuthHandler
|
||||||
|
|
||||||
suite "EngineAuth: Http/rpc authentication mechanics":
|
suite "EngineAuth: Http/rpc authentication mechanics":
|
||||||
|
|
||||||
@ -249,7 +249,7 @@ proc runJwtAuth(noisy = true; keyFile = jwtKeyFile) =
|
|||||||
setTraceLevel()
|
setTraceLevel()
|
||||||
|
|
||||||
# Run http authorisation request
|
# Run http authorisation request
|
||||||
let htCode = waitFor req.asyHandler
|
let htCode = req.handler
|
||||||
noisy.say "***", "result",
|
noisy.say "***", "result",
|
||||||
" htCode=", htCode
|
" htCode=", htCode
|
||||||
|
|
||||||
@ -268,7 +268,7 @@ proc runJwtAuth(noisy = true; keyFile = jwtKeyFile) =
|
|||||||
setTraceLevel()
|
setTraceLevel()
|
||||||
|
|
||||||
# Run http authorisation request
|
# Run http authorisation request
|
||||||
let htCode = waitFor req.asyHandler
|
let htCode = req.handler
|
||||||
noisy.say "***", "result",
|
noisy.say "***", "result",
|
||||||
" htCode=", htCode
|
" htCode=", htCode
|
||||||
|
|
||||||
@ -285,7 +285,7 @@ proc jwtAuthMain*(noisy = defined(debug)) =
|
|||||||
|
|
||||||
when isMainModule:
|
when isMainModule:
|
||||||
const
|
const
|
||||||
noisy = defined(debug) or true
|
noisy = defined(debug)
|
||||||
|
|
||||||
setErrorLevel()
|
setErrorLevel()
|
||||||
|
|
||||||
|
2
vendor/nim-json-rpc
vendored
2
vendor/nim-json-rpc
vendored
@ -1 +1 @@
|
|||||||
Subproject commit d4ae2328d4247c59cefd8d5e0fbc3f178a0eb4ef
|
Subproject commit b80313bfed0594198d77c6a22616f1f96c0d91fa
|
Loading…
x
Reference in New Issue
Block a user