/* * 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; }
/* * parse and (optionally) decrypt 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 *keys, apr_jwt_error_t *err) { *j_jwt = apr_pcalloc(pool, sizeof(apr_jwt_t)); apr_jwt_t *jwt = *j_jwt; apr_array_header_t *unpacked = NULL; if (apr_jwt_header_parse(pool, s_json, &unpacked, &jwt->header, err) == FALSE) return FALSE; if (unpacked->nelts < 2) { apr_jwt_error(err, "could not successfully deserialize 2 or more elements from JWT header"); return FALSE; } if (apr_jwe_is_encrypted_jwt(pool, &jwt->header)) { char *decrypted = NULL; if ((apr_jwe_decrypt_jwt(pool, &jwt->header, unpacked, keys, &decrypted, err) == FALSE) || (decrypted == NULL)) return FALSE; apr_array_clear(unpacked); unpacked = NULL; json_decref(jwt->header.value.json); if (apr_jwt_header_parse(pool, (const char *) decrypted, &unpacked, &jwt->header, err) == FALSE) return FALSE; if (unpacked->nelts < 2) { apr_jwt_error(err, "could not successfully deserialize 2 or more elements from decrypted JWT header"); 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, err) == 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); apr_jwt_error(err, "could not successfully parse (base64urldecode) JWT signature"); return FALSE; } } return TRUE; }