/* * check whether the provided string is a valid id_token and return its parsed contents */ apr_byte_t oidc_proto_parse_idtoken(request_rec *r, oidc_cfg *cfg, oidc_provider_t *provider, const char *id_token, const char *nonce, char **user, apr_jwt_t **jwt, apr_byte_t is_code_flow) { oidc_debug(r, "enter"); if (apr_jwt_parse(r->pool, id_token, jwt, cfg->private_keys, provider->client_secret) == FALSE) { if ((*jwt) && ((*jwt)->header.alg) && (apr_jwe_algorithm_is_supported(r->pool, (*jwt)->header.alg) == FALSE)) { oidc_error(r, "JWE content key encryption algorithm is not supported: %s", (*jwt)->header.alg); } if ((*jwt) && ((*jwt)->header.enc) && (apr_jwe_encryption_is_supported(r->pool, (*jwt)->header.enc) == FALSE)) { oidc_error(r, "JWE encryption type is not supported: %s", (*jwt)->header.enc); } oidc_error(r, "apr_jwt_parse failed for JWT with header: \"%s\"", apr_jwt_header_to_string(r->pool, id_token)); apr_jwt_destroy(*jwt); return FALSE; } oidc_debug(r, "successfully parsed (and possibly decrypted) JWT with header: \"%s\"", apr_jwt_header_to_string(r->pool, id_token)); // make signature validation exception for 'code' flow and the algorithm NONE if (is_code_flow == FALSE || strcmp((*jwt)->header.alg, "none") != 0) { apr_byte_t refresh = FALSE; if (oidc_proto_idtoken_verify_signature(r, cfg, provider, *jwt, &refresh) == FALSE) { oidc_error(r, "id_token signature could not be validated, aborting"); apr_jwt_destroy(*jwt); return FALSE; } } /* this is where the meat is */ if (oidc_proto_validate_idtoken(r, provider, *jwt, nonce) == FALSE) { oidc_error(r, "id_token payload could not be validated, aborting"); apr_jwt_destroy(*jwt); return FALSE; } if (oidc_proto_set_remote_user(r, cfg, provider, *jwt, user) == FALSE) { oidc_error(r, "remote user could not be set, aborting"); apr_jwt_destroy(*jwt); return FALSE; } /* log our results */ oidc_debug(r, "valid id_token for user \"%s\" (expires in %" APR_TIME_T_FMT " seconds)", *user, (*jwt)->payload.exp - apr_time_sec(apr_time_now())); /* since we've made it so far, we may as well say it is a valid id_token */ return TRUE; }
/* * check if the the JWT is encrypted */ apr_byte_t apr_jwe_is_encrypted_jwt(apr_pool_t *pool, apr_jwt_header_t *hdr) { return (apr_jwe_algorithm_is_supported(pool, hdr->alg) && (apr_jwe_encryption_is_supported(pool, hdr->enc))); }