Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

libjwt (JWT Authentication)

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);