Skip to content

Commit

Permalink
Add support for .withsshcertificateauthenticationscheme when WAM enab…
Browse files Browse the repository at this point in the history
…led (#4916)

* add suport for .withsshcertificateauthenticationscheme when WAM enabled

* Fix for test failure

* fix attempt for tests cancelling in pipeline

* remove extra new lines
  • Loading branch information
Ugonnaak1 authored Sep 11, 2024
1 parent a805fca commit 7c663df
Show file tree
Hide file tree
Showing 5 changed files with 307 additions and 113 deletions.
12 changes: 11 additions & 1 deletion src/client/Microsoft.Identity.Client.Broker/WamAdapters.cs
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,16 @@ public static NativeInterop.AuthParameters GetCommonAuthParameters(
{
authParams.Properties["instance_aware"] = "true";
}

//SSH Cert
if(authenticationRequestParameters.AuthenticationScheme.AccessTokenType == "ssh-cert")
{
authParams.Properties["key_id"]= authenticationRequestParameters.AuthenticationScheme.KeyId;
foreach (KeyValuePair<string, string> kvp in authenticationRequestParameters.AuthenticationScheme.GetTokenRequestParams())
{
authParams.Properties[kvp.Key] = kvp.Value;
}
}

//pass extra query parameters if there are any
if (authenticationRequestParameters.ExtraQueryParameters != null)
Expand Down Expand Up @@ -352,7 +362,7 @@ private static MsalTokenResponse ParseRuntimeResponse(
Scope = authResult.GrantedScopes,
ExpiresIn = (long)(DateTime.SpecifyKind(authResult.ExpiresOn, DateTimeKind.Utc) - DateTimeOffset.UtcNow).TotalSeconds,
ClientInfo = authResult.Account.ClientInfo,
TokenType = authResult.IsPopAuthorization ? Constants.PoPAuthHeaderPrefix : BrokerResponseConst.Bearer,
TokenType = authResult.IsPopAuthorization ? Constants.PoPAuthHeaderPrefix: authenticationRequestParameters.RequestContext.ApiEvent.TokenType.ToString(),
WamAccountId = authResult.Account.AccountId,
TokenSource = TokenSource.Broker
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,17 @@
using System.Net;
using System.Net.Http;
using System.Runtime.InteropServices;
using System.Security.Cryptography;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Identity.Client;
using Microsoft.Identity.Client.ApiConfig;
using Microsoft.Identity.Client.Broker;
using Microsoft.Identity.Client.Core;
using Microsoft.Identity.Client.OAuth2;
using Microsoft.Identity.Client.SSHCertificates;
using Microsoft.Identity.Client.UI;
using Microsoft.Identity.Client.Utils;
using Microsoft.Identity.Test.Common;
using Microsoft.Identity.Test.Common.Core.Helpers;
using Microsoft.Identity.Test.Common.Core.Mocks;
Expand All @@ -35,6 +38,23 @@ public class RuntimeBrokerTests
[DllImport("user32.dll")]
static extern IntPtr GetForegroundWindow();

//This client id is for Azure CLI which is one of the only 2 clients that have PreAuth to use ssh cert feature
string _SSH_ClientId = "04b07795-8ddb-461a-bbee-02f9e1bf7b46";
//SSH User impersonation scope required for this test
private string[] _SSH_scopes = new[] { "https://pas.windows.net/CheckMyAccess/Linux/user_impersonation" };

private string CreateJwk()
{
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(2048);
RSAParameters rsaKeyInfo = rsa.ExportParameters(false);

string modulus = Base64UrlHelpers.Encode(rsaKeyInfo.Modulus);
string exp = Base64UrlHelpers.Encode(rsaKeyInfo.Exponent);
string jwk = $"{{\"kty\":\"RSA\", \"n\":\"{modulus}\", \"e\":\"{exp}\"}}";

return jwk;
}

// This test should fail locally but succeed in a CI build.
[IgnoreOnOneBranch]
[TestMethod]
Expand Down Expand Up @@ -223,6 +243,45 @@ await AssertException.TaskThrowsAsync<MsalUiRequiredException>(
.ConfigureAwait(false);
}

[IgnoreOnOneBranch]
[TestMethod]
public async Task WamWithSSHCertificateAuthenticationSchemeAsync()
{
IntPtr intPtr = GetForegroundWindow();
Func<IntPtr> windowHandleProvider = () => intPtr;
var labResponse = await LabUserHelper.GetDefaultUserAsync().ConfigureAwait(false);

IPublicClientApplication pca = PublicClientApplicationBuilder
.Create(_SSH_ClientId)
.WithTestLogging()
.WithAuthority(labResponse.Lab.Authority, "organizations")
.WithParentActivityOrWindow(windowHandleProvider)
.WithBroker(new BrokerOptions(BrokerOptions.OperatingSystems.Windows))
.Build();

string jwk = CreateJwk();
//Do a login with username password
AuthenticationResult result = await pca
.AcquireTokenByUsernamePassword(_SSH_scopes, labResponse.User.Upn, labResponse.User.GetOrFetchPassword())
.ExecuteAsync()
.ConfigureAwait(false);

//Assert successful login
var accounts = await pca.GetAccountsAsync().ConfigureAwait(false);
Assert.IsNotNull(accounts);
var account = accounts.FirstOrDefault();
Assert.IsNotNull(account);

//Acquire token with SSH cert
result = await pca
.AcquireTokenSilent(_SSH_scopes, account)
.WithSSHCertificateAuthenticationScheme(jwk, "key1")
.ExecuteAsync()
.ConfigureAwait(false);

Assert.AreEqual("SshCert", result.TokenType);
}

[IgnoreOnOneBranch]
[TestMethod]
public async Task WamUsernamePasswordWithForceRefreshAsync()
Expand Down
Loading

0 comments on commit 7c663df

Please sign in to comment.