@@ -652,116 +652,133 @@ SciToken::deserialize_continue(std::unique_ptr<SciTokenAsyncStatus> status) {
652652std::unique_ptr<AsyncStatus>
653653Validator::get_public_keys_from_web (const std::string &issuer,
654654 unsigned timeout) {
655- std::string openid_metadata, oauth_metadata;
656- get_metadata_endpoint (issuer, openid_metadata, oauth_metadata);
657-
658- std::unique_ptr<AsyncStatus> status (new AsyncStatus ());
659- status->m_oauth_metadata_url = oauth_metadata;
660- status->m_cget .reset (new internal::SimpleCurlGet (1024 * 1024 , timeout));
661- auto cget_status = status->m_cget ->perform_start (openid_metadata);
662- status->m_continue_fetch = true ;
663- if (!cget_status.m_done ) {
664- return status;
665- }
666- return get_public_keys_from_web_continue (std::move (status));
655+ try {
656+ std::string openid_metadata, oauth_metadata;
657+ get_metadata_endpoint (issuer, openid_metadata, oauth_metadata);
658+
659+ std::unique_ptr<AsyncStatus> status (new AsyncStatus ());
660+ status->m_oauth_metadata_url = oauth_metadata;
661+ status->m_cget .reset (new internal::SimpleCurlGet (1024 * 1024 , timeout));
662+ auto cget_status = status->m_cget ->perform_start (openid_metadata);
663+ status->m_continue_fetch = true ;
664+ if (!cget_status.m_done ) {
665+ return status;
666+ }
667+ return get_public_keys_from_web_continue (std::move (status));
668+ } catch (const CurlException &e) {
669+ // Rethrow CURL errors during issuer key fetch as IssuerLookupException
670+ throw IssuerLookupException (e.what ());
671+ }
667672}
668673
669674std::unique_ptr<AsyncStatus> Validator::get_public_keys_from_web_continue (
670675 std::unique_ptr<AsyncStatus> status) {
671- char *buffer;
672- size_t len;
676+ try {
677+ char *buffer;
678+ size_t len;
673679
674- switch (status->m_state ) {
680+ switch (status->m_state ) {
675681
676- case AsyncStatus::DOWNLOAD_METADATA: {
677- auto cget_status = status->m_cget ->perform_continue ();
678- if (!cget_status.m_done ) {
679- return std::move (status);
680- }
681- if (cget_status.m_status_code != 200 ) {
682- if (status->m_oauth_fallback ) {
683- throw CurlException (" Failed to retrieve metadata provider "
684- " information for issuer." );
685- } else {
686- status->m_oauth_fallback = true ;
687- status->m_cget .reset (new internal::SimpleCurlGet ());
688- cget_status =
689- status->m_cget ->perform_start (status->m_oauth_metadata_url );
690- if (!cget_status.m_done ) {
691- return std::move (status);
682+ case AsyncStatus::DOWNLOAD_METADATA: {
683+ auto cget_status = status->m_cget ->perform_continue ();
684+ if (!cget_status.m_done ) {
685+ return std::move (status);
686+ }
687+ if (cget_status.m_status_code != 200 ) {
688+ if (status->m_oauth_fallback ) {
689+ throw IssuerLookupException (
690+ " Failed to retrieve metadata provider "
691+ " information for issuer." );
692+ } else {
693+ status->m_oauth_fallback = true ;
694+ status->m_cget .reset (new internal::SimpleCurlGet ());
695+ cget_status = status->m_cget ->perform_start (
696+ status->m_oauth_metadata_url );
697+ if (!cget_status.m_done ) {
698+ return std::move (status);
699+ }
700+ return get_public_keys_from_web_continue (std::move (status));
692701 }
693- return get_public_keys_from_web_continue (std::move (status));
694702 }
703+ status->m_cget ->get_data (buffer, len);
704+ std::string metadata (buffer, len);
705+ picojson::value json_obj;
706+ auto err = picojson::parse (json_obj, metadata);
707+ if (!err.empty ()) {
708+ throw JsonException (" JSON parse failure when downloading from "
709+ " the metadata URL " +
710+ status->m_cget ->get_url () + " : " + err);
711+ }
712+ if (!json_obj.is <picojson::object>()) {
713+ throw JsonException (" Metadata resource " +
714+ status->m_cget ->get_url () +
715+ " contains "
716+ " improperly-formatted JSON." );
717+ }
718+ auto top_obj = json_obj.get <picojson::object>();
719+ auto iter = top_obj.find (" jwks_uri" );
720+ if (iter == top_obj.end () || (!iter->second .is <std::string>())) {
721+ throw JsonException (" Metadata resource " +
722+ status->m_cget ->get_url () +
723+ " is missing 'jwks_uri' string value" );
724+ }
725+ auto jwks_uri = iter->second .get <std::string>();
726+ status->m_has_metadata = true ;
727+ status->m_state = AsyncStatus::DOWNLOAD_PUBLIC_KEY;
728+ status->m_cget .reset (new internal::SimpleCurlGet ());
729+ status->m_cget ->perform_start (jwks_uri);
730+ // This should also fall through the next state
695731 }
696- status->m_cget ->get_data (buffer, len);
697- std::string metadata (buffer, len);
698- picojson::value json_obj;
699- auto err = picojson::parse (json_obj, metadata);
700- if (!err.empty ()) {
701- throw JsonException (
702- " JSON parse failure when downloading from the metadata URL " +
703- status->m_cget ->get_url () + " : " + err);
704- }
705- if (!json_obj.is <picojson::object>()) {
706- throw JsonException (" Metadata resource " +
707- status->m_cget ->get_url () +
708- " contains "
709- " improperly-formatted JSON." );
710- }
711- auto top_obj = json_obj.get <picojson::object>();
712- auto iter = top_obj.find (" jwks_uri" );
713- if (iter == top_obj.end () || (!iter->second .is <std::string>())) {
714- throw JsonException (" Metadata resource " +
715- status->m_cget ->get_url () +
716- " is missing 'jwks_uri' string value" );
717- }
718- auto jwks_uri = iter->second .get <std::string>();
719- status->m_has_metadata = true ;
720- status->m_state = AsyncStatus::DOWNLOAD_PUBLIC_KEY;
721- status->m_cget .reset (new internal::SimpleCurlGet ());
722- status->m_cget ->perform_start (jwks_uri);
723- // This should also fall through the next state
724- }
725732
726- case AsyncStatus::DOWNLOAD_PUBLIC_KEY: {
727- auto cget_status = status->m_cget ->perform_continue ();
728- if (!cget_status.m_done ) {
729- return std::move (status);
730- }
731- if (cget_status.m_status_code != 200 ) {
732- throw CurlException (" Failed to retrieve the issuer's key set" );
733- }
733+ case AsyncStatus::DOWNLOAD_PUBLIC_KEY: {
734+ auto cget_status = status->m_cget ->perform_continue ();
735+ if (!cget_status.m_done ) {
736+ return std::move (status);
737+ }
738+ if (cget_status.m_status_code != 200 ) {
739+ throw IssuerLookupException (
740+ " Failed to retrieve the issuer's key set" );
741+ }
734742
735- status->m_cget ->get_data (buffer, len);
736- auto metadata = std::string (buffer, len);
737- picojson::value json_obj;
738- auto err = picojson::parse (json_obj, metadata);
739- if (!err.empty ()) {
740- throw JsonException (" JSON parse failure when downloading from the "
741- " public key URL " +
742- status->m_cget ->get_url () + " : " + err);
743+ status->m_cget ->get_data (buffer, len);
744+ auto metadata = std::string (buffer, len);
745+ picojson::value json_obj;
746+ auto err = picojson::parse (json_obj, metadata);
747+ if (!err.empty ()) {
748+ throw JsonException (
749+ " JSON parse failure when downloading from the "
750+ " public key URL " +
751+ status->m_cget ->get_url () + " : " + err);
752+ }
753+ status->m_cget .reset ();
754+
755+ auto now = std::time (NULL );
756+ // TODO: take expiration time from the cache-control header in the
757+ // response.
758+
759+ int next_update_delta =
760+ configurer::Configuration::get_next_update_delta ();
761+ int expiry_delta = configurer::Configuration::get_expiry_delta ();
762+ status->m_next_update = now + next_update_delta;
763+ status->m_expires = now + expiry_delta;
764+ status->m_keys = json_obj;
765+ status->m_continue_fetch = false ;
766+ status->m_done = true ;
767+ status->m_state = AsyncStatus::DONE;
743768 }
744- status->m_cget .reset ();
745-
746- auto now = std::time (NULL );
747- // TODO: take expiration time from the cache-control header in the
748- // response.
749-
750- int next_update_delta =
751- configurer::Configuration::get_next_update_delta ();
752- int expiry_delta = configurer::Configuration::get_expiry_delta ();
753- status->m_next_update = now + next_update_delta;
754- status->m_expires = now + expiry_delta;
755- status->m_keys = json_obj;
756- status->m_continue_fetch = false ;
757- status->m_done = true ;
758- status->m_state = AsyncStatus::DONE;
759- }
760- case AsyncStatus::DONE:
761- status->m_done = true ;
762-
763- } // Switch
764- return std::move (status);
769+ case AsyncStatus::DONE:
770+ status->m_done = true ;
771+
772+ } // Switch
773+ return std::move (status);
774+ } catch (const CurlException &e) {
775+ // Rethrow CURL errors during issuer key fetch as IssuerLookupException
776+ // (unless it's already an IssuerLookupException)
777+ if (dynamic_cast <const IssuerLookupException *>(&e)) {
778+ throw ;
779+ }
780+ throw IssuerLookupException (e.what ());
781+ }
765782}
766783
767784std::string Validator::get_jwks (const std::string &issuer) {
0 commit comments