azure-sdk-for-cpp
azure-sdk-for-cpp copied to clipboard
Should ctors of credentials throw exceptions during input validation or defer to first GetToken() call?
Context: A, potentially implicit, design goal of our DefaultAzureCredential (and by extension ChainedTokenCredential) is to allow the end user to construct one without hitting exceptions, as part of a “good” getting started experience.
For example, we don’t expect this line to fail/throw an exception to disrupt the getting started flow/samples for end users. In C++:
auto credential = std::make_shared<Azure::Identity::DefaultAzureCredential>();
In .NET:
var credential = new DefaultAzureCredential();
The way we’ve solved this problem in C++ is defer throwing an AuthenticationException on the first GetToken() call. Within the various Credential constructors, we log error messages when doing input/environment validation, but don’t explicitly throw. We follow this pattern even for credentials that are explicitly not part of the DAC (as of today) such as AzurePipelinesCredential, to be consistent, and since they can still be included as part of the ChainTokenCredential. I want to make sure the design choice of how credentials validate and throw is consistent across languages, both as individual types, and as part of a DAC.
Open questions:
- To make sure my assumption is sound: Is it a desired design goal to not throw an exception on the construction of DefaultAzureCredential as a good getting started experience?
- How do other languages solve this design problem, if not deferring throwing outside the credential ctor? For example, rather than deferring throwing, do we throw an exception in each Credential ctor for input/environment validation, but catch those exceptions in the chain or DAC ctors? I imagine we’d want to be consistent here in behavior across languages.