Started implementing jwt validation.
h3rald h3rald@h3rald.com
Fri, 29 Dec 2023 14:33:34 +0100
10 files changed,
101 insertions(+),
28 deletions(-)
jump to
M
litestore.nimble
→
litestore.nimble
@@ -25,7 +25,7 @@ installExt = @["nim", "c", "h", "json", "ico"]
# Dependencies -requires "nim >= 2.0.0", "db_connector", "https://github.com/yglukhov/nim-jwt.git", "nimgen", "duktape" +requires "nim >= 2.0.0", "db_connector", "nimgen", "duktape" # Build
D
src/litestore.nim.cfg
@@ -1,27 +0,0 @@
-define:release -threads:on - -@if nimHasWarningObservableStores: - warning[ObservableStores]: off -@end - -# https://blog.filippo.io/easy-windows-and-linux-cross-compilers-for-macos/ - -amd64.windows.gcc.path = "/usr/local/bin" -amd64.windows.gcc.exe = "x86_64-w64-mingw32-gcc" -amd64.windows.gcc.linkerexe = "x86_64-w64-mingw32-gcc" - -amd64.linux.gcc.path = "/usr/local/bin" -amd64.linux.gcc.exe = "x86_64-linux-musl-gcc" -amd64.linux.gcc.linkerexe = "x86_64-linux-musl-gcc" - -mm:refc -opt:size - -@if windows: - dynLibOverride:sqlite3_64 -@else: - dynLibOverride:sqlite3 -@end - -threadAnalysis:off
A
src/litestore.nims
@@ -0,0 +1,23 @@
+ +switch("mm", "refc") +switch("opt", "size") +switch("define", "ssl") +switch("define", "release") +switch("threadAnalysis", "off") + +when defined(windows): + switch("dynlibOverride", "sqlite3_64") +else: + switch("dynlibOverride", "sqlite3") + +when defined(ssl): + switch("define", "useOpenSsl3") + when defined(windows): + # TODO", change once issue nim#15220 is resolved + switch("define", "noOpenSSLHacks") + switch("define", "sslVersion:(") + switch("dynlibOverride", "ssl-") + switch("dynlibOverride", "crypto-") + else: + switch("dynlibOverride", "ssl") + switch("dynlibOverride", "crypto")
A
src/litestorepkg/lib/jwt.nim
@@ -0,0 +1,77 @@
+import openssl, base64, strutils, macros + + +when defined(windows) and defined(amd64): + {.passL: "-static -L"&getProjectPath()&"/litestorepkg/vendor/openssl/windows -lssl -lcrypto -lbcrypt".} +elif defined(linux) and defined(amd64): + {.passL: "-static -L"&getProjectPath()&"/litestorepkg/vendor/openssl/linux -lssl -lcrypto".} +elif defined(macosx) and defined(amd64): + {.passL: "-Bstatic -L"&getProjectPath()&"/litestorepkg/vendor/openssl/macosx -lssl -lcrypto -Bdynamic".} + +proc X509_get_pubkey(cert: PX509): EVP_PKEY {.cdecl, importc.} +proc EVP_DigestVerifyInit(ctx: EVP_MD_CTX; pctx: ptr EVP_PKEY_CTX; typ: EVP_MD; + e: ENGINE; pkey: EVP_PKEY): cint {.cdecl, importc.} +proc EVP_DigestVerifyUpdate(ctx: EVP_MD_CTX; data: pointer; + len: cuint): cint {.cdecl, importc.} +proc EVP_DigestVerifyFinal(ctx: EVP_MD_CTX; data: pointer; + len: cuint): cint {.cdecl, importc.} + +proc base64UrlDecode(encoded: string): string = + let padding = 4 - (encoded.len mod 4) + let base64String = encoded.replace("-", "+").replace("_", "/") & repeat("=", padding) + result = base64.decode(base64String) + +proc validateJwtToken*(token: string; x5c: string): bool = + let parts = token.split(".") + let sig = parts[2].base64UrlDecode + let payload = parts[0]&"."&parts[1] + let cert = x5c.decode + let alg = EVP_sha256(); + var x509: PX509 + var pubkey: EVP_PKEY + var pkeyctx: EVP_PKEY_CTX + + ### Validate Signature (Only RS256 supported) + x509 = d2i_X509(cert) + if x509.isNil: + raise newException(ValueError, "Invalid X509 certificate") + + pubkey = X509_get_pubkey(x509) + if pubkey.isNil: + raise newException(ValueError, "An error occurred while retrieving the public key") + + let mdctx = EVP_MD_CTX_create() + if mdctx.isNil: + raise newException(ValueError, "Unable to initialize MD CTX") + + if EVP_DigestVerifyInit(mdctx, addr pkeyctx, alg, nil, pubkey) != 1: + raise newException(ValueError, "Unable to initialize digest verification") + + if EVP_DigestVerify_Update(mdctx, addr payload[0], payload.len.cuint) != 1: + raise newException(ValueError, "Unable to update digest verification") + + if EVP_DigestVerify_Final(mdctx, addr sig[0], sig.len.cuint) != 1: + raise newException(ValueError, "Verification failed") + + if not mdctx.isNil: + EVP_MD_CTX_destroy(mdctx) + if not pkeyctx.isNil: + EVP_PKEY_CTX_free(pkeyctx) + #if not pubkey.isNil: + # EVP_PKEY_free(pubkey) + if not x509.isNil: + X509_free(x509) + + ### TODO: Verify claims + return true + + + + + + + + + + +