Hi navgupta ,
The application is a C# application that is connecting to Remote PowerShell.
We are not using New-PSSession but a Runspace in C# connecting PowerShell remotely. Something like this.
public void ConnectUsingOauth()
{
PSCredential credential = GetBearerCredentials();
var connection = new WSManConnectionInfo(new Uri("https://outlook.office365.com/powershell-liveid?BasicAuthToOAuthConversion=true"), "http://schemas.microsoft.com/powershell/Microsoft.Exchange", Credentials);
connection.AuthenticationMechanism = AuthenticationMechanism.Basic;
Runspace r = System.Management.Automation.Runspaces.RunspaceFactory.CreateRunspace(connection);
r.Open();
using (var p = r.CreatePipeline())
{
p.Commands.Add("Get-Mailbox");
p.Invoke();
}
}
/// <summary>
/// Gets the credentials.
/// </summary>
/// <returns>PSCredential.</returns>
public static PSCredential GetBearerCredentials()
{
lock (static_lock)
{
PSCredential cred = GetCredentials(); // Gets basic credentials
IAzureDirectoryProvider azure = ExtendedSchemaProvider.Instance.GetAzureDirectoryProvider();
System.Threading.Tasks.Task<string> token = System.Threading.Tasks.Task.Run(async () =>
{
return await GetUserAccessTokenAsync(azure.TenantName, cred);
});
string accessToken = token.Result;
string password = "Bearer " + accessToken;
System.Security.SecureString p = new System.Security.SecureString();
foreach (char c in password)
p.AppendChar(c);
return new PSCredential(cred.UserName,p );
}
}
// Get an access token. First tries to get the token from the token cache.
public async static System.Threading.Tasks.Task<string> GetUserAccessTokenAsync(string tenantName,PSCredential cred)
{
string authority = string.Format(@"https://login.microsoftonline.com/{0}/v2.0", tenantName);
//https://www.michev.info/Blog/Post/1771/hacking-your-way-around-modern-authentication-and-the-powershell-modules-for-office-365
// "a0c73c16-a7e3-4564-9a95-2bdf47383716" - this is the standard client ID for Exchange
// "urn:ietf:wg:oauth:2.0:oob" - standard redirect URI
PublicClientApplication app = new PublicClientApplication(
"a0c73c16-a7e3-4564-9a95-2bdf47383716",
authority,
tokenCache);
app.RedirectUri = "urn:ietf:wg:oauth:2.0:oob";
AuthenticationResult result = await app.AcquireTokenByUsernamePasswordAsync(new string[] { "https://outlook.office365.com/.default" }, cred.UserName, cred.Password);
return result.AccessToken;
}
The EX PowerShell module is a complete change. Because it forces local PowerShell instead of just remoting.
The connection time using the EX module is about 10-15 seconds vs 1-2 using OAuth and a direct connection.
The EX Powershell module also causes data type conversions in code that are not ideal. For example an Enum becomes a String.
This works perfectly at the moment and is there just a change to the auth mechanism for us. The EX Module is a problem.
Thanks,
Shaun.