/* * parse a JSON Web Token */ apr_byte_t apr_jwt_parse(apr_pool_t *pool, const char *s_json, apr_jwt_t **j_jwt, apr_hash_t *private_keys, const char *shared_key) { *j_jwt = apr_pcalloc(pool, sizeof(apr_jwt_t)); apr_jwt_t *jwt = *j_jwt; apr_array_header_t *unpacked = apr_jwt_compact_deserialize(pool, s_json); if (unpacked->nelts < 2) return FALSE; /* parse the header fields */ if (apr_jwt_parse_header(pool, ((const char**) unpacked->elts)[0], &jwt->header) == FALSE) return FALSE; if (apr_jwe_is_encrypted_jwt(pool, &jwt->header)) { char *decrypted = NULL; if ((apr_jwe_decrypt_jwt(pool, &jwt->header, unpacked, private_keys, shared_key, &decrypted) == FALSE) || (decrypted == NULL)) return FALSE; apr_array_clear(unpacked); unpacked = apr_jwt_compact_deserialize(pool, (const char *) decrypted); json_decref(jwt->header.value.json); if (unpacked->nelts < 2) return FALSE; /* parse the nested header fields */ if (apr_jwt_parse_header(pool, ((const char**) unpacked->elts)[0], &jwt->header) == FALSE) return FALSE; } /* concat the base64url-encoded payload to the base64url-encoded header for signature verification purposes */ jwt->message = apr_pstrcat(pool, ((const char**) unpacked->elts)[0], ".", ((const char**) unpacked->elts)[1], NULL); /* parse the payload fields */ if (apr_jwt_parse_payload(pool, ((const char**) unpacked->elts)[1], &jwt->payload) == FALSE) { json_decref(jwt->header.value.json); return FALSE; } if (unpacked->nelts > 2 && strcmp(jwt->header.alg, "none") != 0) { /* remainder is the signature */ if (apr_jwt_parse_signature(pool, ((const char**) unpacked->elts)[2], &jwt->signature) == FALSE) { json_decref(jwt->header.value.json); json_decref(jwt->payload.value.json); return FALSE; } } return TRUE; }
/* * return plain deserialized header text */ const char *apr_jwt_header_to_string(apr_pool_t *pool, const char *s_json) { apr_array_header_t *unpacked = apr_jwt_compact_deserialize(pool, s_json); if (unpacked->nelts < 1) return NULL; apr_jwt_header_t header; if (apr_jwt_parse_header(pool, ((const char**) unpacked->elts)[0], &header) == FALSE) return NULL; json_decref(header.value.json); return header.value.str; }
/* * parse a JOSE header from a compact serialized string */ apr_byte_t apr_jwt_header_parse(apr_pool_t *pool, const char *s_json, apr_array_header_t **unpacked, apr_jwt_header_t *header, apr_jwt_error_t *err) { *unpacked = apr_jwt_compact_deserialize(pool, s_json); if ((*unpacked)->nelts < 1) { apr_jwt_error(err, "could not deserialize at least one element"); return FALSE; } if (apr_jwt_parse_header_object(pool, ((const char**) (*unpacked)->elts)[0], header, err) == FALSE) return FALSE; return TRUE; }