When using a shared key for authorization, some services require that the name of the key be used as a component of the algorithm to form the authorization token. For these cases, AzureKeyCredential
and AzureSasCredential
aren't adequate as they track only a single value. A new credential type, AzureNamedKeyCredential
has been approved to address this gap.
-
The names used in this document are intended for illustration only. Some names are not ideal and will need to be refined during discussions.
-
Some details not related to the high-level concept are not illustrated; the scope of this is limited to the high level shape and paradigms for the feature area.
-
Fake methods are used to illustrate "something needs to happen, but the details are unimportant." These methods will most often use ellipses for the parameter list, in order to help differentiate them.
-
Offer a token credential suitable for working with any service needing a named key that follows patterns established by the other credential types offered in
Azure.Core
andAzure.Identity
. -
Developers should be able to construct the credential by providing a string-based name and key.
-
Developers should be able to update the name and key after construction to support rolling credentials or using a new access policy. Updating credential information should be done in-place and not require creating a new credential instance.
-
Developers should be able to read the name of they key, in order to support caching within an application so that it can be easily identified when updates are needed.
-
The Azure SDKs should be able to read the name and key, ensuring they reflect the most current values.
-
Support updates and reads concurrently with consistent behavior. Developers should be able to update the credential at any time without concern for whether the SDK is reading from it.
-
Providing a friendly and discoverable means for developers to read the key from the credential.
-
Allowing the name or key to be updated independently; both elements will be required when updating a credential.
-
Unlike the other key and SAS-based credential types, the named key credential has multiple attributes; the name/key pairing must be treated as an atomic unit for reads and updates.
-
Unlike the
TokenCredential
andAzure.Identity
types, the named key credential cannot implicitly renew the name and key when needed; the updates are the responsibility of the host application and must be performed manually. -
Reading the name and key from the credential is likely to be performed as part of the hot path for service clients; this should be optimized for performance and efficiency.
This approach uses deconstruction to provide an atomic means of reading multiple values at once, without introducing a tuple as part of a public API.
public class AzureNamedKeyCredential
{
public string Name { get; }
public AzureNamedKeyCredential(string name, string key);
public void Update (string name, string key);
[EditorBrowsable(EditorBrowsableState.Never)]
public void Deconstruct(out string name, out string key);
}
// Use the credential to create an Azure SDK client type.
var credential = new AzureNamedKeyCredential("<< NAME >>", "<< KEY >>");
var client = new AzureFakeClient("<< URI >>", credential, new AzureFakeClientOptions());
// Updating the name and/or key can be done without interacting with the client; the
// client should respond to the change automatically.
credential.Update("<< NEW NAME >>", "<< NEW KEY >>");
// Read the name and key for generation of an auth token.
var (name, key) = credential;
var authToken = CreateAuthToken(name, key, ...);
// -- OR --
credential.Deconstruct(out var name, out var key);
var authToken = CreateAuthToken(name, key, ...);
- No new type is needed to represent the name/key pair.
- The intended API for developers is discoverable and differentiated from that intended for SDK use.
- There is no emphasis on reading the key for developers using the credential.
- Developers may read the name/key pair to aid in mocking/testing scenarios.
- Deconstruction is still a newer pattern in C# and may not be obvious to Azure SDK authors.
This approach uses a new container type to represent the name/key pairing, allowing it to be represented clearly and treated as a single unit.
public class AzureNamedKeyCredential
{
public string Name { get; }
public AzureNamedKeyCredential(string name, string key);
public void Update (string name, string key);
[EditorBrowsable(EditorBrowsableState.Never)]
public AzureNamedKey GetNamedKey();
}
public class AzureNamedKey
{
public string Name { get; }
public string Key { get; }
internal AzureNamedKey(string name, string key);
}
// Use the credential to create an Azure SDK client type.
var credential = new AzureNamedKeyCredential("<< NAME >>", "<< KEY >>");
var client = new AzureFakeClient("<< URI >>", credential, new AzureFakeClientOptions());
// Updating the name and/or key can be done without interacting with the client; the
// client should respond to the change automatically.
credential.Update("<< NEW NAME >>", "<< NEW KEY >>");
// Read the name and key for generation of an auth token.
var namedKey = credential.GetNamedKey();
var authToken = CreateAuthToken(namedKey.Name, namedKey.Key, ...);
- The intended API for developers is discoverable and differentiated from that intended for SDK use.
- There is no emphasis on reading the key for developers using the credential.
- Developers may read the name/key pair to aid in mocking/testing scenarios.
- This requires a new public type to be introduced but is not something developers are likely to use.
GetNamedKey
may look more tempting to developers thanDeconstruct
which seems more like plumbing.
This approach uses an embedded container type to represent the name/key pairing, allowing it to be represented clearly and treated as a single unit.
public class AzureNamedKeyCredential
{
public string Name { get; }
public AzureNamedKeyCredential(string name, string key);
public void Update (string name, string key);
[EditorBrowsable(EditorBrowsableState.Never)]
public NamedKey GetNamedKey();
public class NamedKey
{
public string Name { get; }
public string Key { get; }
internal NamedKey(string name, string key);
}
}
// Use the credential to create an Azure SDK client type.
var credential = new AzureNamedKeyCredential("<< NAME >>", "<< KEY >>");
var client = new AzureFakeClient("<< URI >>", credential, new AzureFakeClientOptions());
// Updating the name and/or key can be done without interacting with the client; the
// client should respond to the change automatically.
credential.Update("<< NEW NAME >>", "<< NEW KEY >>");
// Read the name and key for generation of an auth token.
var namedKey = credential.GetNamedKey();
var authToken = CreateAuthToken(namedKey.Name, namedKey.Key, ...);
- The intended API for developers is discoverable and differentiated from that intended for SDK use.
- There is no top-level type pollution.
- There is no emphasis on reading the key for developers using the credential.
- Developers may read the name/key pair to aid in mocking/testing scenarios.
GetNamedKey
may look more tempting to developers thanDeconstruct
which seems more like plumbing.- The embedded type is a bit more cumbersome to reference directly, outside the credential.