Skip to content
This repository has been archived by the owner on Jul 22, 2024. It is now read-only.

Commit

Permalink
Adding new user features (#193)
Browse files Browse the repository at this point in the history
  • Loading branch information
Isaiah Williams authored Nov 20, 2019
1 parent a2975f3 commit c51d13f
Show file tree
Hide file tree
Showing 13 changed files with 109 additions and 62 deletions.
32 changes: 31 additions & 1 deletion docs/help/Get-PartnerUser.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ Gets a list of users from the partner tenant
## SYNTAX

```powershell
Get-PartnerUser [<CommonParameters>]
Get-PartnerUser [-UserId <String>] [-UserPrincipalName <String>] [<CommonParameters>]
```

## DESCRIPTION
Expand All @@ -32,6 +32,36 @@ Gets a list of users from the partner tenant

## PARAMETERS

### -UserId
The identifier for the user.

```yaml
Type: String
Parameter Sets: (All)
Aliases:

Required: False
Position: Named
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -UserPrincipalName
The user principal name for the user.
```yaml
Type: String
Parameter Sets: (All)
Aliases: UPN

Required: False
Position: Named
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### CommonParameters
This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216).
Expand Down
23 changes: 16 additions & 7 deletions docs/help/Get-PartnerUserSignInActivity.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ Get-PartnerUserSignInActivity [-EndDate <DateTime>] [-StartDate <DateTime>] [-Us
```

## DESCRIPTION
Gets the sign activities for the specified user.
Gets the sign-in activities for the specified user.

## EXAMPLES

Expand All @@ -29,23 +29,23 @@ Gets the sign activities for the specified user.
PS C:\> Get-PartnerUserSignInActivity -UserId '3dd89389-b34c-4f5a-975d-516df5694d7e'
```

Gets the sign activities for the specified user.
Gets the sign-in activities for the specified user.

### Example 2
```powershell
PS C:\> Get-PartnerUserSignInActivity -EndDate (Get-Date) -StartDate (Get-Date).AddDays(-7) -UserId '3dd89389-b34c-4f5a-975d-516df5694d7e'
PS C:\> Get-PartnerUserSignInActivity -StartDate (Get-Date).AddDays(-7) -UserId '3dd89389-b34c-4f5a-975d-516df5694d7e'
```

Gets the sign activities from the past seven days for the specified user.
Gets the sign-in activities from the past seven days for the specified user.

### Example 3
```powershell
PS C:\> $users = Get-PartnerUser
PS C:\> $activities = $users.ForEach({Get-PartnerUserSignInActivity -EndDate (Get-Date) -StartDate (Get-Date).AddDays(-7) -UserId $_.Id})
PS C:\> $activities = $users.ForEach({Get-PartnerUserSignInActivity -StartDate (Get-Date).AddDays(-7) -UserId $_.Id})
PS C:\> $activities | ? {$_.AuthenticationDetails | ? {$_.Succeeded -eq $true}}
```

Gets the sign-activities from the past seven days that have successfully authenticated.
Gets the sign-in activities from the past seven days that have successfully authenticated.

### Example 4
```powershell
Expand All @@ -58,9 +58,18 @@ Gets the sign-in activities from the past seven days where the resource being ac

### Example 5
```powershell
PS C:\> $users = Get-PartnerUser
PS C:\> $activities = $users.ForEach({Get-PartnerUserSignInActivity -StartDate (Get-Date).AddDays(-7) -UserId $_.Id})
PS C:\> $activities | ? {$_.AuthenticationDetails | ? {$_.Succeeded -eq $true}} | ? {$_.MfaDetail -eq $null}
```

Gets the sign-in activities from the past seven days that have successfully authenticated, but have not utilized multi-factor authentication.

### Example 6
```powershell
PS C:> $users = Get-PartnerUser
PS C:> $activities = $users.ForEach({Get-PartnerUserSignInActivity -EndDate (Get-Date) -StartDate (Get-Date).AddDays(-7) -UserId $_.Id})
PS C:> $activities | ? {$_.AuthenticationDetails | ? {$_.Succeeded -eq $true}} | ? {$_.MfaDetail | ? {$_.AuthMethod -eq $null}} | ? {$_.ResourceId -eq 'fa3d9a0c-3fb0-42cc-9193-47c7ecd2edbd'}
PS C:> $activities | ? {$_.AuthenticationDetails | ? {$_.Succeeded -eq $true}} | ? {$_.MfaDetail -eq $null} | ? {$_.ResourceId -eq 'fa3d9a0c-3fb0-42cc-9193-47c7ecd2edbd'}
```

Gets the sign-in activities from the past seven days where the resource being accessed was the Partner Center API and the sign-in activity was not challenged for multi-factor authentication.
Expand Down
6 changes: 3 additions & 3 deletions src/PowerShell/Authenticators/InteractiveUserAuthenticator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ public override async Task<AuthenticationResult> AuthenticateAsync(Authenticatio
}
catch (Exception ex)
{
promptAction($"Port {port} is taken with exception '{ex.Message}'; trying to connect to the next port.");
Console.WriteLine($"Port {port} is taken with exception '{ex.Message}'; trying to connect to the next port.");
listener?.Stop();
}
}
Expand All @@ -60,7 +60,7 @@ public override async Task<AuthenticationResult> AuthenticateAsync(Authenticatio

if (app is IConfidentialClientApplication)
{
ICustomWebUi customWebUi = new DefaultOsBrowserWebUi(interactiveParameters.Message, promptAction);
ICustomWebUi customWebUi = new DefaultOsBrowserWebUi(interactiveParameters.Message);

Uri authCodeUrl = await customWebUi.AcquireAuthorizationCodeAsync(
await app.AsConfidentialClient().GetAuthorizationRequestUrl(parameters.Scopes).ExecuteAsync(cancellationToken).ConfigureAwait(false),
Expand All @@ -76,7 +76,7 @@ await app.AsConfidentialClient().GetAuthorizationRequestUrl(parameters.Scopes).E
else
{
authResult = await app.AsPublicClient().AcquireTokenInteractive(parameters.Scopes)
.WithCustomWebUi(new DefaultOsBrowserWebUi(interactiveParameters.Message, promptAction))
.WithCustomWebUi(new DefaultOsBrowserWebUi(interactiveParameters.Message))
.WithPrompt(Prompt.ForceLogin)
.ExecuteAsync(cancellationToken).ConfigureAwait(false);
}
Expand Down
1 change: 1 addition & 0 deletions src/PowerShell/Commands/ConnectPartnerCenter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,7 @@ protected override void ProcessRecord()
new[] { account.GetProperty(PartnerAccountPropertyType.Scope) },
Message,
WriteWarning,
WriteDebug,
CancellationToken);

PartnerSession.Instance.Context = new PartnerContext
Expand Down
2 changes: 1 addition & 1 deletion src/PowerShell/Commands/GetPartnerCustomer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ public override void ExecuteCmdlet()
FieldFilterOperation.StartsWith,
Domain))).ConfigureAwait(false).GetAwaiter().GetResult();
}
else
else
{
seekCustomers = Partner.Customers.GetAsync().ConfigureAwait(false).GetAwaiter().GetResult();
}
Expand Down
40 changes: 32 additions & 8 deletions src/PowerShell/Commands/GetPartnerUser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,27 +8,51 @@ namespace Microsoft.Store.PartnerCenter.PowerShell.Commands
using Graph;
using Models.Authentication;

/// <summary>
/// Command that gets partner level user accounts.
/// </summary>
[Cmdlet(VerbsCommon.Get, "PartnerUser"), OutputType(typeof(User))]
public class GetPartnerUser : PartnerCmdlet
{
/// <summary>
/// Gets or sets the user identifier.
/// </summary>
[Parameter(HelpMessage = "The identifier for the user.", Mandatory = false)]
public string UserId { get; set; }

/// <summary>
/// Gets or sets the user principal name for the user.
/// </summary>
[Parameter(HelpMessage = "The user principal name for the user.", Mandatory = false)]
[Alias("UPN")]
public string UserPrincipalName { get; set; }

/// <summary>
/// Executes the operations associated with the cmdlet.
/// </summary>
public override void ExecuteCmdlet()
{
IGraphServiceClient client = PartnerSession.Instance.ClientFactory.CreateGraphServiceClient();
IGraphServiceUsersCollectionPage data = client.Users.Request().GetAsync().ConfigureAwait(false).GetAwaiter().GetResult();
List<User> users = new List<User>();

users.AddRange(data.CurrentPage);

while (data.NextPageRequest != null)
if (string.IsNullOrEmpty(UserId) && string.IsNullOrEmpty(UserPrincipalName))
{
data = data.NextPageRequest.GetAsync().ConfigureAwait(false).GetAwaiter().GetResult();
users.AddRange(data.CurrentPage);
IGraphServiceUsersCollectionPage data = client.Users.Request().GetAsync().ConfigureAwait(false).GetAwaiter().GetResult();
List<User> users = new List<User>(data.CurrentPage);

while (data.NextPageRequest != null)
{
data = data.NextPageRequest.GetAsync().ConfigureAwait(false).GetAwaiter().GetResult();
users.AddRange(data.CurrentPage);
}

WriteObject(users, true);
}
else
{
User user = client.Users[string.IsNullOrEmpty(UserPrincipalName) ? UserId : UserPrincipalName].Request().GetAsync().ConfigureAwait(false).GetAwaiter().GetResult();

WriteObject(users, true);
WriteObject(user);
}
}
}
}
1 change: 1 addition & 0 deletions src/PowerShell/Commands/NewPartnerAccessToken.cs
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,7 @@ protected override void ProcessRecord()
Scopes,
Message,
WriteWarning,
WriteDebug,
CancellationToken);

byte[] cacheData = SharedTokenCacheClientFactory.GetTokenCache(ApplicationId).SerializeMsalV3();
Expand Down
1 change: 1 addition & 0 deletions src/PowerShell/Commands/TestPartnerSecurityRequirement.cs
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ protected override void ProcessRecord()
new[] { $"{environment.PartnerCenterEndpoint}/user_impersonation" },
Message,
WriteWarning,
WriteDebug,
CancellationToken);


Expand Down
43 changes: 15 additions & 28 deletions src/PowerShell/Factories/AuthenticationFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,45 +19,32 @@ internal class AuthenticationFactory : IAuthenticationFactory
{
internal IAuthenticatorBuilder Builder => new DefaultAuthenticatorBuilder();

public AuthenticationResult Authenticate(PartnerAccount account, PartnerEnvironment environment, IEnumerable<string> scopes, string message = null, Action<string> promptAction = null, CancellationToken cancellationToken = default)
public AuthenticationResult Authenticate(PartnerAccount account, PartnerEnvironment environment, IEnumerable<string> scopes, string message = null, Action<string> promptAction = null, Action<string> debugAction = null, CancellationToken cancellationToken = default)
{
AuthenticationResult authResult = null;
IAuthenticator processAuthenticator = Builder.Authenticator;
int retries = 5;

while (retries-- > 0)
while (processAuthenticator != null && processAuthenticator.TryAuthenticate(GetAuthenticationParameters(account, environment, scopes, message), out Task<AuthenticationResult> result, promptAction, cancellationToken))
{
try
authResult = result.ConfigureAwait(true).GetAwaiter().GetResult();

if (authResult != null)
{
while (processAuthenticator != null && processAuthenticator.TryAuthenticate(GetAuthenticationParameters(account, environment, scopes, message), out Task<AuthenticationResult> result, promptAction, cancellationToken))
if (authResult.Account?.HomeAccountId != null)
{
authResult = result.ConfigureAwait(true).GetAwaiter().GetResult();

if (authResult != null)
{
if (authResult.Account?.HomeAccountId != null)
{
account.Identifier = authResult.Account.HomeAccountId.Identifier;
account.ObjectId = authResult.Account.HomeAccountId.ObjectId;
}

if (account.Tenant.Equals("common", StringComparison.InvariantCultureIgnoreCase) && !string.IsNullOrEmpty(authResult.TenantId))
{
account.Tenant = authResult.TenantId;
}

break;
}
account.Identifier = authResult.Account.HomeAccountId.Identifier;
account.ObjectId = authResult.Account.HomeAccountId.ObjectId;
}

processAuthenticator = processAuthenticator.Next;
if (account.Tenant.Equals("common", StringComparison.InvariantCultureIgnoreCase) && !string.IsNullOrEmpty(authResult.TenantId))
{
account.Tenant = authResult.TenantId;
}
}
catch (InvalidOperationException)
{
continue;

break;
}

break;
processAuthenticator = processAuthenticator.Next;
}

return authResult ?? null;
Expand Down
2 changes: 1 addition & 1 deletion src/PowerShell/Factories/IAuthenticationFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,6 @@ public interface IAuthenticationFactory
/// Acquires the security token from the authority.
/// </summary>
/// <returns>The result from the authentication request.</returns>
AuthenticationResult Authenticate(PartnerAccount account, PartnerEnvironment environment, IEnumerable<string> scopes, string message = null, Action<string> promptAction = null, CancellationToken cancellationToken = default);
AuthenticationResult Authenticate(PartnerAccount account, PartnerEnvironment environment, IEnumerable<string> scopes, string message = null, Action<string> promptAction = null, Action<string> debugAction = null, CancellationToken cancellationToken = default);
}
}
16 changes: 4 additions & 12 deletions src/PowerShell/Network/DefaultOsBrowserWebUi.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,6 @@ internal class DefaultOsBrowserWebUi : ICustomWebUi
</body>
</html>";

/// <summary>
/// The action used to prompt for interaction.
/// </summary>
private readonly Action<string> promptAction;

/// <summary>
/// The message written to the console.
/// </summary>
Expand All @@ -55,14 +50,11 @@ internal class DefaultOsBrowserWebUi : ICustomWebUi
/// Initializes a new instance of the <see cref="DefaultOsBrowserWebUi" /> class.
/// </summary>
/// <param name="message">The message written to the console.</param>
/// <param name="promptAction">The action used to prompt for interaction.</param>
public DefaultOsBrowserWebUi(string message, Action<string> promptAction)
public DefaultOsBrowserWebUi(string message)
{
message.AssertNotEmpty(nameof(message));
promptAction.AssertNotNull(nameof(promptAction));

this.message = message;
this.promptAction = promptAction;
}

/// <summary>
Expand All @@ -74,14 +66,14 @@ public DefaultOsBrowserWebUi(string message, Action<string> promptAction)
/// <returns>The URI returned back from the STS authorization endpoint. This URI contains a code=CODE parameter that MSAL.NET will extract and redeem.</returns>
public async Task<Uri> AcquireAuthorizationCodeAsync(Uri authorizationUri, Uri redirectUri, CancellationToken cancellationToken)
{
promptAction("Attempting to launch a browser for authorization code login.");
Console.WriteLine("Attempting to launch a browser for authorization code login.");

if (!OpenBrowser(authorizationUri.ToString()))
{
promptAction("Unable to launch a browser for authorization code login. Reverting to device code login.");
Console.WriteLine("Unable to launch a browser for authorization code login. Reverting to device code login.");
}

promptAction(message);
Console.WriteLine(message);

using (SingleMessageTcpListener listener = new SingleMessageTcpListener(redirectUri.Port))
{
Expand Down
2 changes: 2 additions & 0 deletions src/PowerShell/Network/SingleMessageTcpListener.cs
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,9 @@ public void Dispose()
protected virtual void Dispose(bool disposing)
{
if (disposed)
{
return;
}

if (disposing)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ public class MockAuthenticationFactory : IAuthenticationFactory
/// Acquires the security token from the authority.
/// </summary>
/// <returns>The result from the authentication request.</returns>
public AuthenticationResult Authenticate(PartnerAccount account, PartnerEnvironment environment, IEnumerable<string> scopes, string message, Action<string> promptAction = null, CancellationToken cancellationToken = default)
public AuthenticationResult Authenticate(PartnerAccount account, PartnerEnvironment environment, IEnumerable<string> scopes, string message, Action<string> promptAction = null, Action<string> debugAction = null, CancellationToken cancellationToken = default)
{
return new AuthenticationResult(
"STUB_TOKEN",
Expand Down

0 comments on commit c51d13f

Please sign in to comment.