benmcollins / libjwt Goto Github PK
View Code? Open in Web Editor NEWJWT C Library
License: Mozilla Public License 2.0
JWT C Library
License: Mozilla Public License 2.0
Please document which version of OpenSSL our using.
I've spend lots of time find out which version to use.
OpenSSL-0.9.7m doesn't compile (but should not be used)
OpenSSL-1.1.0d doesn't compile (EVP_PKEY doesn't contain 'type' member)
Find out OpenSSL-1.0.2k that compile OK.
I do not understand why jwt_set_alg() has 'unsigned char *key' parameter. Is not correct for key to have type with const qualifier 'const unsigned char *key'?
I'm trying to use libjwt to connect to google Core iot.
jwt_encode_str fails in my program. I've created the jwt object, added iat, expiry, project id and set the algorithm and key. What could be causing the encode to fail? Any ideas? Most of the code is copied from mqtt_ciotc.c, so it should work.
jwt_encode_bio doesn't encode the right signature when the algorithm is JWT_ALG_NONE.
The signature should be empty, in this case, but what's actually encoded is the leftover contents
of buf.
You can see this by doing printfs.
The automake build produces static and dynamic library. CMake instructions only produce one or other.
CMake install does not include header installation.
And it might be nice export a LibJwtConfig.cmake to make it easier to integrate into other CMake projects.
In statement:
str = malloc(len);
memory is not allocated for NULL char.
Recent security review by auth0 uncovered an issue with various JWT implementations:
https://auth0.com/blog/critical-vulnerabilities-in-json-web-token-libraries/
It seems like libjwt is affected as well.
https://github.com/benmcollins/libjwt/blob/master/libjwt/jwt.c#L781
When trying to install libjwt
via your ppa
I see this issue:
Err:8 http://ppa.launchpad.net/ben-collins/libjwt/ubuntu bionic Release
404 Not Found [IP: 91.189.95.83 80]
Presumably there is no version available for the current Ubuntu 18.04 LTS (bionic).
It would be great if that would become available.
autoreconf -i
Can't exec "aclocal": No such file or directory at /usr/share/autoconf/Autom4te/FileUtils.pm line 326.
autoreconf: failed to run aclocal: No such file or directory
when i execute “autoreconf -i” , I make a mistake:
configure:12172: error: possibly undefined macro: AM_DEFAULT_VERBOSITY
If this token and others are legitimate, please use m4_pattern_allow.
See the Autoconf documentation.
my operation is Ubuntu 12.04.5 LTS;
autoconf version is 2.68;
Look forward to your answer,thanks
if using jwt_decode(). the jwt->grants that is allocated in jwt_new is never freed in the case of jwt_decode calling it, because jwt_decode resets the pointer to newly allocated memory.
in jwt.c around line 156:
(*jwt)->grants = json_object();
in jwt_parse_body() around line 337which is called from jwt_decode:
jwt->grants = jwt_b64_decode(body);
So the original that is allocated in jwt_new is lost.
Hi,
Does ES384 verification already implemented?
I've read the code, and think that it should be implemented.
I asked this because:
more details about the issue:
Lines 565 to 566 in bb036db
Let me know if you need more info about the issue
Hi,
This is not a bug.
Need :
In a nginx module i need to copy all grants in a context.
Pb:
I haven't the defined list of grant key in this module.
Solution:
Add iterator on grants to copy all grants without specified list of key.
Code:
void *jwt_get_grant_iterator(jwt_t *jwt, void *iter)
{
if (!jwt) {
errno = EINVAL;
return NULL;
}
errno = 0;
if (iter == NULL) {
return json_object_iter(jwt->grants);
}
return json_object_iter_next(jwt->grants, iter);
}
const char *jwt_iterator_key(void *iter)
{
return json_object_iter_key(iter);
}
const char *jwt_iterator_value(void *iter)
{
json_t json = json_object_iter_value(iter);
if (json == NULL) {
return NULL;
}
return (const char)json_string_value(json);
}
Best regards.
Sebastien
Since I am new to JWT, I was trying to find an introduction to what this repository is all about and how to use it. But all I find is doxygen generated docs, which I think are inadequate.
Specifically, I am generating JWT tokens on the server-side in PHP. My client application is in C and it needs to use the token when accessing the server API. I was looking for a client-side C implementation for JWT. Can it be done with this repo? Thanks.
This may not really be an "Issue." I did not find any other place to start a forum-like discussion thread. Feel free to close it.
hi friend,
I am using the latest jwt version. i aasign the RSA contents to jwt->key. but it cored.
is the jwt library related rely on other libraries?
Note: I use the libcrypto.so with version 0.9.8
+++
Program received signal SIGSEGV, Segmentation fault.
0x00007f52241eab85 in do_sigver_init () from /usr/lib64/libcrypto.so.10
(gdb) bt
#0 0x00007f52241eab85 in do_sigver_init () from /usr/lib64/libcrypto.so.10
#1 0x00007f52255975f0 in jwt_sign_sha_pem (jwt=jwt@entry=0x7f51c4001f80, out=out@entry=0x7f51d74ad9d8, len=len@entry=0x7f51d74ad9cc,
str=0x7f51c4001570 "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJhdWQiOiJodHRwczovL2FjY291bnRzLmdvb2dsZS5jb20vby9vYXV0aDIvdG9rZW4iLCJleHAiOjE1NDQ3Njk4MzUsImlhdCI6MTU0NDc2NjIzNSwiaXNzIjoic21hcnRob21lYWN0aW9uQGhpc2Vuc2Utc21hcnQ"...) at jwt-openssl.c:222
#2 0x00007f5225596c79 in jwt_sign (str=, len=0x7f51d74ad9cc, out=0x7f51d74ad9d8, jwt=0x7f51c4001f80) at jwt.c:361
#3 jwt_encode (jwt=jwt@entry=0x7f51c4001f80, out=out@entry=0x7f51d74ada28) at jwt.c:1020
#4 0x00007f5225596eb7 in jwt_encode_str (jwt=0x7f51c4001f80) at jwt.c:1065
on line 308: buf = alloca(len); should probably be buf = alloca(len + 1); since later on buf[len] = '\0';
To complete the jwa support, libjwt should also support RSA-PSS signatures.
I have to admit, even if it seems easy to add, the RSA-PSS algorithm support is quite new in OpenSSL and GnuTLS librairies.
Do you think it's a good idea at the time?
Hi there!
I am building with Debian stretch and the configuration failed because the distro ships with cmake 3.7.
I managed to build with this change so I think you are asking for a version that is too recent.
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required (VERSION 3.9)
+cmake_minimum_required (VERSION 3.0)
Cheers!
PS: Let me know if you want me to send the trivial patch that fixes the issue.
Will you support RS256 a algorithm?
I would like to see support for validating a JWT against a JSON Web Key Set (JWKS).
Hello,
This is more of question than an issue. How did you generate the RSA private and public keys ?
I am doing this:
ssh-keygen -t rsa -b 4096 -f jwtRS256.key
/usr/local/Cellar/openssl/1.0.2j/bin/openssl pkcs8 -topk8 -outform PEM -in jwtRS256.key -out jwtRS256.key.pem --nocrypt
I get below error (with and without step#2):
PEM_read_bio_PrivateKey failed: error:0906D06C:lib(9):func(109):reason(108)
Thanks
I use working token from your test:
Line 135 in 2e7ea46
jwt_t *jwt = NULL;
jwt_decode(&jwt, "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYXQiOjE0NzU5ODA1NDUsImlzcyI6ImZpbGVzLmN5cGhyZS5jb20iLCJyZWYiOiJYWFhYLVlZWVktWlpaWi1BQUFBLUNDQ0MiLCJzdWIiOiJ1c2VyMCJ9.B0a9gqWgPuuIx-EFXXSHQByCMHCzs0gjvY3-60oV4TY", (unsigned char *)"012345678901234567890123456789XY", strlen("012345678901234567890123456789XY"));
const char *str = jwt_get_grant(jwt, "iss");
jwt_free(jwt);
printf("%s", str);
returns:
���dV
to output.
Which encoding is it and how to convert this value to human readable encoding?
-- The C compiler identification is GNU 4.8.1
-- The CXX compiler identification is GNU 4.8.1
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Found OpenSSL: /usr/lib/i386-linux-gnu/libcrypto.so (found version "1.0.1")
-- Found PkgConfig: /usr/bin/pkg-config (found version "0.26")
-- Could NOT find LibJansson (missing: JANSSON_LIBRARY JANSSON_INCLUDE_DIR)
CMake Error: The following variables are used in this project, but they are set to NOTFOUND.
Please set them or make sure they are set and tested correctly in the CMake files:
/home/zhang/work/jwt_test/libjwt-1.10.2/libjwt/JANSSON_INCLUDE_DIR
used as include directory in directory /home/zhang/work/jwt_test/libjwt-1.10.2/libjwt
JANSSON_LIBRARY (ADVANCED)
linked by target "jwt" in directory /home/zhang/work/jwt_test/libjwt-1.10.2/libjwt
-- Configuring incomplete, errors occurred!
See also "/home/zhang/work/jwt_test/libjwt-1.10.2/cmake/CMakeFiles/CMakeOutput.log".
I've recently realized that the test jwt_ec
fails when gnutls backend is enabled (configure --without-openssl
).
The test output is the following:
Running suite(s): LibJWT EC Sign/Verify
14%: Checks: 7, Failures: 6, Errors: 0
jwt_ec.c:89:F:jwt_ec:test_jwt_encode_es256:0: Assertion 'ret == 0' failed: ret == 22, 0 == 0
jwt_ec.c:89:F:jwt_ec:test_jwt_verify_es256:0: Assertion 'ret == 0' failed: ret == 22, 0 == 0
jwt_ec.c:89:F:jwt_ec:test_jwt_encode_es384:0: Assertion 'ret == 0' failed: ret == 22, 0 == 0
jwt_ec.c:89:F:jwt_ec:test_jwt_verify_es384:0: Assertion 'ret == 0' failed: ret == 22, 0 == 0
jwt_ec.c:89:F:jwt_ec:test_jwt_encode_es512:0: Assertion 'ret == 0' failed: ret == 22, 0 == 0
jwt_ec.c:89:F:jwt_ec:test_jwt_verify_es512:0: Assertion 'ret == 0' failed: ret == 22, 0 == 0
jwt_ec.c:194:P:jwt_ec:test_jwt_encode_ec_with_rsa:0: Passed
I was able to narrow it down to the gnutls_pubkey_verify_data2 command which fails with the return value -419 (GNUTLS_E_INCOMPATIBLE_SIG_WITH_KEY
).
Hi,
We want to decode a token which is generated by JAVA Keytool. They can be verified in jwt.io with RS256.
When we decode, it always shows error code 22 "Invalid argument".
ret = jwt_decode(&jwt, token, key, strlen(key));
Finally, we found use JWT_ALG_NONE it can work.
ret = jwt_decode(&jwt, token, key, JWT_ALG_NONE);
Could you take a look if this is valid?
Thanks
Token:
eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJzY29wZSI6IlJPTEVfUFNBLFJPTEVfR0lQUyIsImlzcyI6IlBTQSIsInN1YiI6IndzYWRtaW4iLCJpYXQiOjE1NjM3OTIwNzIsImF1ZCI6IlZNVF9SUExGIiwibmJmIjoxNTYzNzkyMDcyLCJqdGkiOiI1MjNkNzRiYy0wZTBhLTQzNDktYTE0MS1mZTA0MGE3ZWJiYTgiLCJleHAiOjE1NjM3OTU2NzJ9.LE4NqLLahUZsJNnBoXmd6Qj-5egkJvSvka-qwGwEX6QIvA5aAWeDbkw5AcA_ZAbfCmNRLEo-5kTQ9MxcemiSTHhJlnMe0omtarLU2QyvCjEvVFL719PLRA5brhz4OehPsMqD3t9iHhstc-5UN8biRVmZu5jB2q-yFOvP5vbsIp1nhHAw6eCQyyeDbB65TSxBiRT6DYI2yDaBlQotrbtOZiU2z05PI19jwLJd_J8B0ZUXSeFZUfAHst0sA9T4NJQSi_ZFTHd6uLjD8f1feES1AlotR6v_qnArNkzh6AmUWejnE02_1HHzujEMDrhjPP2uZSJeeQvISsTWIrnhlbB39A
Public Key:
-----BEGIN CERTIFICATE-----
MIIDQzCCAiugAwIBAgIECISEujANBgkqhkiG9w0BAQsFADBRMQswCQYDVQQGEwJj
bjELMAkGA1UECBMCbG4xCzAJBgNVBAcTAmRsMQwwCgYDVQQKEwNvcmcxDDAKBgNV
BAsTA29yZzEMMAoGA1UEAxMDcmF5MCAXDTE5MDcyMjA5MzEwN1oYDzIxMTgwMjEz
MDkzMTA3WjBRMQswCQYDVQQGEwJjbjELMAkGA1UECBMCbG4xCzAJBgNVBAcTAmRs
MQwwCgYDVQQKEwNvcmcxDDAKBgNVBAsTA29yZzEMMAoGA1UEAxMDcmF5MIIBIjAN
BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAknPGNQ2+zKdm/rCQQ8GW264I7397
4dxZfu0B8rhqXdchPHHKVAxr4b+aphphB6Ht0mNEGAuaW/21hXB9lIObpcR9wMvT
V6Bfuvf33Slqk6y2/hczblbEZ9q1O2xtfwoKJbGoL5cvQVtmJvvW2WeprQQrsSAm
fCa/sGCSlGd98U05inVaaPpIfRegyeiA4mbdCPcKRZiRaHMKUACjgobOlOItgTOG
u2xUJtNnKbZpy1qwkCtcTHDKUmX0R5g7RHxyZ6aHxS979570fc0A0d3AXlr9hrJO
4vo7kchvLk+4yVQN4JdUMXvtHlKhgQw1achU6q8jaatIXLTvSNkZIjTjKQIDAQAB
oyEwHzAdBgNVHQ4EFgQUkBuCE4QaD4T6gkgR4vRwvvWENz4wDQYJKoZIhvcNAQEL
BQADggEBAI1J8IIL1hZ2E2rGSSEDVVIOmdd3TXtX6c/EcpCRWuEPW1cq0G3T5Zuh
GU/nGfRCJzgQHKO9vJcgwp0m096eIyeM/DtUU0eZR2TcRUxDd34tnb5FZZSdHjeE
qV9h1bOALjnYqoM1KHcM/Ov7Zjqvb0eq9W9nwTUlRZo4uDEwE5Iz7uhkb4fSfpoV
ZtJMdFxYj4nUZUrv2Icn0Ie5AhpLcigI3IZjT+LmDjd5jCr9oJQxpKWQmSmuwNIX
I+MQ99xEK9NZNe/avNLBvMFGVAkVws9ybFoHnebS3upyO3f1PHwJBCLVjwJxsAMt
vDFkT/hZJHEJmiR5TycctEgFIqAaBKc=
-----END CERTIFICATE-----
I was trying to use libjwt to generate Apple Music Developer Token, however it seems no place to found where to set kid header parameter?
Hi there,
please take a look at this post: https://auth0.com/blog/critical-vulnerabilities-in-json-web-token-libraries/
I suspect that the jwt_decode function is using the alg from JWT head and does not validate "alg" value against algorithm of the KEY. So as described in the blog-post if the SERVER is using RS256 then the attacker can forge valid Tokens with HS256 using publicly available RS256 public key.
Have a good day,
Gheorghe
Would it be possible to add these 2 functions to public header ?
It would be useful to check the algorithm in the token to prevent the security issue mentioned in #33. I use this library in a program where the expected algorithm is loaded from a configuration file so I need to compare a string instead of a jwt_alg_t
Hello,
Your library has a major security issue in the token validation step (in jwt_decode).
If the provided alg is none, it bypasses the whole signature check, even though a key is provided in arguments.
It allows an attacker to forge a valid token with any signature (even empty), as long as the alg is set to none.
This security issue is thoroughly explained here: https://auth0.com/blog/2015/03/31/critical-vulnerabilities-in-json-web-token-libraries/
It suggests not to let the responsibility to the library to choose the algorithm based on alg header. It suggests to completely ignore this field. In your library, it means adding a parameter in the decoding process which is the algorithm, or at least testing that the provided key is null when bypassing the signature check.
I will be able to make a pull request if you agree with this.
Regards,
Anthony
Hello,
When i declare my token as jwt_t I get the error as in the title of this thread.
#include <jwt.h>
jwt_t token;
I link shared library in CFLAGS: -ljwt
I never get this error before and is not well documented in google.
Someone already facing this issue ?
Thank you in advance.
Trying to execute this code:
jwt_t *jwt = NULL;
jwt_decode(&jwt, token, (const unsigned char *)SESSION_KEY_APP_SECRET, 0);
const char *account = jwt_get_grant(jwt, "jti");
jwt_free(jwt);
printf(SESSION_KEY_APP_SECRET);
printf(token);
printf(account);
Key:
red cat wears hat
Token:
eyJhbGciOiJIUzI1NiJ9.NWQxOTUxYzI0NzI2OTAzNDIyMjRiOTlm.OWEWwvFwAHUMvSCs5Nx-S1cpgx14unCkkMUjjgYOX9E
Output:
`
red cat wears hat
eyJhbGciOiJIUzI1NiJ9.NWQxOTUxYzI0NzI2OTAzNDIyMjRiOTlm.OWEWwvFwAHUMvSCs5Nx-S1cpgx14unCkkMUjjgYOX9E
`
Expected: UUID stored inside jti "5a8b392c-f3b6-42ac-bc42-07d4ff11eb2e"
Please help to get what's the problem there. Thank you!
I am working on a project using LibJWT that has to be portable to Windows and Linux. For Windows, we are not allowed to store our keys outside of the Windows certificate store. So, I ported the code, and created a jwt-wincrypt.c implementation that uses Windows CNG APIs, and I have verified that HMAC, RSA, and ECC algorithms are working.
For public keys, the code continues to accept PEM-encoded public keys, but it will also accept a Windows cert store path of the form: cert:\LocalMachine\My<thumbprint>. For private keys, there are unfortunately no good Windows APIs for importing PEM-encoded private keys, and so currently the code only accepts Windows cert store paths for jwt_encode. ("It's a feature!" -- Since realistically, no one on Windows is going to put their private keys in files.)
In addition, porting to Windows uncovered a memory management issue with the DLLs, where for whatever reason, sometimes when LibJWT would free a buffer allocated by Jansson, it would result in an AV in the heap code. To deal with Windows runtime issues with DLLs, I added the ability to set malloc, free, and realloc functions to the API, and this method propagates those down to Jansson, which also has this ability. I also added a "jwt_free_str" function that should be used to free strings allocated by jwt_encode_str. The malloc/free thing required me to rename all the allocation and free calls in the code to jalloc, jfree, etc.
Anyway, I would like to make a branch and submit a PR for this so I can get comments on it. Please let me know how I can go about doing that. Either I can become a contributor, or I can upload the patch file. Let me know.
Hello, @benmcollins!
This is not a bug, but I want to be sure:
On the https://jwt.io/ page your repository hasn't iss
, sub
, aud
, exp
, iat
check features and hasn't RS256
algorithm support, but using search I can find some examples in your repo with iss
, sub
, aud
, exp
, iat
and RS256
keywords. So, what is the status of these features in your project? Are they available?
In particular, I want to use your project for verifying Firebase ID tokens using C++. Is it possible?
I just want to know this and understand all correctly before I start.
Regards!
then java jwt can not decode
the jwt_decode return not 0
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJmaXJzdE5hbWUiOiJoZWxsbyIsIm5iZiI6MTQ4ODgxOSwiZXhwIjoxOTA4ODM1fQ.OKJ-3sOiXFgJr37xT6SIohzfQQLS7iaHYvNCd7WatuA
who can help me
Does this library support ES256? I ask because JWT.io seems to think it doesn't.
I am having a very simple setup:
libjwt/ <-- fresh unmodified git clone (master)
CMakeLists.txt <-- my cmake file
jwttest.c <-- a very simple test program
Contents of CMakeLists.txt:
cmake_minimum_required(VERSION 3.5.1)
project(myproject C)
SET(BUILD_TESTS FALSE CACHE BOOL "")
SET(BUILD_SHARED_LIBS TRUE CACHE BOOL "")
SET(WITHOUT_OPENSSL FALSE CACHE BOOL "")
SET(ENABLE_DEBUG_INFO_IN_RELEASE FALSE CACHE BOOL "")
add_subdirectory(libjwt)
include_directories(libjwt/include)
add_executable(jwttest jwttest.c)
target_link_libraries(jwttest jwt)
Contents of jwttest.c:
#include "jwt.h"
int main() {
jwt_t *jwt = NULL;
jwt_new(&jwt);
return 0;
}
Now when I am running cmake on this directory, and later make, it fails:
$ make
Scanning dependencies of target jwttest
[ 16%] Building C object CMakeFiles/jwttest.dir/jwttest.c.o
[ 33%] Linking C executable jwttest
/usr/bin/ld: cannot find -ljwt
collect2: error: ld returned 1 exit status
CMakeFiles/jwttest.dir/build.make:83: recipe for target 'jwttest' failed
make[2]: *** [jwttest] Error 1
CMakeFiles/Makefile2:72: recipe for target 'CMakeFiles/jwttest.dir/all' failed
make[1]: *** [CMakeFiles/jwttest.dir/all] Error 2
Makefile:129: recipe for target 'all' failed
make: *** [all] Error 2
Is this intended?
When you create a JWT with the algorithm set to none, then invalid output is created during encoding.
Compare the following two tokens:
Please notice the following difference:
The body part should be the same, but with token # 2 the last character (0) is missing.
While debugging I can see it getting truncated in the function "base64uri_encode". The reason why it is being truncated is because there is an "=" character in the header part of the token.
So the cause of this problem is that the "=" character in the header does not get truncated.
I have two tokens:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJzb21lLWxvbmctdXVpZCIsImZpcnN0TmFtZSI6ImhlbGxvIiwibGFzdE5hbWUiOiJ3b3JsZCIsInJvbGVzIjpbInRoaXMiLCJ0aGF0IiwidGhlb3RoZXIiXSwiaXNzIjoiaXNzdWVyIiwicGVyc29uSWQiOiI3NWJiM2NjNy1iOTMzLTQ0ZjAtOTNjNi0xNDdiMDgyZmFkYjUiLCJleHAiOjE5MDg4MzUyMDAsImlhdCI6MTQ4ODgxOTYwMCwidXNlcm5hbWUiOiJoZWxsby53b3JsZCJ9.tJoAl_pvq95hK7GKqsp5TU462pLTbmSYZc1fAHzcqWM
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJzb21lLWxvbmctdXVpZCIsImZpcnN0TmFtZSI6ImhlbGxvIiwibGFzdE5hbWUiOiJ3b3JsZCIsInJvbGVzIjpbInRoaXMiLCJ0aGF0IiwidGhlb3RoZXIiXSwiaXNzIjoiaXNzdWVyIiwicGVyc29uSWQiOiI3NWJiM2NjNy1iOTMzLTQ0ZjAtOTNjNi0xNDdiMDgyZmFkYjUiLCJleHAiOjE5MDg4MzUyMDAsImlhdCI6MTQ4ODgxOTYwMCwidXNlcm5hbWUiOiJoZWxsby53b3JsZCJ9.GpCRdGxE4uClX6Vg7eAPwG-37ZvNBQXyfcldKzDG_QI
First one is a test token from https://github.com/TeslaGov/ngx-http-auth-jwt-module/blob/master/test.sh, second one I generated using PHP. According to jwt.io, the first token is not valid, the second is valid. But when I use the nginx module which uses jwt_decode
from libjwt (which I compiled and installed), the first token is valid, second is invalid. Algorithm is HS256
.
Secret for testing is 00112233445566778899AABBCCDDEEFF00112233445566778899AABBCCDDEEFF
It's been a year since the latest tag.
Can you please tag a new release?
When I try to build I get this error:
Unknown CMake command "add_compile_options".
Apparently that's a feature of CMake 2.8.12 and later and CMakeLists.txt requires 2.8
cmake_minimum_required(VERSION 2.8)
I tried kicking it up to 2.8.12, but I only have 2.8.11... I'm on CentOS. Trying to figure out why I'm not getting this update.
Using the ES issue as a reason, I need to build out the test suite so that we make sure that the JWTs we create work with other implementations and vice versa.
Hello,
I agree valgrind is not perfect, but according to this sample test code, it detected a memory leak:
#include <iomanip>
#include <string>
#include <cstring>
#include <cstdint>
#include <cstdio>
#include <iostream>
#include <cstdlib>
#include <sstream>
#include <jwt.h>
using namespace std;
int test_jwt(const char* str, const char* secret) {
string decoded;
jwt_t* jwt_tok = NULL;
if (jwt_new(&jwt_tok))
return 1;
if (jwt_decode(&jwt_tok,
str,
(const unsigned char*) secret,
strlen(secret))) {
cout << "fail to decode jwt " << str << endl;
jwt_free(jwt_tok);
return 1;
}
char* output = jwt_dump_str(jwt_tok, 0);
decoded.assign(output);
cout << "successfully decoded jwt " << output << endl;
free(output);
jwt_free(jwt_tok);
return 0;
}
int
main (int argc, char* argv[])
{
return test_jwt(argv[1], argv[0]);
}
g++ -std=c++11 -ljwt -o test_jwt test_jwt.cc
valgrind --leak-check=yes eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHBpcmF0aW9uIjoiMTUwNDA5NzU4MyIsImlkIjoiS2VybGluayIsInZhbCI6ImFueSJ9.r1mqxLud3UFSpWHfbRDK6rCX5Igc9vsyoUTqQvlg secret
==3505== Memcheck, a memory error detector
==3505== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==3505== Using Valgrind-3.12.0 and LibVEX; rerun with -h for copyright info
==3505== Command: ./test_jwt eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHBpcmF0aW9uIjoiMTUwNDA5NzU4MyIsImlkIjoiS2VybGluayIsInZhbCI6ImFueSJ9.r1mqxLud3UFSpWHfbRDK6rCX5Igc9vsyoUTqQvlg secret
==3505==
fail to decode jwt eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHBpcmF0aW9uIjoiMTUwNDA5NzU4MyIsImlkIjoiS2VybGluayIsInZhbCI6ImFueSJ9.r1mqxLud3UFSpWHfbRDK6rCX5Igc9vsyoUTqQvlg
==3505==
==3505== HEAP SUMMARY:
==3505== in use at exit: 656 bytes in 9 blocks
==3505== total heap usage: 52 allocs, 43 frees, 6,014 bytes allocated
==3505==
==3505== 240 (32 direct, 208 indirect) bytes in 1 blocks are definitely lost in loss record 9 of 9
==3505== at 0x4C29BE3: malloc (vg_replace_malloc.c:299)
==3505== by 0x4E3889C: jwt_new (in /usr/lib64/libjwt.so.0.3.1)
==3505== by 0x400D5D: test_jwt(char const*, char const*) (in /home/jcourtat/test_jwt)
==3505== by 0x400EAA: main (in /home/jcourtat/test_jwt)
==3505==
==3505== LEAK SUMMARY:
==3505== definitely lost: 32 bytes in 1 blocks
==3505== indirectly lost: 208 bytes in 2 blocks
==3505== possibly lost: 0 bytes in 0 blocks
==3505== still reachable: 416 bytes in 6 blocks
==3505== suppressed: 0 bytes in 0 blocks
==3505== Reachable blocks (those to which a pointer was found) are not shown.
==3505== To see them, rerun with: --leak-check=full --show-leak-kinds=all
==3505==
==3505== For counts of detected and suppressed errors, rerun with: -v
==3505== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
Result is the same with successful decodes
Regards
Julien
When I try to get the "exp" or "iat" grant (created by other jwt libraries), NULL is returned. This is because those values are not stored as strings (and should not be stored as strings according to the spec.)
jwt_get_grant
calls get_js_string
which calls json_string_value
I made functions
jwt_get_grant_int
which calls get_js_int
which calls json_integer_value
Here's the JWT that I was parsing. I printed this via jwt_dump_str
:
{ "typ": "JWT", "alg": "HS256" } . { "emailAddress": "[email protected]", "exp": 1473905589, "firstName": "Joe", "iat": 1473819189, "iss": "RAMPART", "lastName": "Fitz", "personId": "0f416f7c-da9e-4fe6-8447-9a5b3b6d79c5", "roles": [ "rampartadmin", "someappuser" ], "sub": "0f416f7c-da9e-4fe6-8447-9a5b3b6d79c5" }
But I was unable to get the "exp" or "iat" values with jwt_get_grant
. I think that jwt_set_grant
will not be compliant for "exp" and "iat" values because it will set them as strings.
I have a branch if you'd like a pull request.
Pb:
Avoid change in grant.
For example change exp grant.
Solution:
Sign JWT with grant key/value.
Add new function call in "jwt_set_alg()" and "jwt_decode()".
That increase the size of signature but this avoid client change in grant part.
Code:
int jwt_set_key(jwt_t *jwt, const unsigned char *key, int len)
{
int grants_len = 0;
const char *grants = json_string_value(jwt->grants);
if (grants) {
grants_len = strlen(grants);
}
// Allocate memory for key
int key_len = len + grants_len;
// TODO check minimum size
jwt->key = malloc(key_len);
if (!jwt->key)
return ENOMEM;
// First copy the configured key
memcpy(jwt->key, key, len);
// Second sign all grants
if (grants) {
memcpy(&(jwt->key[len]), grants, grants_len);
}
jwt->key_len = key_len;
return 0;
}
Best regards
Sebastien
I encounter a decoding issue when I try to validate the token below against libjwt. jwt_decode does not return 0.
Here is a token, expired but with a valid signature.
eyJraWQiOiJkWUoxTDVnbWd0eDlWVU9xbVpyd2F6cWNhK3B5c1lHNUl3N3RSUXB6a3Z3PSIsImFsZyI6IlJTMjU2In0.eyJzdWIiOiJhMDQyZjY4My0xODNiLTQ1ZWUtOTZiYy1lNDdlYjhiMzc2MTYiLCJ0b2tlbl91c2UiOiJhY2Nlc3MiLCJzY29wZSI6ImF3cy5jb2duaXRvLnNpZ25pbi51c2VyLmFkbWluIiwiaXNzIjoiaHR0cHM6XC9cL2NvZ25pdG8taWRwLnVzLWVhc3QtMS5hbWF6b25hd3MuY29tXC91cy1lYXN0LTFfUWJvMXlMZ0ZIIiwiZXhwIjoxNDg1ODgyNDg5LCJpYXQiOjE0ODU4Nzg4ODksImp0aSI6Ijg1MTBlMGVkLWU3N2UtNDJmZS1hMmI2LTgyMjAzMDcxZWQyOCIsImNsaWVudF9pZCI6IjdicTVhanV0czM1anVmamVnMGYwcmhzNnRpIiwidXNlcm5hbWUiOiJhZG1pbjMifQ.IZqzZEuwKCVT0acHk3p5DnzPSNxg1tLISt8wZCMAHJAnLSdtbtVibrCTZkTLP5zPD16MgzgsID_CFF2wZXPGBihhyihu1B5W8GimY4eQOKrt4qiLJgK-D8tG6MSZ2K_9DC3RwhMjrNL4lpu2YoSOgugRdKpJWy4zadtHKptFkKrkI8qjnDoDSkF0kt4I6S1xOcEPuVhEOrGsfKr5Bm1N3wX9OVQhcTiVugKrpU8x0Mv1AJYdaxKASOQ6fFlNquwfohgLDwy3By3xU6RoY6ZWhKm5dcGW7H9gqmr9X4aBmHDmYG5KQtodwf0LOYtprPAXCs9X7Ja-7ddJvko8mDObTA
Here is the public key to verify signature.
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAn/7RTQX1xlllgo+aqo5z
d/+wqaRZwFWp3JJIUXryJ4d153J1gEYdz4RkjFO0X8kpv8qb5hdzWhhZHSItD+07
LaQXP4lSUuiK1lJAT/YW51D37nCkWm839gAqEGdsWsYQCvqJKSJr4pWCZTEx2MEf
ikmmnaXPR/VOVgZSj9kIoKo+kFwlw9LGVBHYAeR/W+l5DJQK6Yha8Igi36hnvZqq
HcQ4gkGUqEc//Tq2nyYNwvAN3ieZvtvL71rFW26FnuA4OwDER+TYSkAr8Z4wH2Ed
Gno1GZQAegIm+yWblleCaBVOnlk8VcDO9PecTiAFjjWAbQiaFKlkf/plD7KE4tAa
mQIDAQAB
-----END PUBLIC KEY-----
I checked with both pyjwt and jwt.io and the signature is correct.
Bug
Calling jwt_get_grant_int
with a key that does not exist will return -1
.
Explanation
This is caused by the get_jst_int
function added in cd227d7. The underlying call to jansson json_object_get
returns NULL
when the provided key is not found in the hash maps. Upon receiving NULL
, get_jst_int
returns the initial set val
of -1
which is directly returned by jwt_get_grant_int
.
Problems
Solution
jwt_get_grant_int
is the least invasive:
long jwt_get_grant_int(jwt_t *jwt, const char *grant)
{
...
long ret = get_js_int(jwt->grants, grant);
return ((ret == -1) ? 0 : ret);
}
0
in get_js_int
.
static long get_js_int(json_t *js, const char *key)
{
long val = 0;
...
}
However I did not dive too deep. I'm not sure of the sure of the repercussions of either solution, so I'll let you determine the best course of action. Just wanted to let you know.
Hello dudes,
Thanks for this awesome job!
So, it would be nice to choose between crypt engine OpenSSL(default) or GnuTLS. :-)
Thank you!
Hello,
There are some problems with the base64 functions on a Raspberry PI 2, armv7l architecture, the problem does not exist on a common x86_64 architecture.
Basically, all the jwt_decode
fail due to inconsistent base64 decoding.
For example, in the test jwt_new:test_jwt_decode
, the head value is eyJhbGciOiJub25lIn0
. This shoulb be decoded into the following string: {"alg":"none"}
. Although, the decoded string is the following: {"alg":"none"}>
with an additional character >
at the end, this leads to a failed json parsing, therefore the whole decoding process fail.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.