diff --git a/r5dev/thirdparty/jwt/CMakeLists.txt b/r5dev/thirdparty/jwt/CMakeLists.txt
index a4bde888..3f257f5c 100644
--- a/r5dev/thirdparty/jwt/CMakeLists.txt
+++ b/r5dev/thirdparty/jwt/CMakeLists.txt
@@ -25,3 +25,7 @@ add_sources( SOURCE_GROUP "Include"
 
 end_sources()
 thirdparty_suppress_warnings()
+
+target_include_directories( ${PROJECT_NAME} PRIVATE
+    "${THIRDPARTY_SOURCE_DIR}/mbedtls/include/"
+)
diff --git a/r5dev/thirdparty/jwt/base64.c b/r5dev/thirdparty/jwt/base64.c
index ea27386a..2d7fe85b 100644
--- a/r5dev/thirdparty/jwt/base64.c
+++ b/r5dev/thirdparty/jwt/base64.c
@@ -133,7 +133,7 @@ int l8w8jwt_base64_encode(const int url, const uint8_t* data, const size_t data_
         return L8W8JWT_OVERFLOW;
     }
 
-    *out = malloc(olen);
+    *out = (char*)malloc(olen);
     if (*out == NULL)
     {
         return L8W8JWT_OUT_OF_MEM;
@@ -249,7 +249,7 @@ int l8w8jwt_base64_decode(const int url, const char* data, const size_t data_len
     if (r == 3)
         r = 1;
 
-    *out = calloc(count / 4 * 3 + 16, sizeof(uint8_t));
+    *out = (uint8_t*)calloc(count / 4 * 3 + 16, sizeof(uint8_t));
     if (*out == NULL)
     {
         return L8W8JWT_OUT_OF_MEM;
diff --git a/r5dev/thirdparty/jwt/claim.c b/r5dev/thirdparty/jwt/claim.c
index 089baff1..8918f0bc 100644
--- a/r5dev/thirdparty/jwt/claim.c
+++ b/r5dev/thirdparty/jwt/claim.c
@@ -24,8 +24,7 @@ extern "C" {
 #include "include/chillbuff.h"
 
 #include <string.h>
-
-#include <mbedtls/md.h> // SChannel???
+#include <mbedtls/md.h>
 
 void l8w8jwt_free_claims(struct l8w8jwt_claim* claims, const size_t claims_count)
 {
diff --git a/r5dev/thirdparty/jwt/decode.c b/r5dev/thirdparty/jwt/decode.c
index 65ecfa25..121a2cab 100644
--- a/r5dev/thirdparty/jwt/decode.c
+++ b/r5dev/thirdparty/jwt/decode.c
@@ -24,11 +24,12 @@ extern "C" {
 #include "include/decode.h"
 #include "include/base64.h"
 #include "include/chillbuff.h"
+#include "include/jsmn.h"
+#include "include/checknum.h"
 
-#include <jsmn.h> // RapidJSON?
 #include <string.h>
 #include <inttypes.h>
-#include <checknum.h>
+
 #include <mbedtls/pk.h>
 #include <mbedtls/md.h>
 #include <mbedtls/platform_util.h>
@@ -82,14 +83,14 @@ static inline void md_info_from_alg(const int alg, mbedtls_md_info_t** md_info,
 static int l8w8jwt_unescape_claim(struct l8w8jwt_claim* claim, const char* key, const size_t key_length, const char* value, const size_t value_length)
 {
     claim->key_length = 0;
-    claim->key = calloc(sizeof(char), key_length + 1);
+    claim->key = (char*)calloc(sizeof(char), key_length + 1);
 
     claim->value_length = 0;
-    claim->value = calloc(sizeof(char), value_length + 1);
+    claim->value = (char*)calloc(sizeof(char), value_length + 1);
 
     if (claim->key == NULL || claim->value == NULL)
     {
-        free(claim->key);
+        free((void*)claim->key);
         free(claim->value);
         return L8W8JWT_OUT_OF_MEM;
     }
@@ -165,7 +166,7 @@ static int l8w8jwt_parse_claims(chillbuff* buffer, char* json, const size_t json
     }
 
     jsmntok_t _tokens[64];
-    jsmntok_t* tokens = r <= (sizeof(_tokens) / sizeof(_tokens[0])) ? _tokens : malloc(r * sizeof(jsmntok_t));
+    jsmntok_t* tokens = r <= (sizeof(_tokens) / sizeof(_tokens[0])) ? _tokens : (jsmntok_t*)malloc(r * sizeof(jsmntok_t));
 
     if (tokens == NULL)
     {
@@ -315,7 +316,7 @@ int l8w8jwt_decode(struct l8w8jwt_decoding_params* params, enum l8w8jwt_validati
     }
 
     const int alg = params->alg;
-    enum l8w8jwt_validation_result validation_res = L8W8JWT_VALID;
+    unsigned validation_res = L8W8JWT_VALID;
 
     int r = l8w8jwt_validate_decoding_params(params);
     if (r != L8W8JWT_SUCCESS)
@@ -328,7 +329,7 @@ int l8w8jwt_decode(struct l8w8jwt_decoding_params* params, enum l8w8jwt_validati
         return L8W8JWT_NULL_ARG;
     }
 
-    *out_validation_result = ~L8W8JWT_VALID;
+    *out_validation_result = (enum l8w8jwt_validation_result)~L8W8JWT_VALID;
 
     char* header = NULL;
     size_t header_length = 0;
@@ -342,6 +343,9 @@ int l8w8jwt_decode(struct l8w8jwt_decoding_params* params, enum l8w8jwt_validati
     char* current = params->jwt;
     char* next = strchr(params->jwt, '.');
 
+    size_t current_length;
+    time_t ct;
+
     if (next == NULL) /* No payload. */
     {
         return L8W8JWT_DECODE_FAILED_INVALID_TOKEN_FORMAT;
@@ -385,7 +389,7 @@ int l8w8jwt_decode(struct l8w8jwt_decoding_params* params, enum l8w8jwt_validati
         goto exit;
     }
 
-    size_t current_length = next - current;
+    current_length = next - current;
 
     r = l8w8jwt_base64_decode(true, current, current_length, (uint8_t**)&header, &header_length);
     if (r != L8W8JWT_SUCCESS)
@@ -651,7 +655,7 @@ int l8w8jwt_decode(struct l8w8jwt_decoding_params* params, enum l8w8jwt_validati
 
     if (params->validate_sub != NULL)
     {
-        struct l8w8jwt_claim* c = l8w8jwt_get_claim(claims.array, claims.length, "sub", 3);
+        struct l8w8jwt_claim* c = l8w8jwt_get_claim((struct l8w8jwt_claim*)claims.array, claims.length, "sub", 3);
         if (c == NULL || strncmp(c->value, params->validate_sub, params->validate_sub_length ? params->validate_sub_length : strlen(params->validate_sub)) != 0)
         {
             validation_res |= (unsigned)L8W8JWT_SUB_FAILURE;
@@ -660,7 +664,7 @@ int l8w8jwt_decode(struct l8w8jwt_decoding_params* params, enum l8w8jwt_validati
 
     if (params->validate_aud != NULL)
     {
-        struct l8w8jwt_claim* c = l8w8jwt_get_claim(claims.array, claims.length, "aud", 3);
+        struct l8w8jwt_claim* c = l8w8jwt_get_claim((struct l8w8jwt_claim*)claims.array, claims.length, "aud", 3);
         if (c == NULL || strncmp(c->value, params->validate_aud, params->validate_aud_length ? params->validate_aud_length : strlen(params->validate_aud)) != 0)
         {
             validation_res |= (unsigned)L8W8JWT_AUD_FAILURE;
@@ -669,7 +673,7 @@ int l8w8jwt_decode(struct l8w8jwt_decoding_params* params, enum l8w8jwt_validati
 
     if (params->validate_iss != NULL)
     {
-        struct l8w8jwt_claim* c = l8w8jwt_get_claim(claims.array, claims.length, "iss", 3);
+        struct l8w8jwt_claim* c = l8w8jwt_get_claim((struct l8w8jwt_claim*)claims.array, claims.length, "iss", 3);
         if (c == NULL || strncmp(c->value, params->validate_iss, params->validate_iss_length ? params->validate_iss_length : strlen(params->validate_iss)) != 0)
         {
             validation_res |= (unsigned)L8W8JWT_ISS_FAILURE;
@@ -678,18 +682,18 @@ int l8w8jwt_decode(struct l8w8jwt_decoding_params* params, enum l8w8jwt_validati
 
     if (params->validate_jti != NULL)
     {
-        struct l8w8jwt_claim* c = l8w8jwt_get_claim(claims.array, claims.length, "jti", 3);
+        struct l8w8jwt_claim* c = l8w8jwt_get_claim((struct l8w8jwt_claim*)claims.array, claims.length, "jti", 3);
         if (c == NULL || strncmp(c->value, params->validate_jti, params->validate_jti_length ? params->validate_jti_length : strlen(params->validate_jti)) != 0)
         {
             validation_res |= (unsigned)L8W8JWT_JTI_FAILURE;
         }
     }
 
-    const time_t ct = time(NULL);
+    ct = time(NULL);
 
     if (params->validate_exp)
     {
-        struct l8w8jwt_claim* c = l8w8jwt_get_claim(claims.array, claims.length, "exp", 3);
+        struct l8w8jwt_claim* c = l8w8jwt_get_claim((struct l8w8jwt_claim*)claims.array, claims.length, "exp", 3);
         if (c == NULL || ct - params->exp_tolerance_seconds > strtoll(c->value, NULL, 10))
         {
             validation_res |= (unsigned)L8W8JWT_EXP_FAILURE;
@@ -698,7 +702,7 @@ int l8w8jwt_decode(struct l8w8jwt_decoding_params* params, enum l8w8jwt_validati
 
     if (params->validate_nbf)
     {
-        struct l8w8jwt_claim* c = l8w8jwt_get_claim(claims.array, claims.length, "nbf", 3);
+        struct l8w8jwt_claim* c = l8w8jwt_get_claim((struct l8w8jwt_claim*)claims.array, claims.length, "nbf", 3);
         if (c == NULL || ct + params->nbf_tolerance_seconds < strtoll(c->value, NULL, 10))
         {
             validation_res |= (unsigned)L8W8JWT_NBF_FAILURE;
@@ -707,7 +711,7 @@ int l8w8jwt_decode(struct l8w8jwt_decoding_params* params, enum l8w8jwt_validati
 
     if (params->validate_iat)
     {
-        struct l8w8jwt_claim* c = l8w8jwt_get_claim(claims.array, claims.length, "iat", 3);
+        struct l8w8jwt_claim* c = l8w8jwt_get_claim((struct l8w8jwt_claim*)claims.array, claims.length, "iat", 3);
         if (c == NULL || ct + params->iat_tolerance_seconds < strtoll(c->value, NULL, 10))
         {
             validation_res |= (unsigned)L8W8JWT_IAT_FAILURE;
@@ -716,7 +720,7 @@ int l8w8jwt_decode(struct l8w8jwt_decoding_params* params, enum l8w8jwt_validati
 
     if (params->validate_typ)
     {
-        struct l8w8jwt_claim* c = l8w8jwt_get_claim(claims.array, claims.length, "typ", 3);
+        struct l8w8jwt_claim* c = l8w8jwt_get_claim((struct l8w8jwt_claim*)claims.array, claims.length, "typ", 3);
         if (c == NULL || l8w8jwt_strncmpic(c->value, params->validate_typ, params->validate_typ_length) != 0)
         {
             validation_res |= (unsigned)L8W8JWT_TYP_FAILURE;
@@ -724,7 +728,7 @@ int l8w8jwt_decode(struct l8w8jwt_decoding_params* params, enum l8w8jwt_validati
     }
 
     r = L8W8JWT_SUCCESS;
-    *out_validation_result = validation_res;
+    *out_validation_result = (enum l8w8jwt_validation_result)validation_res;
 
     if (out_claims != NULL && out_claims_length != NULL)
     {
diff --git a/r5dev/thirdparty/jwt/encode.c b/r5dev/thirdparty/jwt/encode.c
index 081901e2..8abc0962 100644
--- a/r5dev/thirdparty/jwt/encode.c
+++ b/r5dev/thirdparty/jwt/encode.c
@@ -24,6 +24,7 @@ extern "C" {
 #include "include/chillbuff.h"
 
 #include <inttypes.h>
+
 #include <mbedtls/pk.h>
 #include <mbedtls/entropy.h>
 #include <mbedtls/ctr_drbg.h>
@@ -143,7 +144,7 @@ static int write_header_and_payload(chillbuff* stringbuilder, struct l8w8jwt_enc
     char* segment;
     size_t segment_length;
 
-    r = l8w8jwt_base64_encode(1, buff.array, buff.length, &segment, &segment_length);
+    r = l8w8jwt_base64_encode(1, (const uint8_t*)buff.array, buff.length, &segment, &segment_length);
     if (r != L8W8JWT_SUCCESS)
     {
         chillbuff_free(&buff);
@@ -176,13 +177,13 @@ static int write_header_and_payload(chillbuff* stringbuilder, struct l8w8jwt_enc
 
     struct l8w8jwt_claim claims[] = {
         // Setting l8w8jwt_claim::value_length to 0 makes the encoder use strlen, which in this case is fine.
-        { .key = *(iatnbfexp + 00) ? "iat" : NULL, .key_length = 3, .value = iatnbfexp + 00, .value_length = 0, .type = L8W8JWT_CLAIM_TYPE_INTEGER },
-        { .key = *(iatnbfexp + 21) ? "nbf" : NULL, .key_length = 3, .value = iatnbfexp + 21, .value_length = 0, .type = L8W8JWT_CLAIM_TYPE_INTEGER },
-        { .key = *(iatnbfexp + 42) ? "exp" : NULL, .key_length = 3, .value = iatnbfexp + 42, .value_length = 0, .type = L8W8JWT_CLAIM_TYPE_INTEGER },
-        { .key = params->sub ? "sub" : NULL, .key_length = 3, .value = params->sub, .value_length = params->sub_length, .type = L8W8JWT_CLAIM_TYPE_STRING },
-        { .key = params->iss ? "iss" : NULL, .key_length = 3, .value = params->iss, .value_length = params->iss_length, .type = L8W8JWT_CLAIM_TYPE_STRING },
-        { .key = params->aud ? "aud" : NULL, .key_length = 3, .value = params->aud, .value_length = params->aud_length, .type = L8W8JWT_CLAIM_TYPE_STRING },
-        { .key = params->jti ? "jti" : NULL, .key_length = 3, .value = params->jti, .value_length = params->jti_length, .type = L8W8JWT_CLAIM_TYPE_STRING },
+        { *(iatnbfexp + 00) ? (char*)"iat" : NULL, 3, iatnbfexp + 00, 0, L8W8JWT_CLAIM_TYPE_INTEGER },
+        { *(iatnbfexp + 21) ? (char*)"nbf" : NULL, 3, iatnbfexp + 21, 0, L8W8JWT_CLAIM_TYPE_INTEGER },
+        { *(iatnbfexp + 42) ? (char*)"exp" : NULL, 3, iatnbfexp + 42, 0, L8W8JWT_CLAIM_TYPE_INTEGER },
+        { params->sub ? (char*)"sub" : NULL, 3, params->sub, params->sub_length, L8W8JWT_CLAIM_TYPE_STRING },
+        { params->iss ? (char*)"iss" : NULL, 3, params->iss, params->iss_length, L8W8JWT_CLAIM_TYPE_STRING },
+        { params->aud ? (char*)"aud" : NULL, 3, params->aud, params->aud_length, L8W8JWT_CLAIM_TYPE_STRING },
+        { params->jti ? (char*)"jti" : NULL, 3, params->jti, params->jti_length, L8W8JWT_CLAIM_TYPE_STRING },
     };
 
     chillbuff_push_back(&buff, "{", 1);
@@ -199,7 +200,7 @@ static int write_header_and_payload(chillbuff* stringbuilder, struct l8w8jwt_enc
 
     chillbuff_push_back(&buff, "}", 1);
 
-    r = l8w8jwt_base64_encode(1, buff.array, buff.length, &segment, &segment_length);
+    r = l8w8jwt_base64_encode(1, (const uint8_t*)buff.array, buff.length, &segment, &segment_length);
     if (r != L8W8JWT_SUCCESS)
     {
         chillbuff_free(&buff);
@@ -221,6 +222,8 @@ static int write_signature(chillbuff* stringbuilder, struct l8w8jwt_encoding_par
     int r;
     const int alg = params->alg;
 
+    unsigned char hash[64] = { 0x00 };
+
     char* signature = NULL;
     size_t signature_length = 0, signature_bytes_length = 0, key_length = 0;
 
@@ -228,6 +231,12 @@ static int write_signature(chillbuff* stringbuilder, struct l8w8jwt_encoding_par
     mbedtls_entropy_context entropy;
     mbedtls_ctr_drbg_context ctr_drbg;
 
+    size_t md_length;
+    mbedtls_md_type_t md_type;
+    mbedtls_md_info_t* md_info;
+
+    size_t half_signature_bytes_length;
+
     mbedtls_pk_init(&pk);
     mbedtls_entropy_init(&entropy);
     mbedtls_ctr_drbg_init(&ctr_drbg);
@@ -263,14 +272,8 @@ static int write_signature(chillbuff* stringbuilder, struct l8w8jwt_encoding_par
         goto exit;
     }
 
-    size_t md_length;
-    mbedtls_md_type_t md_type;
-    mbedtls_md_info_t* md_info;
-
     md_info_from_alg(alg, &md_info, &md_type, &md_length);
 
-    unsigned char hash[64] = { 0x00 };
-
     switch (alg)
     {
         case L8W8JWT_ALG_HS256:
@@ -492,7 +495,7 @@ static int write_signature(chillbuff* stringbuilder, struct l8w8jwt_encoding_par
                 goto ecdsa_exit;
             }
 
-            const size_t half_signature_bytes_length = signature_bytes_length / 2;
+            half_signature_bytes_length = signature_bytes_length / 2;
 
             r = mbedtls_mpi_write_binary(&sig_r, signature_bytes, half_signature_bytes_length);
             if (r != 0)
@@ -589,7 +592,7 @@ exit:
 /* Step 3: finalize the token by writing it into the "out" string defined in the l8w8jwt_encoding_params argument. */
 static int write_token(chillbuff* stringbuilder, struct l8w8jwt_encoding_params* params)
 {
-    *(params->out) = malloc(stringbuilder->length + 1);
+    *(params->out) = (char*)malloc(stringbuilder->length + 1);
     if (*(params->out) == NULL)
     {
         return L8W8JWT_OUT_OF_MEM;
diff --git a/r5dev/thirdparty/jwt/include/base64.h b/r5dev/thirdparty/jwt/include/base64.h
index f3124fc8..2fa71771 100644
--- a/r5dev/thirdparty/jwt/include/base64.h
+++ b/r5dev/thirdparty/jwt/include/base64.h
@@ -51,7 +51,7 @@ extern "C" {
  *
  *  @return Return code as defined in retcodes.h
  */
-L8W8JWT_API int l8w8jwt_base64_encode(int url, const uint8_t* data, size_t data_length, char** out, size_t* out_length);
+L8W8JWT_API int l8w8jwt_base64_encode(const int url, const uint8_t* data, const size_t data_length, char** out, size_t* out_length);
 
 /**
  *  Decodes a base-64 encoded string to an array of bytes. <p>
@@ -68,7 +68,7 @@ L8W8JWT_API int l8w8jwt_base64_encode(int url, const uint8_t* data, size_t data_
  *
  *  @return Return code as defined in retcodes.h
  */
-L8W8JWT_API int l8w8jwt_base64_decode(int url, const char* data, size_t data_length, uint8_t** out, size_t* out_length);
+L8W8JWT_API int l8w8jwt_base64_decode(const int url, const char* data, const size_t data_length, uint8_t** out, size_t* out_length);
 
 #ifdef __cplusplus
 } // extern "C"
diff --git a/r5dev/thirdparty/jwt/include/checknum.h b/r5dev/thirdparty/jwt/include/checknum.h
new file mode 100644
index 00000000..c84a32fa
--- /dev/null
+++ b/r5dev/thirdparty/jwt/include/checknum.h
@@ -0,0 +1,141 @@
+/*
+   Copyright 2020 Raphael Beck
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
+/**
+ *  @file checknum.h
+ *  @author Raphael Beck
+ *  @brief Check whether a given string contains an integer or floating point number.
+ */
+
+/* https://github.com/GlitchedPolygons/checknum */
+
+#ifndef CHECKNUM_H
+#define CHECKNUM_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef CHECKNUM_STATIC
+    #define CHECKNUM_API static
+#else
+    #define CHECKNUM_API extern
+#endif
+
+#include <string.h>
+#include <stddef.h>
+#include <stdbool.h>
+#include <inttypes.h>
+
+/**
+ * Checks whether a given string contains a valid integer or floating point number. <p>
+ * If it's an integer, 1 is returned. <P>
+ * If it's a float or a double, 2 is returned. <p>
+ * If the string doesn't contain a valid number at all, 0 is returned.
+ */
+CHECKNUM_API int checknum(char* string, size_t string_length)
+{
+    if (string == NULL)
+        return 0;
+
+    if (string_length == 0)
+        string_length = strlen(string);
+
+    char* c = string;
+
+    while (*c == ' ' && c < string + string_length)
+        c++;
+
+    while (*(string + string_length - 1) == ' ' && c < string + string_length)
+        string_length--;
+
+    switch (*c)
+    {
+        case '+':
+        case '-':
+            if (++c >= string + string_length)
+                return 0;
+        default:
+            break;
+    }
+
+    unsigned int type = 0;
+
+    if (*c == '0')
+    {
+        type |= 1 << 0;
+        if (*++c != '.' && c < string + string_length)
+            return 0;
+    }
+
+    for (; c < string + string_length; c++)
+    {
+        switch (*c)
+        {
+            case '0':
+            case '1':
+            case '2':
+            case '3':
+            case '4':
+            case '5':
+            case '6':
+            case '7':
+            case '8':
+            case '9':
+                type |= 1 << 0;
+                continue;
+            case '-':
+                if (type & 1 << 1 || (*(c - 1) != 'E' && *(c - 1) != 'e'))
+                    return 0;
+                type |= 1 << 1;
+                continue;
+            case '.':
+                if (type & 1 << 2 || type & 1 << 3)
+                    return 0;
+                type |= 1 << 2;
+                continue;
+            case 'E':
+            case 'e':
+                if (!(type & 1 << 0) || type & 1 << 3 || c + 1 >= string + string_length)
+                    return 0;
+                type |= 1 << 3;
+                continue;
+            case '+':
+                if (type & 1 << 4 || (*(c - 1) != 'E' && *(c - 1) != 'e'))
+                    return 0;
+                type |= 1 << 4;
+                continue;
+            default:
+                return 0;
+        }
+    }
+
+    switch (type)
+    {
+        case 0:
+            return 0;
+        case 1 << 0:
+            return 1;
+        default:
+            return type & 1 << 0 ? 2 : 0;
+    }
+}
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // CHECKNUM_H
diff --git a/r5dev/thirdparty/jwt/include/claim.h b/r5dev/thirdparty/jwt/include/claim.h
index 0b55acad..b9bf18d2 100644
--- a/r5dev/thirdparty/jwt/include/claim.h
+++ b/r5dev/thirdparty/jwt/include/claim.h
@@ -117,7 +117,7 @@ struct l8w8jwt_claim
  * @param claims The claims to free.
  * @param claims_count The size of the passed claims array.
  */
-L8W8JWT_API void l8w8jwt_free_claims(struct l8w8jwt_claim* claims, size_t claims_count);
+L8W8JWT_API void l8w8jwt_free_claims(struct l8w8jwt_claim* claims, const size_t claims_count);
 
 /**
  * Writes a bunch of JWT claims into a chillbuff stringbuilder. <p>
@@ -127,7 +127,7 @@ L8W8JWT_API void l8w8jwt_free_claims(struct l8w8jwt_claim* claims, size_t claims
  * @param claims_count The claims array size.
  * @return Return code as specified inside retcodes.h
  */
-L8W8JWT_API int l8w8jwt_write_claims(struct chillbuff* stringbuilder, struct l8w8jwt_claim* claims, size_t claims_count);
+L8W8JWT_API int l8w8jwt_write_claims(struct chillbuff* stringbuilder, struct l8w8jwt_claim* claims, const size_t claims_count);
 
 /**
  * Gets a claim by key from a l8w8jwt_claim array.
@@ -137,7 +137,7 @@ L8W8JWT_API int l8w8jwt_write_claims(struct chillbuff* stringbuilder, struct l8w
  * @param key_length The claim key's string length.
  * @return The found claim; <code>NULL</code> if no such claim was found in the array.
  */
-L8W8JWT_API struct l8w8jwt_claim* l8w8jwt_get_claim(struct l8w8jwt_claim* claims, size_t claims_count, const char* key, size_t key_length);
+L8W8JWT_API struct l8w8jwt_claim* l8w8jwt_get_claim(struct l8w8jwt_claim* claims, const size_t claims_count, const char* key, const size_t key_length);
 
 #ifdef __cplusplus
 } // extern "C"
diff --git a/r5dev/thirdparty/jwt/include/decode.h b/r5dev/thirdparty/jwt/include/decode.h
index a8a31cb4..dd9ac563 100644
--- a/r5dev/thirdparty/jwt/include/decode.h
+++ b/r5dev/thirdparty/jwt/include/decode.h
@@ -34,6 +34,7 @@ extern "C" {
 #include <time.h>
 #include <stddef.h>
 #include <stdint.h>
+#include <stdio.h>
 
 #ifndef L8W8JWT_MAX_KEY_SIZE
 #define L8W8JWT_MAX_KEY_SIZE 8192
@@ -94,6 +95,31 @@ enum l8w8jwt_validation_result {
     L8W8JWT_TYP_FAILURE = (unsigned)1 << (unsigned)8
 };
 
+static void l8w8jwt_get_validation_result_desc(enum l8w8jwt_validation_result res, char* out_buffer, size_t buffer_size)
+{
+#define JWT_OUTPUT_MSG(msg) snprintf(out_buffer, buffer_size, "%s", msg)
+#define JWT_FLAG_STATUS(flag, msg) if(res & flag) { JWT_OUTPUT_MSG(msg); return; }
+
+    if (res == L8W8JWT_VALID)
+    {
+        JWT_OUTPUT_MSG("Success");
+        return;
+    }
+
+    JWT_FLAG_STATUS(L8W8JWT_ISS_FAILURE, "Issuer claim is invalid");
+    JWT_FLAG_STATUS(L8W8JWT_SUB_FAILURE, "Subject claim is invalid");
+    JWT_FLAG_STATUS(L8W8JWT_AUD_FAILURE, "Audience claim is invalid");
+    JWT_FLAG_STATUS(L8W8JWT_JTI_FAILURE, "JWT ID claim is invalid");
+    JWT_FLAG_STATUS(L8W8JWT_EXP_FAILURE, "Token has expired");
+    JWT_FLAG_STATUS(L8W8JWT_NBF_FAILURE, "Token is not yet valid");
+    JWT_FLAG_STATUS(L8W8JWT_IAT_FAILURE, "Token has not been issued yet");
+    JWT_FLAG_STATUS(L8W8JWT_SIGNATURE_VERIFICATION_FAILURE, "Token signature is invalid");
+    JWT_FLAG_STATUS(L8W8JWT_TYP_FAILURE, "Token type is invalid");
+
+#undef JWT_OUTPUT_MSG
+#undef JWT_FLAG_STATUS
+}
+
 /**
  * Struct containing the parameters to use for decoding and validating a JWT.
  */
diff --git a/r5dev/thirdparty/jwt/include/jsmn.h b/r5dev/thirdparty/jwt/include/jsmn.h
new file mode 100644
index 00000000..8ac14c1b
--- /dev/null
+++ b/r5dev/thirdparty/jwt/include/jsmn.h
@@ -0,0 +1,471 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) 2010 Serge Zaitsev
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#ifndef JSMN_H
+#define JSMN_H
+
+#include <stddef.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef JSMN_STATIC
+#define JSMN_API static
+#else
+#define JSMN_API extern
+#endif
+
+/**
+ * JSON type identifier. Basic types are:
+ * 	o Object
+ * 	o Array
+ * 	o String
+ * 	o Other primitive: number, boolean (true/false) or null
+ */
+typedef enum {
+  JSMN_UNDEFINED = 0,
+  JSMN_OBJECT = 1 << 0,
+  JSMN_ARRAY = 1 << 1,
+  JSMN_STRING = 1 << 2,
+  JSMN_PRIMITIVE = 1 << 3
+} jsmntype_t;
+
+enum jsmnerr {
+  /* Not enough tokens were provided */
+  JSMN_ERROR_NOMEM = -1,
+  /* Invalid character inside JSON string */
+  JSMN_ERROR_INVAL = -2,
+  /* The string is not a full JSON packet, more bytes expected */
+  JSMN_ERROR_PART = -3
+};
+
+/**
+ * JSON token description.
+ * type		type (object, array, string etc.)
+ * start	start position in JSON data string
+ * end		end position in JSON data string
+ */
+typedef struct jsmntok {
+  jsmntype_t type;
+  int start;
+  int end;
+  int size;
+#ifdef JSMN_PARENT_LINKS
+  int parent;
+#endif
+} jsmntok_t;
+
+/**
+ * JSON parser. Contains an array of token blocks available. Also stores
+ * the string being parsed now and current position in that string.
+ */
+typedef struct jsmn_parser {
+  unsigned int pos;     /* offset in the JSON string */
+  unsigned int toknext; /* next token to allocate */
+  int toksuper;         /* superior token node, e.g. parent object or array */
+} jsmn_parser;
+
+/**
+ * Create JSON parser over an array of tokens
+ */
+JSMN_API void jsmn_init(jsmn_parser *parser);
+
+/**
+ * Run JSON parser. It parses a JSON data string into and array of tokens, each
+ * describing
+ * a single JSON object.
+ */
+JSMN_API int jsmn_parse(jsmn_parser *parser, const char *js, const size_t len,
+                        jsmntok_t *tokens, const unsigned int num_tokens);
+
+#ifndef JSMN_HEADER
+/**
+ * Allocates a fresh unused token from the token pool.
+ */
+static jsmntok_t *jsmn_alloc_token(jsmn_parser *parser, jsmntok_t *tokens,
+                                   const size_t num_tokens) {
+  jsmntok_t *tok;
+  if (parser->toknext >= num_tokens) {
+    return NULL;
+  }
+  tok = &tokens[parser->toknext++];
+  tok->start = tok->end = -1;
+  tok->size = 0;
+#ifdef JSMN_PARENT_LINKS
+  tok->parent = -1;
+#endif
+  return tok;
+}
+
+/**
+ * Fills token type and boundaries.
+ */
+static void jsmn_fill_token(jsmntok_t *token, const jsmntype_t type,
+                            const int start, const int end) {
+  token->type = type;
+  token->start = start;
+  token->end = end;
+  token->size = 0;
+}
+
+/**
+ * Fills next available token with JSON primitive.
+ */
+static int jsmn_parse_primitive(jsmn_parser *parser, const char *js,
+                                const size_t len, jsmntok_t *tokens,
+                                const size_t num_tokens) {
+  jsmntok_t *token;
+  int start;
+
+  start = parser->pos;
+
+  for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) {
+    switch (js[parser->pos]) {
+#ifndef JSMN_STRICT
+    /* In strict mode primitive must be followed by "," or "}" or "]" */
+    case ':':
+#endif
+    case '\t':
+    case '\r':
+    case '\n':
+    case ' ':
+    case ',':
+    case ']':
+    case '}':
+      goto found;
+    default:
+                   /* to quiet a warning from gcc*/
+      break;
+    }
+    if (js[parser->pos] < 32 || js[parser->pos] >= 127) {
+      parser->pos = start;
+      return JSMN_ERROR_INVAL;
+    }
+  }
+#ifdef JSMN_STRICT
+  /* In strict mode primitive must be followed by a comma/object/array */
+  parser->pos = start;
+  return JSMN_ERROR_PART;
+#endif
+
+found:
+  if (tokens == NULL) {
+    parser->pos--;
+    return 0;
+  }
+  token = jsmn_alloc_token(parser, tokens, num_tokens);
+  if (token == NULL) {
+    parser->pos = start;
+    return JSMN_ERROR_NOMEM;
+  }
+  jsmn_fill_token(token, JSMN_PRIMITIVE, start, parser->pos);
+#ifdef JSMN_PARENT_LINKS
+  token->parent = parser->toksuper;
+#endif
+  parser->pos--;
+  return 0;
+}
+
+/**
+ * Fills next token with JSON string.
+ */
+static int jsmn_parse_string(jsmn_parser *parser, const char *js,
+                             const size_t len, jsmntok_t *tokens,
+                             const size_t num_tokens) {
+  jsmntok_t *token;
+
+  int start = parser->pos;
+  
+  /* Skip starting quote */
+  parser->pos++;
+  
+  for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) {
+    char c = js[parser->pos];
+
+    /* Quote: end of string */
+    if (c == '\"') {
+      if (tokens == NULL) {
+        return 0;
+      }
+      token = jsmn_alloc_token(parser, tokens, num_tokens);
+      if (token == NULL) {
+        parser->pos = start;
+        return JSMN_ERROR_NOMEM;
+      }
+      jsmn_fill_token(token, JSMN_STRING, start + 1, parser->pos);
+#ifdef JSMN_PARENT_LINKS
+      token->parent = parser->toksuper;
+#endif
+      return 0;
+    }
+
+    /* Backslash: Quoted symbol expected */
+    if (c == '\\' && parser->pos + 1 < len) {
+      int i;
+      parser->pos++;
+      switch (js[parser->pos]) {
+      /* Allowed escaped symbols */
+      case '\"':
+      case '/':
+      case '\\':
+      case 'b':
+      case 'f':
+      case 'r':
+      case 'n':
+      case 't':
+        break;
+      /* Allows escaped symbol \uXXXX */
+      case 'u':
+        parser->pos++;
+        for (i = 0; i < 4 && parser->pos < len && js[parser->pos] != '\0';
+             i++) {
+          /* If it isn't a hex character we have an error */
+          if (!((js[parser->pos] >= 48 && js[parser->pos] <= 57) ||   /* 0-9 */
+                (js[parser->pos] >= 65 && js[parser->pos] <= 70) ||   /* A-F */
+                (js[parser->pos] >= 97 && js[parser->pos] <= 102))) { /* a-f */
+            parser->pos = start;
+            return JSMN_ERROR_INVAL;
+          }
+          parser->pos++;
+        }
+        parser->pos--;
+        break;
+      /* Unexpected symbol */
+      default:
+        parser->pos = start;
+        return JSMN_ERROR_INVAL;
+      }
+    }
+  }
+  parser->pos = start;
+  return JSMN_ERROR_PART;
+}
+
+/**
+ * Parse JSON string and fill tokens.
+ */
+JSMN_API int jsmn_parse(jsmn_parser *parser, const char *js, const size_t len,
+                        jsmntok_t *tokens, const unsigned int num_tokens) {
+  int r;
+  int i;
+  jsmntok_t *token;
+  int count = parser->toknext;
+
+  for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) {
+    char c;
+    jsmntype_t type;
+
+    c = js[parser->pos];
+    switch (c) {
+    case '{':
+    case '[':
+      count++;
+      if (tokens == NULL) {
+        break;
+      }
+      token = jsmn_alloc_token(parser, tokens, num_tokens);
+      if (token == NULL) {
+        return JSMN_ERROR_NOMEM;
+      }
+      if (parser->toksuper != -1) {
+        jsmntok_t *t = &tokens[parser->toksuper];
+#ifdef JSMN_STRICT
+        /* In strict mode an object or array can't become a key */
+        if (t->type == JSMN_OBJECT) {
+          return JSMN_ERROR_INVAL;
+        }
+#endif
+        t->size++;
+#ifdef JSMN_PARENT_LINKS
+        token->parent = parser->toksuper;
+#endif
+      }
+      token->type = (c == '{' ? JSMN_OBJECT : JSMN_ARRAY);
+      token->start = parser->pos;
+      parser->toksuper = parser->toknext - 1;
+      break;
+    case '}':
+    case ']':
+      if (tokens == NULL) {
+        break;
+      }
+      type = (c == '}' ? JSMN_OBJECT : JSMN_ARRAY);
+#ifdef JSMN_PARENT_LINKS
+      if (parser->toknext < 1) {
+        return JSMN_ERROR_INVAL;
+      }
+      token = &tokens[parser->toknext - 1];
+      for (;;) {
+        if (token->start != -1 && token->end == -1) {
+          if (token->type != type) {
+            return JSMN_ERROR_INVAL;
+          }
+          token->end = parser->pos + 1;
+          parser->toksuper = token->parent;
+          break;
+        }
+        if (token->parent == -1) {
+          if (token->type != type || parser->toksuper == -1) {
+            return JSMN_ERROR_INVAL;
+          }
+          break;
+        }
+        token = &tokens[token->parent];
+      }
+#else
+      for (i = parser->toknext - 1; i >= 0; i--) {
+        token = &tokens[i];
+        if (token->start != -1 && token->end == -1) {
+          if (token->type != type) {
+            return JSMN_ERROR_INVAL;
+          }
+          parser->toksuper = -1;
+          token->end = parser->pos + 1;
+          break;
+        }
+      }
+      /* Error if unmatched closing bracket */
+      if (i == -1) {
+        return JSMN_ERROR_INVAL;
+      }
+      for (; i >= 0; i--) {
+        token = &tokens[i];
+        if (token->start != -1 && token->end == -1) {
+          parser->toksuper = i;
+          break;
+        }
+      }
+#endif
+      break;
+    case '\"':
+      r = jsmn_parse_string(parser, js, len, tokens, num_tokens);
+      if (r < 0) {
+        return r;
+      }
+      count++;
+      if (parser->toksuper != -1 && tokens != NULL) {
+        tokens[parser->toksuper].size++;
+      }
+      break;
+    case '\t':
+    case '\r':
+    case '\n':
+    case ' ':
+      break;
+    case ':':
+      parser->toksuper = parser->toknext - 1;
+      break;
+    case ',':
+      if (tokens != NULL && parser->toksuper != -1 &&
+          tokens[parser->toksuper].type != JSMN_ARRAY &&
+          tokens[parser->toksuper].type != JSMN_OBJECT) {
+#ifdef JSMN_PARENT_LINKS
+        parser->toksuper = tokens[parser->toksuper].parent;
+#else
+        for (i = parser->toknext - 1; i >= 0; i--) {
+          if (tokens[i].type == JSMN_ARRAY || tokens[i].type == JSMN_OBJECT) {
+            if (tokens[i].start != -1 && tokens[i].end == -1) {
+              parser->toksuper = i;
+              break;
+            }
+          }
+        }
+#endif
+      }
+      break;
+#ifdef JSMN_STRICT
+    /* In strict mode primitives are: numbers and booleans */
+    case '-':
+    case '0':
+    case '1':
+    case '2':
+    case '3':
+    case '4':
+    case '5':
+    case '6':
+    case '7':
+    case '8':
+    case '9':
+    case 't':
+    case 'f':
+    case 'n':
+      /* And they must not be keys of the object */
+      if (tokens != NULL && parser->toksuper != -1) {
+        const jsmntok_t *t = &tokens[parser->toksuper];
+        if (t->type == JSMN_OBJECT ||
+            (t->type == JSMN_STRING && t->size != 0)) {
+          return JSMN_ERROR_INVAL;
+        }
+      }
+#else
+    /* In non-strict mode every unquoted value is a primitive */
+    default:
+#endif
+      r = jsmn_parse_primitive(parser, js, len, tokens, num_tokens);
+      if (r < 0) {
+        return r;
+      }
+      count++;
+      if (parser->toksuper != -1 && tokens != NULL) {
+        tokens[parser->toksuper].size++;
+      }
+      break;
+
+#ifdef JSMN_STRICT
+    /* Unexpected char in strict mode */
+    default:
+      return JSMN_ERROR_INVAL;
+#endif
+    }
+  }
+
+  if (tokens != NULL) {
+    for (i = parser->toknext - 1; i >= 0; i--) {
+      /* Unmatched opened object or array */
+      if (tokens[i].start != -1 && tokens[i].end == -1) {
+        return JSMN_ERROR_PART;
+      }
+    }
+  }
+
+  return count;
+}
+
+/**
+ * Creates a new parser based over a given buffer with an array of tokens
+ * available.
+ */
+JSMN_API void jsmn_init(jsmn_parser *parser) {
+  parser->pos = 0;
+  parser->toknext = 0;
+  parser->toksuper = -1;
+}
+
+#endif /* JSMN_HEADER */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* JSMN_H */
diff --git a/r5dev/thirdparty/jwt/include/util.h b/r5dev/thirdparty/jwt/include/util.h
index 7bd4d479..ef986795 100644
--- a/r5dev/thirdparty/jwt/include/util.h
+++ b/r5dev/thirdparty/jwt/include/util.h
@@ -40,7 +40,7 @@ extern "C" {
  * @param output_length [OPTIONAL] Where to write the output array length into. This is always gonna be <c>hexstr_length / 2</c>, but you can still choose to write it out just to be sure. If you want to omit this: no problem.. just pass <c>NULL</c>!
  * @return <c>0</c> if conversion succeeded. <c>1</c> if one or more required arguments were <c>NULL</c> or invalid. <c>2</c> if the hexadecimal string is in an invalid format (e.g. not divisible by 2). <c>3</c> if output buffer size was insufficient (needs to be at least <c>(hexstr_length / 2) + 1</c> bytes).
  */
-L8W8JWT_API int l8w8jwt_hexstr2bin(const char* hexstr, size_t hexstr_length, unsigned char* output, size_t output_size, size_t* output_length);
+L8W8JWT_API int l8w8jwt_hexstr2bin(const char* hexstr, const size_t hexstr_length, unsigned char* output, const size_t output_size, size_t* output_length);
 
 /**
  * Compares two strings ignoring UPPER vs. lowercase.
diff --git a/r5dev/thirdparty/jwt/version.c b/r5dev/thirdparty/jwt/version.c
index 2484b772..62604c3a 100644
--- a/r5dev/thirdparty/jwt/version.c
+++ b/r5dev/thirdparty/jwt/version.c
@@ -18,6 +18,10 @@
 #include <stdlib.h>
 #include <string.h>
 
+#if defined(_WIN32)
+#include <windows.h>
+#endif
+
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -29,8 +33,6 @@ void l8w8jwt_free(void* mem)
 
 void l8w8jwt_zero(void* buf, size_t len)
 {
-    MBEDTLS_INTERNAL_VALIDATE(len == 0 || buf != NULL);
-
     if (len > 0)
     {
 #if defined(MBEDTLS_PLATFORM_HAS_EXPLICIT_BZERO)