Skip to content

Commit

Permalink
Adding SNI support to ClientCertificateCredential (#14636)
Browse files Browse the repository at this point in the history
* Adding SNI support to ClientCertificateCredential

* updating API ref
  • Loading branch information
schaabs authored Aug 31, 2020
1 parent 398ab3c commit 70b00f7
Show file tree
Hide file tree
Showing 10 changed files with 334 additions and 4 deletions.
2 changes: 2 additions & 0 deletions sdk/identity/Azure.Identity/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
# Release History
## 1.3.0-preview.1 (Unreleased)

### New Features
- Restoring Application Authentication APIs from 1.2.0-preview.6
- Added `IncludeX5CClaimHeader` to `ClientCertificateCredentialOptions` to enable subject name / issuer authentication with the `ClientCertificateCredential`.

### Fixes and improvements
- Fixed issue with non GUID Client Ids (Issue [#14585](https://github.com/Azure/azure-sdk-for-net/issues/14585))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ public partial class ClientCertificateCredentialOptions : Azure.Identity.TokenCr
public ClientCertificateCredentialOptions() { }
public bool AllowUnencryptedCache { get { throw null; } set { } }
public bool EnablePersistentCache { get { throw null; } set { } }
public bool IncludeX5CCliamHeader { get { throw null; } set { } }
}
public partial class ClientSecretCredential : Azure.Core.TokenCredential
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ internal ClientCertificateCredential(string tenantId, string clientId, IX509Cert

_pipeline = pipeline ?? CredentialPipeline.GetInstance(options);

_client = client ?? new MsalConfidentialClient(_pipeline, tenantId, clientId, certificateProvider, options as ITokenCacheOptions);
_client = client ?? new MsalConfidentialClient(_pipeline, tenantId, clientId, certificateProvider, (options as ClientCertificateCredentialOptions)?.IncludeX5CCliamHeader ?? false, options as ITokenCacheOptions);
}

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,10 @@ public class ClientCertificateCredentialOptions : TokenCredentialOptions, IToken
/// If set to true the credential will fall back to storing tokens in an unencrypted file if no OS level user encryption is available.
/// </summary>
public bool AllowUnencryptedCache { get; set; }

/// <summary>
/// Will include x5c header to enable subject name / issuer based authentication for the <see cref="ClientCertificateCredential"/>.
/// </summary>
public bool IncludeX5CCliamHeader { get; set; }
}
}
7 changes: 5 additions & 2 deletions sdk/identity/Azure.Identity/src/MsalConfidentialClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ namespace Azure.Identity
internal class MsalConfidentialClient : MsalClientBase<IConfidentialClientApplication>
{
private readonly string _clientSecret;
private readonly bool _includeX5CClaimHeader;
private readonly ClientCertificateCredential.IX509Certificate2Provider _certificateProvider;

/// <summary>
Expand All @@ -29,9 +30,10 @@ public MsalConfidentialClient(CredentialPipeline pipeline, string tenantId, stri
_clientSecret = clientSecret;
}

public MsalConfidentialClient(CredentialPipeline pipeline, string tenantId, string clientId, ClientCertificateCredential.IX509Certificate2Provider certificateProvider, ITokenCacheOptions cacheOptions)
public MsalConfidentialClient(CredentialPipeline pipeline, string tenantId, string clientId, ClientCertificateCredential.IX509Certificate2Provider certificateProvider, bool includeX5CClaimHeader, ITokenCacheOptions cacheOptions)
: base(pipeline, tenantId, clientId, cacheOptions)
{
_includeX5CClaimHeader = includeX5CClaimHeader;
_certificateProvider = certificateProvider;
}

Expand All @@ -56,7 +58,8 @@ protected override async ValueTask<IConfidentialClientApplication> CreateClientA
public virtual async ValueTask<AuthenticationResult> AcquireTokenForClientAsync(string[] scopes, bool async, CancellationToken cancellationToken)
{
IConfidentialClientApplication client = await GetClientAsync(async, cancellationToken).ConfigureAwait(false);
return await client.AcquireTokenForClient(scopes).ExecuteAsync(async, cancellationToken).ConfigureAwait(false);

return await client.AcquireTokenForClient(scopes).WithSendX5C(_includeX5CClaimHeader).ExecuteAsync(async, cancellationToken).ConfigureAwait(false);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,25 @@ public async Task FromX509Certificate2()
}
}

[Test]
public async Task IncludeX5CCliamHeader()
{
var tenantId = TestEnvironment.ServicePrincipalTenantId;
var clientId = TestEnvironment.ServicePrincipalClientId;
var certPath = TestEnvironment.ServicePrincipalSniCertificatePath;

var options = Recording.InstrumentClientOptions(new ClientCertificateCredentialOptions { IncludeX5CCliamHeader = true });

var credential = new ClientCertificateCredential(tenantId, clientId, certPath, options);

var tokenRequestContext = new TokenRequestContext(new[] { AzureAuthorityHosts.GetDefaultScope(AzureAuthorityHosts.AzurePublicCloud) });

// ensure we can initially acquire a token
AccessToken token = await credential.GetTokenAsync(tokenRequestContext);

Assert.IsNotNull(token.Token);
}

[Test]
public void IncorrectCertificate()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,6 @@ public IdentityTestEnvironment() : base("identity")
public string ServicePrincipalClientSecret => GetOptionalVariable("IDENTITY_SP_CLIENT_SECRET") ?? "SANITIZED";
public string ServicePrincipalCertificatePfxPath => GetOptionalVariable("IDENTITY_SP_CERT_PFX") ?? Path.Combine(TestContext.CurrentContext.TestDirectory, "Data", "cert.pfx");
public string ServicePrincipalCertificatePemPath => GetOptionalVariable("IDENTITY_SP_CERT_PEM") ?? Path.Combine(TestContext.CurrentContext.TestDirectory, "Data", "cert.pem");

public string ServicePrincipalSniCertificatePath => GetOptionalVariable("IDENTITY_SP_SNI_CERT") ?? Path.Combine(TestContext.CurrentContext.TestDirectory, "Data", "cert.pfx");
}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 70b00f7

Please sign in to comment.