Yuneta-adapted fork of the libjwt C library for JSON Web Tokens, JSON Web Keys (JWK), and JWK Sets (JWKS).
The upstream libjwt changed its API and removed functions required by Yuneta, so this is a maintained fork tailored to Yuneta’s needs.
Source: kernel/c/libjwt/src/jwt.h
Core¶
jwt_get_alg()¶
jwt_alg_t jwt_get_alg(const jwt_t *jwt);jwt_alg_str()¶
const char *jwt_alg_str(jwt_alg_t alg);jwt_str_alg()¶
jwt_alg_t jwt_str_alg(const char *alg);jwt_set_alloc()¶
int jwt_set_alloc(jwt_malloc_t pmalloc, jwt_free_t pfree);jwt_get_alloc()¶
void jwt_get_alloc(jwt_malloc_t *pmalloc, jwt_free_t *pfree);jwt_get_crypto_ops()¶
const char *jwt_get_crypto_ops(void);jwt_get_crypto_ops_t()¶
jwt_crypto_provider_t jwt_get_crypto_ops_t(void);jwt_set_crypto_ops()¶
int jwt_set_crypto_ops(const char *opname);jwt_set_crypto_ops_t()¶
int jwt_set_crypto_ops_t(jwt_crypto_provider_t opname);jwt_crypto_ops_supports_jwk()¶
int jwt_crypto_ops_supports_jwk(void);jwt_init()¶
void jwt_init(void);Builder¶
jwt_builder_new()¶
jwt_builder_t *jwt_builder_new(void);jwt_builder_free()¶
void jwt_builder_free(jwt_builder_t *builder);jwt_builder_error()¶
int jwt_builder_error(const jwt_builder_t *builder);jwt_builder_error_msg()¶
const char *jwt_builder_error_msg(const jwt_builder_t *builder);jwt_builder_error_clear()¶
void jwt_builder_error_clear(jwt_builder_t *builder);jwt_builder_setkey()¶
int jwt_builder_setkey(jwt_builder_t *builder, const jwt_alg_t alg, const jwk_item_t *key);jwt_builder_enable_iat()¶
int jwt_builder_enable_iat(jwt_builder_t *builder, int enable);jwt_builder_setcb()¶
int jwt_builder_setcb(jwt_builder_t *builder, jwt_callback_t cb, void *ctx);jwt_builder_getctx()¶
void *jwt_builder_getctx(jwt_builder_t *builder);jwt_builder_generate()¶
char *jwt_builder_generate(jwt_builder_t *builder);jwt_builder_header_set()¶
jwt_value_error_t jwt_builder_header_set(jwt_builder_t *builder, jwt_value_t *value);jwt_builder_header_get()¶
jwt_value_error_t jwt_builder_header_get(jwt_builder_t *builder, jwt_value_t *value);jwt_builder_header_del()¶
jwt_value_error_t jwt_builder_header_del(jwt_builder_t *builder, const char *header);jwt_builder_claim_set()¶
jwt_value_error_t jwt_builder_claim_set(jwt_builder_t *builder, jwt_value_t *value);jwt_builder_claim_get()¶
jwt_value_error_t jwt_builder_claim_get(jwt_builder_t *builder, jwt_value_t *value);jwt_builder_claim_del()¶
jwt_value_error_t jwt_builder_claim_del(jwt_builder_t *builder, const char *claim);jwt_builder_time_offset()¶
int jwt_builder_time_offset(jwt_builder_t *builder, jwt_claims_t claim, time_t secs);Checker¶
jwt_checker_new()¶
jwt_checker_t *jwt_checker_new(void);jwt_checker_free()¶
void jwt_checker_free(jwt_checker_t *checker);jwt_checker_error()¶
int jwt_checker_error(const jwt_checker_t *checker);jwt_checker_error_msg()¶
const char *jwt_checker_error_msg(const jwt_checker_t *checker);jwt_checker_error_clear()¶
void jwt_checker_error_clear(jwt_checker_t *checker);jwt_checker_setkey()¶
int jwt_checker_setkey(jwt_checker_t *checker, const jwt_alg_t alg, const jwk_item_t *key);jwt_checker_setcb()¶
int jwt_checker_setcb(jwt_checker_t *checker, jwt_callback_t cb, void *ctx);jwt_checker_getctx()¶
void *jwt_checker_getctx(jwt_checker_t *checker);jwt_checker_verify()¶
int jwt_checker_verify(jwt_checker_t *checker, const char *token);jwt_checker_verify2()¶
The ArtGins variant of jwt_checker_verify(): verifies the token and returns its claims, so the caller reads them without parsing the token a second time. It fails closed (since 7.6.0, commit 46f62d8be): a non-NULL return means the token passed every check -- signature, algorithm, exp/nbf, a crit header refused -- and on any failure it returns NULL with the cause in the checker, never the claims of a token that did not verify.
json_t *jwt_checker_verify2(jwt_checker_t *checker, const char *token);Returns
The claims (a json_t object, yours: json_decref() it), or NULL with jwt_checker_error(checker) set and the message in jwt_checker_error_msg(checker).
Example
json_t *claims = jwt_checker_verify2(checker, token);
if(!claims) {
gobj_log_warning(gobj, 0,
"msgset", "%s", MSGSET_AUTH,
"msg", "%s", "token refused",
"error", "%s", jwt_checker_error_msg(checker),
NULL
);
return -1;
}
const char *username = json_string_value(json_object_get(claims, "preferred_username"));
json_decref(claims);Canonical consumer: c_authz.c.
jwt_checker_claim_get()¶
const char *jwt_checker_claim_get(jwt_checker_t *checker, jwt_claims_t type);jwt_checker_claim_set()¶
int jwt_checker_claim_set(jwt_checker_t *checker, jwt_claims_t type, const char *value);jwt_checker_claim_del()¶
int jwt_checker_claim_del(jwt_checker_t *checker, jwt_claims_t type);jwt_checker_time_leeway()¶
int jwt_checker_time_leeway(jwt_checker_t *checker, jwt_claims_t claim, time_t secs);JWT Header & Claims (legacy)¶
jwt_header_set()¶
jwt_value_error_t jwt_header_set(jwt_t *jwt, jwt_value_t *value);jwt_header_get()¶
jwt_value_error_t jwt_header_get(jwt_t *jwt, jwt_value_t *value);jwt_header_del()¶
jwt_value_error_t jwt_header_del(jwt_t *jwt, const char *header);jwt_claim_set()¶
jwt_value_error_t jwt_claim_set(jwt_t *jwt, jwt_value_t *value);jwt_claim_get()¶
jwt_value_error_t jwt_claim_get(jwt_t *jwt, jwt_value_t *value);jwt_claim_del()¶
jwt_value_error_t jwt_claim_del(jwt_t *jwt, const char *claim);JWK / JWKS¶
jwks_load()¶
jwk_set_t *jwks_load(jwk_set_t *jwk_set, const char *jwk_json_str);jwks_load_strn()¶
jwk_set_t *jwks_load_strn(jwk_set_t *jwk_set, const char *jwk_json_str, const size_t len);jwks_load_fromfile()¶
jwk_set_t *jwks_load_fromfile(jwk_set_t *jwk_set, const char *file_name);jwks_load_fromfp()¶
jwk_set_t *jwks_load_fromfp(jwk_set_t *jwk_set, FILE *input);jwks_load_fromurl()¶
jwk_set_t *jwks_load_fromurl(jwk_set_t *jwk_set, const char *url, int verify);jwks_create()¶
jwk_set_t *jwks_create(const char *jwk_json_str);jwks_create_strn()¶
jwk_set_t *jwks_create_strn(const char *jwk_json_str, const size_t len);jwks_create_fromfile()¶
jwk_set_t *jwks_create_fromfile(const char *file_name);jwks_create_fromfp()¶
jwk_set_t *jwks_create_fromfp(FILE *input);jwks_create_fromurl()¶
jwk_set_t *jwks_create_fromurl(const char *url, int verify);jwks_error()¶
int jwks_error(const jwk_set_t *jwk_set);jwks_error_any()¶
int jwks_error_any(const jwk_set_t *jwk_set);jwks_error_msg()¶
const char *jwks_error_msg(const jwk_set_t *jwk_set);jwks_error_clear()¶
void jwks_error_clear(jwk_set_t *jwk_set);jwks_free()¶
void jwks_free(jwk_set_t *jwk_set);jwks_item_get()¶
const jwk_item_t *jwks_item_get(const jwk_set_t *jwk_set, size_t index);jwks_find_bykid()¶
jwk_item_t *jwks_find_bykid(jwk_set_t *jwk_set, const char *kid);jwks_item_is_private()¶
int jwks_item_is_private(const jwk_item_t *item);jwks_item_error()¶
int jwks_item_error(const jwk_item_t *item);jwks_item_error_msg()¶
const char *jwks_item_error_msg(const jwk_item_t *item);jwks_item_curve()¶
const char *jwks_item_curve(const jwk_item_t *item);jwks_item_kid()¶
const char *jwks_item_kid(const jwk_item_t *item);jwks_item_alg()¶
jwt_alg_t jwks_item_alg(const jwk_item_t *item);jwks_item_kty()¶
jwk_key_type_t jwks_item_kty(const jwk_item_t *item);jwks_item_use()¶
jwk_pub_key_use_t jwks_item_use(const jwk_item_t *item);jwks_item_key_ops()¶
jwk_key_op_t jwks_item_key_ops(const jwk_item_t *item);jwks_item_pem()¶
const char *jwks_item_pem(const jwk_item_t *item);jwks_item_key_oct()¶
int jwks_item_key_oct(const jwk_item_t *item, const unsigned char **buf, size_t *len);jwks_item_key_bits()¶
int jwks_item_key_bits(const jwk_item_t *item);jwk_process_one()¶
ArtGins addition. Builds ONE key item from one JWK (a json_t object with kty EC, RSA, OKP or oct), for a set that is filled a key at a time -- c_authz adds each key its IdP publishes this way, instead of reloading the whole JWKS. The JWK is copied: the caller keeps jwk.
jwk_item_t *jwk_process_one(jwk_set_t *jwk_set, json_t *jwk);Returns
A new item, not yet in the set: add it with jwks_item_add() or free it with jwks_item_free2(). NULL only when memory runs out (the error is written in jwk_set). A JWK that cannot be used (no kty, an unknown one) still returns an item, with the error written IN THE ITEM: check jwks_item_error(item) before using it.
jwks_item_add()¶
ArtGins addition. Appends an item made by jwk_process_one() to the set; from then on the set owns it and frees it with the set.
int jwks_item_add(jwk_set_t *jwk_set, jwk_item_t *item);Returns
0.
jwks_item_free2()¶
ArtGins addition. Frees ONE item by pointer (an HMAC key is scrubbed before it is freed) and unlinks it from the set if it was in it. jwks_item_free() frees by index.
int jwks_item_free2(jwk_set_t *jwk_set, jwk_item_t *item);Returns
1 when freed, 0 when jwk_set or item is NULL.
Example
The way c_authz.c adds one key of the IdP, and undoes it when the next step fails:
jwk_item_t *jwk_item = jwk_process_one(priv->jwks, jn_jwk);
if(!jwk_item) {
return -1;
}
jwks_item_add(priv->jwks, jwk_item);
jwt_checker_t *jwt_checker = jwt_checker_new();
if(!jwt_checker) {
jwks_item_free2(priv->jwks, jwk_item);
return -1;
}jwks_item_free()¶
int jwks_item_free(jwk_set_t *jwk_set, size_t index);jwks_item_free_all()¶
int jwks_item_free_all(jwk_set_t *jwk_set);jwks_item_free_bad()¶
int jwks_item_free_bad(jwk_set_t *jwk_set);jwks_item_count()¶
size_t jwks_item_count(const jwk_set_t *jwk_set);