Esempio n. 1
0
        public async Task AddAppRoleAssignmentAsync(
            ServicePrincipal servicePrincipal,
            AppRoleAssignment appRoleAssignment,
            CancellationToken cancellationToken = default
            )
        {
            const string ROLE_ASSIGNMENT_FORMATTER = "https://graph.microsoft.com/beta/servicePrincipals/{0}/appRoleAssignments";
            var          url = string.Format(ROLE_ASSIGNMENT_FORMATTER, servicePrincipal.Id);

            using (var client = new HttpClient()) {
                client.DefaultRequestHeaders.Authorization = await _microsoftGraphTokenProvider
                                                             .GetAuthenticationHeaderAsync(cancellationToken);

                var content = new StringContent(
                    Newtonsoft.Json.JsonConvert.SerializeObject(appRoleAssignment),
                    System.Text.Encoding.UTF8,
                    "application/json"
                    );

                content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
                var response = await client.PostAsync(url, content);

                if (response.IsSuccessStatusCode)
                {
                    return;
                }
                else
                {
                    throw new HttpRequestException(response.ReasonPhrase);
                }
            }
        }
Esempio n. 2
0
        public async Task <bool> PostRolAsync(string oid, Guid rolguid)
        {
            HttpClient client = new HttpClient();
            var        token  = await AcquireAsync();

            client.SetBearerToken(token);
            var role = $"https://graph.microsoft.com/v1.0/users/{oid}/appRoleAssignments";

            var rol = new AppRoleAssignment();

            rol.AppRoleId   = rolguid;
            rol.ResourceId  = new Guid("a3c988aa-a379-42af-97de-571305d7c572");
            rol.PrincipalId = new Guid(oid);

            var control   = JsonConvert.SerializeObject(rol);
            var bufferrol = System.Text.Encoding.UTF8.GetBytes(control);
            var r         = new ByteArrayContent(bufferrol);

            r.Headers.ContentType = new MediaTypeHeaderValue("application/json");

            var response = await client.PostAsync(new Uri(role), r);

            if (response.IsSuccessStatusCode)
            {
                return(true);
            }

            return(false);
        }
Esempio n. 3
0
        public async Task <bool> AssignRole(User user, AppRole role)
        {
            try
            {
                ActiveDirectoryClient client            = AuthenticationHelper.GetActiveDirectoryClient();
                AppRoleAssignment     appRoleAssignment = new AppRoleAssignment();

                /*
                 * id = approle id
                 * principle id = user objectid
                 * resource id = service principle objectid
                 */
                appRoleAssignment.Id          = role.Id;
                appRoleAssignment.PrincipalId = Guid.Parse(user.ObjectId);
                appRoleAssignment.ResourceId  = Guid.Parse(LBAS.Web.Utils.Constants.ClientId);
                IList <AppRoleAssignment> appRoleAssignments = new List <AppRoleAssignment>()
                {
                    appRoleAssignment
                };
                user.AppRoleAssignments = appRoleAssignments;
                await user.UpdateAsync();

                return(true);
            }
            catch (Exception)
            {
                throw;
            }
        }
        public async Task Post([FromBody] AssignRole value)
        {
            _logger.LogInformation("Check Token from logged user.");
            await AuthenticationHelper.CheckToken(User.Identity as ClaimsIdentity, _azureAdOptions);

            _logger.LogInformation("Try to add Admin role for me.");

            ActiveDirectoryClient client = AuthenticationHelper.GetActiveDirectoryClient(_azureAdOptions.TenantId);

            IAppRoleAssignment appRoleAssignment = new AppRoleAssignment()
            {
                CreationTimestamp = DateTime.Now,
                Id = Guid.Parse(value.RoleId),
                PrincipalDisplayName = value.PrincipalDisplayName,
                PrincipalId          = Guid.Parse(value.PrincipalId),
                PrincipalType        = value.PrincipalType,
                ResourceDisplayName  = "GrathWebAPITest",
                ResourceId           = Guid.Parse("bfa79360-7eac-4bc3-81f2-459ea1ff9f3f")
            };

            if (value.PrincipalType == "Group")
            {
                await client.Groups.GetByObjectId(value.PrincipalId).AppRoleAssignments.AddAppRoleAssignmentAsync(appRoleAssignment);
            }
            else
            {
                await client.Users.GetByObjectId(value.PrincipalId).AppRoleAssignments.AddAppRoleAssignmentAsync(appRoleAssignment);
            }
        }
Esempio n. 5
0
        static async Task AddAdminRoleAssignmentToServer(IServicePrincipal serverApplication)
        {
            // Get the admin role,
            var role = serverApplication.AppRoles.First(r => r.Value == "admin_signservice");

            var ara = new AppRoleAssignment
            {
                PrincipalId   = Guid.Parse(authResult.UserInfo.UniqueId),
                PrincipalType = "User",
                Id            = role.Id,
                ResourceId    = Guid.Parse(serverApplication.ObjectId)
            };

            await graphClient.Users.GetByObjectId(authResult.UserInfo.UniqueId).AppRoleAssignments.AddAppRoleAssignmentAsync(ara);
        }
        public async Task <AppRoleAssignment> AddServicePrincipalAppRoleAssignmentAsync(
            ServicePrincipal servicePrincipal,
            AppRoleAssignment appRoleAssignmentDefinition,
            CancellationToken cancellationToken = default
            )
        {
            var appRoleAssignment = await _graphServiceClient
                                    .ServicePrincipals[servicePrincipal.Id]
                                    .AppRoleAssignments
                                    .Request()
                                    .AddAsync(
                appRoleAssignmentDefinition,
                cancellationToken
                );

            return(appRoleAssignment);
        }
        /// <summary>
        /// Create new navigation property to appRoleAssignments for users
        /// <param name="body"></param>
        /// <param name="requestConfiguration">Configuration for the request such as headers, query parameters, and middleware options.</param>
        /// </summary>
        public RequestInformation CreatePostRequestInformation(AppRoleAssignment body, Action <AppRoleAssignmentsRequestBuilderPostRequestConfiguration> requestConfiguration = default)
        {
            _ = body ?? throw new ArgumentNullException(nameof(body));
            var requestInfo = new RequestInformation {
                HttpMethod     = Method.POST,
                UrlTemplate    = UrlTemplate,
                PathParameters = PathParameters,
            };

            requestInfo.SetContentFromParsable(RequestAdapter, "application/json", body);
            if (requestConfiguration != null)
            {
                var requestConfig = new AppRoleAssignmentsRequestBuilderPostRequestConfiguration();
                requestConfiguration.Invoke(requestConfig);
                requestInfo.AddRequestOptions(requestConfig.Options);
                requestInfo.AddHeaders(requestConfig.Headers);
            }
            return(requestInfo);
        }
Esempio n. 8
0
        public async Task <AppRoleAssignment> AssignAppRole(Guid targetPrincipalId, Guid resourceId, Guid appRoleId)
        {
            var resource = await GetResourceUserCanAdminister(resourceId);

            if (resource == null)
            {
                return(null);
            }

            var principal = await _graphClient.Users[targetPrincipalId.ToString()]
                            .Request()
                            .Select(_options.UserFieldSelection)
                            .GetAsync();

            // todo: wrap this in ServiceResult or similar
            if (!principal.AdditionalData.Any())
            {
                return(null);
            }
            bool userOrgMatch = false;

            if (principal.AdditionalData.ContainsKey(_options.OrgIdExtensionName))
            {
                var orgData = principal.AdditionalData[_options.OrgIdExtensionName].ToString();
                userOrgMatch = string.Equals(orgData, _orgId, StringComparison.OrdinalIgnoreCase);
            }

            if (userOrgMatch) // assign only if match
            {
                var assignment = new AppRoleAssignment()
                {
                    ResourceId  = resource.ResourceId,
                    PrincipalId = Guid.Parse(principal.Id),
                    AppRoleId   = appRoleId
                };
                await _graphClient.ServicePrincipals[resource.ResourceId.ToString()].AppRoleAssignedTo.Request().AddAsync(assignment);
                return(assignment);
            }
            return(null);
        }
Esempio n. 9
0
        public async Task <Application> RegisterServiceApplicationAsync(
            string servicesApplicationName,
            IEnumerable <string> tags           = null,
            CancellationToken cancellationToken = default
            )
        {
            tags = tags ?? new List <string>();

            // Setup AppRoles for service application
            var serviceApplicationAppRoles = new List <AppRole>();

            var serviceApplicationApproverRoleIdGuid = Guid.NewGuid();

            serviceApplicationAppRoles.Add(new AppRole {
                DisplayName        = "Approver",
                Value              = "Sign",
                Description        = "Approvers have the ability to issue certificates.",
                AllowedMemberTypes = new List <string> {
                    "User"
                },
                Id = serviceApplicationApproverRoleIdGuid
            });

            var serviceApplicationWriterRoleIdGuid = Guid.NewGuid();

            serviceApplicationAppRoles.Add(new AppRole {
                DisplayName        = "Writer",
                Value              = "Write",
                Description        = "Writers Have the ability to change entities.",
                AllowedMemberTypes = new List <string> {
                    "User"
                },
                Id = serviceApplicationWriterRoleIdGuid
            });

            var serviceApplicationAdministratorRoleIdGuid = Guid.NewGuid();

            serviceApplicationAppRoles.Add(new AppRole {
                DisplayName        = "Administrator",
                Value              = "Admin",
                Description        = "Admins can access advanced features.",
                AllowedMemberTypes = new List <string> {
                    "User"
                },
                Id = serviceApplicationAdministratorRoleIdGuid
            });

            // Setup RequiredResourceAccess for service application

            //// This flow is not supported yet.
            //var keyVaultUserImpersonationRequiredResourceAccess =
            //    await GetRequiredResourceAccessByDisplayNameAsync(
            //        "Azure Key Vault",
            //        new List<string> { "user_impersonation" },
            //        cancellationToken
            //    );

            var keyVaultUserImpersonationRequiredResourceAccess = new RequiredResourceAccess {
                ResourceAppId  = AzureAppsConstants.AzureKeyVault.AppId,
                ResourceAccess = new List <ResourceAccess> {
                    new ResourceAccess {
                        Id   = AzureAppsConstants.AzureKeyVault.ResourceAccess["user_impersonation"],
                        Type = "Scope"
                    }
                }
            };

            //// This flow is not supported yet.
            //var microsoftGraphUserReadRequiredResourceAccess =
            //    await GetRequiredResourceAccessByDisplayNameAsync(
            //        "Microsoft Graph",
            //        new List<string> { "User.Read" },
            //        cancellationToken
            //    );

            var microsoftGraphUserReadRequiredResourceAccess = new RequiredResourceAccess {
                ResourceAppId  = AzureAppsConstants.MicrosoftGraph.AppId,
                ResourceAccess = new List <ResourceAccess> {
                    new ResourceAccess {
                        Id   = AzureAppsConstants.MicrosoftGraph.ResourceAccess["User.Read"],
                        Type = "Scope"
                    }
                }
            };

            var serviceApplicationRequiredResourceAccess = new List <RequiredResourceAccess>()
            {
                keyVaultUserImpersonationRequiredResourceAccess,
                microsoftGraphUserReadRequiredResourceAccess
            };

            // Add OAuth2Permissions
            var oauth2Permissions = new List <PermissionScope> {
                new PermissionScope {
                    AdminConsentDescription = $"Allow the app to access {servicesApplicationName} on behalf of the signed-in user.",
                    AdminConsentDisplayName = $"Access {servicesApplicationName}",
                    Id        = Guid.NewGuid(),
                    IsEnabled = true,
                    Type      = "User",
                    UserConsentDescription = $"Allow the application to access {servicesApplicationName} on your behalf.",
                    UserConsentDisplayName = $"Access {servicesApplicationName}",
                    Value = "user_impersonation"
                }
            };

            var serviceApplicationApiApplication = new ApiApplication {
                Oauth2PermissionScopes = oauth2Permissions
            };

            var serviceApplicationWebApplication = new WebApplication {
                ImplicitGrantSettings = new ImplicitGrantSettings {
                    EnableIdTokenIssuance = true
                }
            };

            var serviceApplicationIdentifierUri = $"https://{_tenantGuid.ToString()}/{servicesApplicationName}";

            var serviceApplicationRequest = new Application {
                DisplayName            = servicesApplicationName,
                IsFallbackPublicClient = false,
                IdentifierUris         = new List <string> {
                    serviceApplicationIdentifierUri
                },
                Tags                   = tags,
                SignInAudience         = "AzureADMyOrg",
                AppRoles               = serviceApplicationAppRoles,
                RequiredResourceAccess = serviceApplicationRequiredResourceAccess,
                Api = serviceApplicationApiApplication,
                Web = serviceApplicationWebApplication,
                PasswordCredentials = new List <PasswordCredential> {
                }
            };

            var serviceApplication = await _graphServiceClient
                                     .Applications
                                     .Request()
                                     .AddAsync(serviceApplicationRequest, cancellationToken);

            // Add Service Key PasswordCredential
            var serviceKeyName = "Service Key";

            var serviceApplicationServiceKeyPasswordCredentialDefinition = new PasswordCredential {
                StartDateTime       = DateTimeOffset.UtcNow,
                EndDateTime         = DateTimeOffset.UtcNow.AddYears(2),
                CustomKeyIdentifier = ToBase64Bytes(serviceKeyName),
                DisplayName         = serviceKeyName
            };

            await _graphServiceClient
            .Applications[serviceApplication.Id]
            .AddPassword(serviceApplicationServiceKeyPasswordCredentialDefinition)
            .Request()
            .PostAsync(cancellationToken);

            // We need to create ServicePrincipal for this application.
            var serviceApplicationSP = await CreateServicePrincipalAsync(
                serviceApplication,
                tags,
                cancellationToken
                );

            var me = Me(cancellationToken);

            var approverAppRoleAssignmentRequest = new AppRoleAssignment {
                //PrincipalDisplayName = "",
                PrincipalType       = "User",
                PrincipalId         = new Guid(me.Id),
                ResourceId          = new Guid(serviceApplicationSP.Id),
                ResourceDisplayName = "Approver",
                Id        = serviceApplicationApproverRoleIdGuid.ToString(),
                AppRoleId = serviceApplicationApproverRoleIdGuid
            };

            var writerAppRoleAssignmentRequest = new AppRoleAssignment {
                //PrincipalDisplayName = "",
                PrincipalType       = "User",
                PrincipalId         = new Guid(me.Id),
                ResourceId          = new Guid(serviceApplicationSP.Id),
                ResourceDisplayName = "Writer",
                Id        = serviceApplicationWriterRoleIdGuid.ToString(),
                AppRoleId = serviceApplicationWriterRoleIdGuid
            };

            var adminAppRoleAssignmentRequest = new AppRoleAssignment {
                //PrincipalDisplayName = "",
                PrincipalType       = "User",
                PrincipalId         = new Guid(me.Id),
                ResourceId          = new Guid(serviceApplicationSP.Id),
                ResourceDisplayName = "Admin",
                Id        = serviceApplicationAdministratorRoleIdGuid.ToString(),
                AppRoleId = serviceApplicationAdministratorRoleIdGuid
            };

            //// ToDo: Use AddAsync() instead of the workaround bellow
            //// when AddAsync() is added.
            //var appRoleAssignment = _graphServiceClient
            //    .ServicePrincipals[serviceApplicationSP.Id]
            //    .AppRoleAssignments
            //    .Request()
            //    .AddAsync(appRoleAssignmentRequest);

            // Workaround using HttpClient
            await AddAppRoleAssignmentAsync(serviceApplicationSP, approverAppRoleAssignmentRequest);
            await AddAppRoleAssignmentAsync(serviceApplicationSP, writerAppRoleAssignmentRequest);
            await AddAppRoleAssignmentAsync(serviceApplicationSP, adminAppRoleAssignmentRequest);

            return(serviceApplication);
        }
Esempio n. 10
0
 public Task <AppRoleAssignment> AssignAppRole(AppRoleAssignment request)
 {
     throw new NotImplementedException();
 }
        /// <summary>
        ///
        /// </summary>
        /// <param name="azureGraphclient"></param>
        /// <param name="model"></param>
        /// <returns>Return values are status,message, user-object-id, application-role-id, application-service-principal-id</returns>
        public async Task <Tuple <bool, string, string, string, string> > AddApplicationRoleToUser(ActiveDirectoryClient azureGraphclient, string AppName, string UserEmailAddress,
                                                                                                   string AppRoleName)
        {
            Guid userObjectID = Guid.Empty, appobjectid = Guid.Empty, approleid = Guid.Empty, srvpr = Guid.Empty;

            bool   ActionStatus = false;
            string message      = string.Empty;

            if (azureGraphclient == null || string.IsNullOrEmpty(AppName) || string.IsNullOrEmpty(UserEmailAddress) || string.IsNullOrEmpty(AppRoleName))
            {
                return(new Tuple <bool, string, string, string, string>(ActionStatus, "Invalid input", null, null, null));
            }
            else
            {
                try
                {
                    AppRoleAssignment assignment = new AppRoleAssignment();
                    assignment.CreationTimestamp = System.DateTime.Now;

                    var _usersFiltered = azureGraphclient.Users.Where(a => a.Mail.Equals(UserEmailAddress, StringComparison.InvariantCultureIgnoreCase) ||
                                                                      a.UserPrincipalName.Equals(UserEmailAddress, StringComparison.InvariantCultureIgnoreCase)).ExecuteAsync().Result;
                    if (_usersFiltered != null)
                    {
                        userObjectID = Guid.Parse(_usersFiltered.CurrentPage.Select(a => a.ObjectId).SingleOrDefault().ToString());

                        var application = azureGraphclient.Applications.Where(a => a.DisplayName == AppName).ExecuteAsync().Result;
                        if (application != null)
                        {
                            var approle = application.CurrentPage.FirstOrDefault().AppRoles.Where(a => a.DisplayName == AppRoleName).FirstOrDefault();

                            if (approle != null)
                            {
                                approleid = Guid.Parse(approle.Id.ToString());

                                srvpr = Guid.Parse(azureGraphclient.ServicePrincipals.Where(a => a.DisplayName == AppName).ExecuteAsync().Result.CurrentPage.FirstOrDefault().ObjectId);

                                //check if assignment is already made
                                var cc = azureGraphclient.Users[userObjectID.ToString()].AppRoleAssignments.ExecuteAsync().Result;
                                var approlesassigns = await AzureADExtensions.EnumerateAllAsync(cc);

                                var filtered = approlesassigns.Where(a => a.Id == approleid && a.PrincipalType == "User").FirstOrDefault();

                                if (filtered == null)
                                {
                                    assignment.PrincipalId   = userObjectID;
                                    assignment.PrincipalType = "User";
                                    assignment.ResourceId    = srvpr;
                                    assignment.Id            = approleid;

                                    await azureGraphclient.Users[userObjectID.ToString()].AppRoleAssignments.AddAppRoleAssignmentAsync(assignment);

                                    ActionStatus = true;
                                    message      = "User successfully associated with application role";
                                }
                                else
                                {
                                    message = "user already associated with application role";
                                }
                            }
                            else
                            {
                                message = "Invalid application role";
                            }
                        }
                        else
                        {
                            message = "Invalid application";
                        }
                    }
                    else
                    {
                        message = "Invalid user";
                    }
                }
                catch (Exception ex)
                {
                    message = ex.Message + (ex.InnerException != null ? Environment.NewLine + ex.InnerException.Message : "");
                }
            }

            return(new Tuple <bool, string, string, string, string>(ActionStatus, message, userObjectID.ToString(), approleid.ToString(), srvpr.ToString()));
        }
Esempio n. 12
0
 public async Task <AppRoleAssignment> AssignAppRole(AppRoleAssignment request)
 {
     return(await AssignAppRole(request.PrincipalId.Value, request.ResourceId.Value, request.AppRoleId.Value));
 }
Esempio n. 13
0
        private async Task <DeviceIdentity> CreateDeviceIdentityAsync(IGraphServiceClient graphService, string displayName, string description)
        {
            // Get information about the customer tenant.
            var currentOrganization = (await graphService.Organization.Request().GetAsync()).Single();
            var currentTenantId     = currentOrganization.Id;

            // Register an application representing the device.
            var deviceIdentityApplication = new Application
            {
                DisplayName            = displayName,
                Description            = description,
                SignInAudience         = "AzureADMyOrg", // Limit exposure of this app registration to the customer tenant
                RequiredResourceAccess = new[]
                {
                    // Specify which permissions the device will ultimately need; in this case we use certain Graph API permissions to prove the point but this could be any Application Permission on any API.
                    new RequiredResourceAccess
                    {
                        ResourceAppId  = "00000003-0000-0000-c000-000000000000", // Request that the device can access the Microsoft Graph API
                        ResourceAccess = new []
                        {
                            new ResourceAccess {
                                Type = "Role", Id = new Guid("798ee544-9d2d-430c-a058-570e29e34338")
                            },                                                                                           // Request an Application Permission (i.e. "Role") for the permission "Calendars.Read"
                            new ResourceAccess {
                                Type = "Role", Id = new Guid("df021288-bdef-4463-88db-98f22de89214")
                            },                                                                                           // Request an Application Permission (i.e. "Role") for the permission "User.Read.All"
                        }
                    }
                }
            };

            deviceIdentityApplication = await graphService.Applications.Request().AddAsync(deviceIdentityApplication);

            this.logger.LogInformation($"Application created for device \"{deviceIdentityApplication.DisplayName}\": App ID = \"{deviceIdentityApplication.AppId}\"");
            await Task.Delay(1000); // Safety buffer

            // Create a client credential for the device.
            // https://docs.microsoft.com/en-us/graph/api/application-addpassword?view=graph-rest-1.0&tabs=http
            var clientCredential = await graphService.Applications[deviceIdentityApplication.Id].AddPassword(new PasswordCredential()).Request().PostAsync();

            this.logger.LogInformation($"Credential created for device: Client Secret = \"{clientCredential.SecretText}\"");
            await Task.Delay(1000); // Safety buffer

            // Store the client secret in the application so we can easily retrieve it later.
            // DO NOT EVER DO THIS IN PRODUCTION SCENARIOS OF COURSE!
            // This is simply to more easily demonstrate that the device can now effectively call the target API.
            // In a real world scenario, this step would handled e.g. through an IoT Hub where the actual identity
            // information including secrets are securely transmitted to the actual device.
            // Also add the Tenant Id to make it simpler to retrieve this when trying to use the device identity.
            var deviceIdentityApplicationPatch = new Application {
                Notes = $"{nameof(DeviceIdentity.TenantId)}={currentTenantId};{nameof(DeviceIdentity.ClientSecret)}={clientCredential.SecretText}"
            };
            await graphService.Applications[deviceIdentityApplication.Id].Request().UpdateAsync(deviceIdentityApplicationPatch);

            // Create the Service Principal for the device's app registration, as this will ultimately receive the required permissions (App Roles).
            var deviceIdentityServicePrincipal = await graphService.ServicePrincipals.Request().AddAsync(new ServicePrincipal {
                AppId = deviceIdentityApplication.AppId
            });

            this.logger.LogInformation($"Service Principal created for device: ID = \"{deviceIdentityApplication.Id}\"");
            await Task.Delay(1000); // Safety buffer

            // Perform an admin consent (i.e. add the App Role Assignment) using the customer tenant admin's privileges for each requested resource access in the device app registration.
            foreach (var requiredResourceAccess in deviceIdentityApplication.RequiredResourceAccess)
            {
                // Look up the Service Principal of the Resource AppId in the target tenant.
                var targetResourceServicePrincipal = (await graphService.ServicePrincipals.Request().Filter($"appId eq '{requiredResourceAccess.ResourceAppId}'").GetAsync()).Single();

                // Create the App Role Assignment for each requested resource.
                foreach (var appRole in requiredResourceAccess.ResourceAccess)
                {
                    var deviceAppRoleAssignment = new AppRoleAssignment
                    {
                        AppRoleId   = appRole.Id,
                        PrincipalId = new Guid(deviceIdentityServicePrincipal.Id),
                        ResourceId  = new Guid(targetResourceServicePrincipal.Id)
                    };
                    // https://docs.microsoft.com/en-us/graph/api/serviceprincipal-post-approleassignments?view=graph-rest-1.0&tabs=http
                    deviceAppRoleAssignment = await graphService.ServicePrincipals[deviceIdentityServicePrincipal.Id].AppRoleAssignments.Request().AddAsync(deviceAppRoleAssignment);
                }
            }

            return(new DeviceIdentity
            {
                DisplayName = deviceIdentityApplication.DisplayName,
                Id = deviceIdentityApplication.Id,
                AppId = deviceIdentityApplication.AppId,
                TenantId = currentTenantId,
                ClientSecret = clientCredential.SecretText,
                CreatedDateTime = deviceIdentityApplication.CreatedDateTime
            });
        }
Esempio n. 14
0
        private static void Main()
        {
            // record start DateTime of execution
            string currentDateTime = DateTime.Now.ToUniversalTime().ToString();

            #region Setup Active Directory Client

            //*********************************************************************
            // setup Active Directory Client
            //*********************************************************************
            ActiveDirectoryClient activeDirectoryClient;
            try
            {
                activeDirectoryClient = AuthenticationHelper.GetActiveDirectoryClientAsApplication();
            }
            catch (AuthenticationException ex)
            {
                Console.ForegroundColor = ConsoleColor.Red;
                Console.WriteLine("Acquiring a token failed with the following error: {0}", ex.Message);
                if (ex.InnerException != null)
                {
                    //You should implement retry and back-off logic per the guidance given here:http://msdn.microsoft.com/en-us/library/dn168916.aspx
                    //InnerException Message will contain the HTTP error status codes mentioned in the link above
                    Console.WriteLine("Error detail: {0}", ex.InnerException.Message);
                }
                Console.ResetColor();
                Console.ReadKey();
                return;
            }

            #endregion

            #region TenantDetails

            //*********************************************************************
            // Get Tenant Details
            // Note: update the string TenantId with your TenantId.
            // This can be retrieved from the login Federation Metadata end point:
            // https://login.windows.net/GraphDir1.onmicrosoft.com/FederationMetadata/2007-06/FederationMetadata.xml
            //  Replace "GraphDir1.onMicrosoft.com" with any domain owned by your organization
            // The returned value from the first xml node "EntityDescriptor", will have a STS URL
            // containing your TenantId e.g. "https://sts.windows.net/4fd2b2f2-ea27-4fe5-a8f3-7b1a7c975f34/" is returned for GraphDir1.onMicrosoft.com
            //*********************************************************************
            VerifiedDomain initialDomain = new VerifiedDomain();
            VerifiedDomain defaultDomain = new VerifiedDomain();
            ITenantDetail  tenant        = null;
            Console.WriteLine("\n Retrieving Tenant Details");
            try
            {
                List <ITenantDetail> tenantsList = activeDirectoryClient.TenantDetails
                                                   .Where(tenantDetail => tenantDetail.ObjectId.Equals(Constants.TenantId))
                                                   .ExecuteAsync().Result.CurrentPage.ToList();
                if (tenantsList.Count > 0)
                {
                    tenant = tenantsList.First();
                }
            }
            catch (Exception e)
            {
                Console.WriteLine("\nError getting TenantDetails {0} {1}", e.Message,
                                  e.InnerException != null ? e.InnerException.Message : "");
            }
            if (tenant == null)
            {
                Console.WriteLine("Tenant not found");
            }
            else
            {
                TenantDetail tenantDetail = (TenantDetail)tenant;
                Console.WriteLine("Tenant Display Name: " + tenantDetail.DisplayName);

                // Get the Tenant's Verified Domains
                initialDomain = tenantDetail.VerifiedDomains.First(x => x.Initial.HasValue && x.Initial.Value);
                Console.WriteLine("Initial Domain Name: " + initialDomain.Name);
                defaultDomain = tenantDetail.VerifiedDomains.First(x => [email protected] && [email protected]);
                Console.WriteLine("Default Domain Name: " + defaultDomain.Name);

                // Get Tenant's Tech Contacts
                foreach (string techContact in tenantDetail.TechnicalNotificationMails)
                {
                    Console.WriteLine("Tenant Tech Contact: " + techContact);
                }
            }

            #endregion

            #region Create a new User

            IUser newUser = new User();
            if (defaultDomain.Name != null)
            {
                newUser.DisplayName       = "Sample App Demo User (Manager)";
                newUser.UserPrincipalName = Helper.GetRandomString(10) + "@" + defaultDomain.Name;
                newUser.AccountEnabled    = true;
                newUser.MailNickname      = "SampleAppDemoUserManager";
                newUser.PasswordProfile   = new PasswordProfile
                {
                    Password = "******",
                    ForceChangePasswordNextLogin = true
                };
                newUser.UsageLocation = "US";
                try
                {
                    activeDirectoryClient.Users.AddUserAsync(newUser).Wait();
                    Console.WriteLine("\nNew User {0} was created", newUser.DisplayName);
                }
                catch (Exception e)
                {
                    Console.WriteLine("\nError creating new user {0} {1}", e.Message,
                                      e.InnerException != null ? e.InnerException.Message : "");
                }
            }

            #endregion

            #region List of max 4 Users by UPN

            //*********************************************************************
            // Demonstrate Getting a list of Users with paging (get 4 users), sorted by displayName
            //*********************************************************************
            int maxUsers = 4;
            try
            {
                Console.WriteLine("\n Retrieving Users");
                List <IUser> users = activeDirectoryClient.Users.OrderBy(user =>
                                                                         user.UserPrincipalName).Take(maxUsers).ExecuteAsync().Result.CurrentPage.ToList();
                foreach (IUser user in users)
                {
                    Console.WriteLine("UserObjectId: {0}  UPN: {1}", user.ObjectId, user.UserPrincipalName);
                }
            }
            catch (Exception e)
            {
                Console.WriteLine("\nError getting Users. {0} {1}", e.Message,
                                  e.InnerException != null ? e.InnerException.Message : "");
            }

            #endregion

            #region Create a User with a temp Password

            //*********************************************************************************************
            // Create a new User with a temp Password
            //*********************************************************************************************
            IUser userToBeAdded = new User();
            userToBeAdded.DisplayName       = "Sample App Demo User";
            userToBeAdded.UserPrincipalName = Helper.GetRandomString(10) + "@" + defaultDomain.Name;
            userToBeAdded.AccountEnabled    = true;
            userToBeAdded.MailNickname      = "SampleAppDemoUser";
            userToBeAdded.PasswordProfile   = new PasswordProfile
            {
                Password = "******",
                ForceChangePasswordNextLogin = true
            };
            userToBeAdded.UsageLocation = "US";
            try
            {
                activeDirectoryClient.Users.AddUserAsync(userToBeAdded).Wait();
                Console.WriteLine("\nNew User {0} was created", userToBeAdded.DisplayName);
            }
            catch (Exception e)
            {
                Console.WriteLine("\nError creating new user. {0} {1}", e.Message,
                                  e.InnerException != null ? e.InnerException.Message : "");
            }

            #endregion

            #region Update newly created User

            //*******************************************************************************************
            // update the newly created user's Password, PasswordPolicies and City
            //*********************************************************************************************
            if (userToBeAdded.ObjectId != null)
            {
                // update User's city and reset their User's Password
                userToBeAdded.City    = "Seattle";
                userToBeAdded.Country = "UK";
                PasswordProfile PasswordProfile = new PasswordProfile
                {
                    Password = "******",
                    ForceChangePasswordNextLogin = false
                };
                userToBeAdded.PasswordProfile  = PasswordProfile;
                userToBeAdded.PasswordPolicies = "DisablePasswordExpiration, DisableStrongPassword";
                try
                {
                    userToBeAdded.UpdateAsync().Wait();
                    Console.WriteLine("\nUser {0} was updated", userToBeAdded.DisplayName);
                }
                catch (Exception e)
                {
                    Console.WriteLine("\nError Updating the user {0} {1}", e.Message,
                                      e.InnerException != null ? e.InnerException.Message : "");
                }
            }

            #endregion

            #region Search User by UPN

            // search for a single user by UPN
            string searchString = "admin@" + initialDomain.Name;
            Console.WriteLine("\n Retrieving user with UPN {0}", searchString);
            User         retrievedUser  = new User();
            List <IUser> retrievedUsers = null;
            try
            {
                retrievedUsers = activeDirectoryClient.Users
                                 .Where(user => user.UserPrincipalName.Equals(searchString))
                                 .ExecuteAsync().Result.CurrentPage.ToList();
            }
            catch (Exception e)
            {
                Console.WriteLine("\nError getting new user {0} {1}", e.Message,
                                  e.InnerException != null ? e.InnerException.Message : "");
            }
            // should only find one user with the specified UPN
            if (retrievedUsers != null && retrievedUsers.Count == 1)
            {
                retrievedUser = (User)retrievedUsers.First();
            }
            else
            {
                Console.WriteLine("User not found {0}", searchString);
            }

            #endregion

            #region User Operations

            if (retrievedUser.UserPrincipalName != null)
            {
                Console.WriteLine("\n Found User: "******"  UPN: " +
                                  retrievedUser.UserPrincipalName);

                #region Assign User a Manager

                //Assigning User a new manager.
                if (newUser.ObjectId != null)
                {
                    Console.WriteLine("\n Assign User {0}, {1} as Manager.", retrievedUser.DisplayName,
                                      newUser.DisplayName);
                    retrievedUser.Manager = newUser as DirectoryObject;
                    try
                    {
                        newUser.UpdateAsync().Wait();
                        Console.Write("User {0} is successfully assigned {1} as Manager.", retrievedUser.DisplayName,
                                      newUser.DisplayName);
                    }
                    catch (Exception e)
                    {
                        Console.WriteLine("\nError assigning manager to user. {0} {1}", e.Message,
                                          e.InnerException != null ? e.InnerException.Message : "");
                    }
                }

                #endregion

                #region Get User's Manager

                //Get the retrieved user's manager.
                Console.WriteLine("\n Retrieving User {0}'s Manager.", retrievedUser.DisplayName);
                DirectoryObject usersManager = retrievedUser.Manager;
                if (usersManager != null)
                {
                    User manager = usersManager as User;
                    if (manager != null)
                    {
                        Console.WriteLine("User {0} Manager details: \nManager: {1}  UPN: {2}",
                                          retrievedUser.DisplayName, manager.DisplayName, manager.UserPrincipalName);
                    }
                }
                else
                {
                    Console.WriteLine("Manager not found.");
                }

                #endregion

                #region Get User's Direct Reports

                //*********************************************************************
                // get the user's Direct Reports
                //*********************************************************************
                if (newUser.ObjectId != null)
                {
                    Console.WriteLine("\n Getting User{0}'s Direct Reports.", newUser.DisplayName);
                    IUserFetcher newUserFetcher = (IUserFetcher)newUser;
                    try
                    {
                        IPagedCollection <IDirectoryObject> directReports =
                            newUserFetcher.DirectReports.ExecuteAsync().Result;
                        do
                        {
                            List <IDirectoryObject> directoryObjects = directReports.CurrentPage.ToList();
                            foreach (IDirectoryObject directoryObject in directoryObjects)
                            {
                                if (directoryObject is User)
                                {
                                    User directReport = directoryObject as User;
                                    Console.WriteLine("User {0} Direct Report is {1}", newUser.UserPrincipalName,
                                                      directReport.UserPrincipalName);
                                }
                            }
                            directReports = directReports.GetNextPageAsync().Result;
                        } while (directReports != null && directReports.MorePagesAvailable);
                    }
                    catch (Exception e)
                    {
                        Console.WriteLine("\nError getting direct reports of user. {0} {1}", e.Message,
                                          e.InnerException != null ? e.InnerException.Message : "");
                    }
                }

                #endregion

                #region Get list of Group IDS, user is member of

                //*********************************************************************
                // get a list of Group IDs that the user is a member of
                //*********************************************************************
                //const bool securityEnabledOnly = false;
                //IEnumerable<string> memberGroups = retrievedUser.GetMemberGroupsAsync(securityEnabledOnly).Result;
                //Console.WriteLine("\n {0} is a member of the following Groups (IDs)", retrievedUser.DisplayName);
                //foreach (String memberGroup in memberGroups)
                //{
                //    Console.WriteLine("Member of Group ID: " + memberGroup);
                //}

                #endregion

                #region Get User's Group And Role Membership, Getting the complete set of objects

                //*********************************************************************
                // get the User's Group and Role membership, getting the complete set of objects
                //*********************************************************************
                Console.WriteLine("\n {0} is a member of the following Group and Roles (IDs)", retrievedUser.DisplayName);
                IUserFetcher retrievedUserFetcher = retrievedUser;
                try
                {
                    IPagedCollection <IDirectoryObject> pagedCollection = retrievedUserFetcher.MemberOf.ExecuteAsync().Result;
                    do
                    {
                        List <IDirectoryObject> directoryObjects = pagedCollection.CurrentPage.ToList();
                        foreach (IDirectoryObject directoryObject in directoryObjects)
                        {
                            if (directoryObject is Group)
                            {
                                Group group = directoryObject as Group;
                                Console.WriteLine(" Group: {0}  Description: {1}", group.DisplayName, group.Description);
                            }
                            if (directoryObject is DirectoryRole)
                            {
                                DirectoryRole role = directoryObject as DirectoryRole;
                                Console.WriteLine(" Role: {0}  Description: {1}", role.DisplayName, role.Description);
                            }
                        }
                        pagedCollection = pagedCollection.GetNextPageAsync().Result;
                    } while (pagedCollection != null && pagedCollection.MorePagesAvailable);
                }
                catch (Exception e)
                {
                    Console.WriteLine("\nError getting user's groups and roles memberships. {0} {1}", e.Message,
                                      e.InnerException != null ? e.InnerException.Message : "");
                }

                #endregion
            }

            #endregion

            #region Search for User (People Picker)

            //*********************************************************************
            // People picker
            // Search for a user using text string "Us" match against userPrincipalName, displayName, giveName, surname
            //*********************************************************************
            searchString = "Us";
            Console.WriteLine("\nSearching for any user with string {0} in UPN,DisplayName,First or Last Name",
                              searchString);
            List <IUser>             usersList     = null;
            IPagedCollection <IUser> searchResults = null;
            try
            {
                IUserCollection userCollection = activeDirectoryClient.Users;
                searchResults = userCollection.Where(user =>
                                                     user.UserPrincipalName.StartsWith(searchString) ||
                                                     user.DisplayName.StartsWith(searchString) ||
                                                     user.GivenName.StartsWith(searchString) ||
                                                     user.Surname.StartsWith(searchString)).ExecuteAsync().Result;
                usersList = searchResults.CurrentPage.ToList();
            }
            catch (Exception e)
            {
                Console.WriteLine("\nError getting User {0} {1}", e.Message,
                                  e.InnerException != null ? e.InnerException.Message : "");
            }

            if (usersList != null && usersList.Count > 0)
            {
                do
                {
                    usersList = searchResults.CurrentPage.ToList();
                    foreach (IUser user in usersList)
                    {
                        Console.WriteLine("User DisplayName: {0}  UPN: {1}",
                                          user.DisplayName, user.UserPrincipalName);
                    }
                    searchResults = searchResults.GetNextPageAsync().Result;
                } while (searchResults != null && searchResults.MorePagesAvailable);
            }
            else
            {
                Console.WriteLine("User not found");
            }

            #endregion

            #region Search for Group using StartWith filter

            //*********************************************************************
            // Search for a group using a startsWith filter (displayName property)
            //*********************************************************************
            Group retrievedGroup = new Group();
            searchString = "US";
            List <IGroup> foundGroups = null;
            try
            {
                foundGroups = activeDirectoryClient.Groups
                              .Where(group => group.DisplayName.StartsWith(searchString))
                              .ExecuteAsync().Result.CurrentPage.ToList();
            }
            catch (Exception e)
            {
                Console.WriteLine("\nError getting Group {0} {1}",
                                  e.Message, e.InnerException != null ? e.InnerException.Message : "");
            }
            if (foundGroups != null && foundGroups.Count > 0)
            {
                retrievedGroup = foundGroups.First() as Group;
            }
            else
            {
                Console.WriteLine("Group Not Found");
            }

            #endregion

            #region Assign Member to Group

            if (retrievedGroup.ObjectId != null)
            {
                try
                {
                    activeDirectoryClient.Context.AddLink(retrievedGroup, "members", newUser);
                    activeDirectoryClient.Context.SaveChanges();
                }
                catch (Exception e)
                {
                    Console.WriteLine("\nError assigning member to group. {0} {1}",
                                      e.Message, e.InnerException != null ? e.InnerException.Message : "");
                }
            }

            #endregion

            #region Get Group members

            if (retrievedGroup.ObjectId != null)
            {
                Console.WriteLine("\n Found Group: " + retrievedGroup.DisplayName + "  " + retrievedGroup.Description);

                //*********************************************************************
                // get the groups' membership -
                // Note this method retrieves ALL links in one request - please use this method with care - this
                // may return a very large number of objects
                //*********************************************************************
                IGroupFetcher retrievedGroupFetcher = retrievedGroup;
                try
                {
                    IPagedCollection <IDirectoryObject> members = retrievedGroupFetcher.Members.ExecuteAsync().Result;
                    Console.WriteLine(" Members:");
                    do
                    {
                        List <IDirectoryObject> directoryObjects = members.CurrentPage.ToList();
                        foreach (IDirectoryObject member in directoryObjects)
                        {
                            if (member is User)
                            {
                                User user = member as User;
                                Console.WriteLine("User DisplayName: {0}  UPN: {1}",
                                                  user.DisplayName,
                                                  user.UserPrincipalName);
                            }
                            if (member is Group)
                            {
                                Group group = member as Group;
                                Console.WriteLine("Group DisplayName: {0}", group.DisplayName);
                            }
                            if (member is Contact)
                            {
                                Contact contact = member as Contact;
                                Console.WriteLine("Contact DisplayName: {0}", contact.DisplayName);
                            }
                        }
                    } while (members != null && members.MorePagesAvailable);
                }
                catch (Exception e)
                {
                    Console.WriteLine("\nError getting groups' membership. {0} {1}",
                                      e.Message, e.InnerException != null ? e.InnerException.Message : "");
                }
            }

            #endregion

            #region Add User to Group

            //*********************************************************************************************
            // Add User to the "WA" Group
            //*********************************************************************************************
            if (retrievedGroup.ObjectId != null)
            {
                try
                {
                    activeDirectoryClient.Context.AddLink(retrievedGroup, "members", userToBeAdded);
                    activeDirectoryClient.Context.SaveChangesAsync().Wait();
                }
                catch (Exception e)
                {
                    Console.WriteLine("\nAdding user to group failed {0} {1}", e.Message,
                                      e.InnerException != null ? e.InnerException.Message : "");
                }
            }

            #endregion

            #region Create a new Group

            //*********************************************************************************************
            // Create a new Group
            //*********************************************************************************************
            Group californiaEmployees = new Group
            {
                DisplayName     = "California Employees" + Helper.GetRandomString(8),
                Description     = "Employees in the state of California",
                MailNickname    = "CalEmployees",
                MailEnabled     = false,
                SecurityEnabled = true
            };
            try
            {
                activeDirectoryClient.Groups.AddGroupAsync(californiaEmployees).Wait();
                Console.WriteLine("\nNew Group {0} was created", californiaEmployees.DisplayName);
            }
            catch (Exception e)
            {
                Console.WriteLine("\nError creating new Group {0} {1}", e.Message,
                                  e.InnerException != null ? e.InnerException.Message : "");
            }

            #endregion

            #region Delete User

            //*********************************************************************************************
            // Delete the user that we just created
            //*********************************************************************************************
            if (userToBeAdded.ObjectId != null)
            {
                try
                {
                    userToBeAdded.DeleteAsync().Wait();
                    Console.WriteLine("\nUser {0} was deleted", userToBeAdded.DisplayName);
                }
                catch (Exception e)
                {
                    Console.WriteLine("Deleting User failed {0} {1}", e.Message,
                                      e.InnerException != null ? e.InnerException.Message : "");
                }
            }
            if (newUser.ObjectId != null)
            {
                try
                {
                    newUser.DeleteAsync().Wait();
                    Console.WriteLine("\nUser {0} was deleted", newUser.DisplayName);
                }
                catch (Exception e)
                {
                    Console.WriteLine("Deleting User failed {0} {1}", e.Message,
                                      e.InnerException != null ? e.InnerException.Message : "");
                }
            }

            #endregion

            #region Delete Group

            //*********************************************************************************************
            // Delete the Group that we just created
            //*********************************************************************************************
            if (californiaEmployees.ObjectId != null)
            {
                try
                {
                    californiaEmployees.DeleteAsync().Wait();
                    Console.WriteLine("\nGroup {0} was deleted", californiaEmployees.DisplayName);
                }
                catch (Exception e)
                {
                    Console.WriteLine("Deleting Group failed {0} {1}", e.Message,
                                      e.InnerException != null ? e.InnerException.Message : "");
                }
            }

            #endregion

            #region Get All Roles

            //*********************************************************************
            // Get All Roles
            //*********************************************************************
            List <IDirectoryRole> foundRoles = null;
            try
            {
                foundRoles = activeDirectoryClient.DirectoryRoles.ExecuteAsync().Result.CurrentPage.ToList();
            }
            catch (Exception e)
            {
                Console.WriteLine("\nError getting Roles {0} {1}", e.Message,
                                  e.InnerException != null ? e.InnerException.Message : "");
            }

            if (foundRoles != null && foundRoles.Count > 0)
            {
                foreach (IDirectoryRole role in foundRoles)
                {
                    Console.WriteLine("\n Found Role: {0} {1} {2} ",
                                      role.DisplayName, role.Description, role.ObjectId);
                }
            }
            else
            {
                Console.WriteLine("Role Not Found {0}", searchString);
            }

            #endregion

            #region Get Service Principals

            //*********************************************************************
            // get the Service Principals
            //*********************************************************************
            IPagedCollection <IServicePrincipal> servicePrincipals = null;
            try
            {
                servicePrincipals = activeDirectoryClient.ServicePrincipals.ExecuteAsync().Result;
            }
            catch (Exception e)
            {
                Console.WriteLine("\nError getting Service Principal {0} {1}",
                                  e.Message, e.InnerException != null ? e.InnerException.Message : "");
            }
            if (servicePrincipals != null)
            {
                do
                {
                    List <IServicePrincipal> servicePrincipalsList = servicePrincipals.CurrentPage.ToList();
                    foreach (IServicePrincipal servicePrincipal in servicePrincipalsList)
                    {
                        Console.WriteLine("Service Principal AppId: {0}  Name: {1}", servicePrincipal.AppId,
                                          servicePrincipal.DisplayName);
                    }
                    servicePrincipals = servicePrincipals.GetNextPageAsync().Result;
                } while (servicePrincipals != null && servicePrincipals.MorePagesAvailable);
            }

            #endregion

            #region Get Applications

            //*********************************************************************
            // get the Application objects
            //*********************************************************************
            IPagedCollection <IApplication> applications = null;
            try
            {
                applications = activeDirectoryClient.Applications.Take(999).ExecuteAsync().Result;
            }
            catch (Exception e)
            {
                Console.WriteLine("\nError getting Applications {0} {1}", e.Message,
                                  e.InnerException != null ? e.InnerException.Message : "");
            }
            if (applications != null)
            {
                do
                {
                    List <IApplication> appsList = applications.CurrentPage.ToList();
                    foreach (IApplication app in appsList)
                    {
                        Console.WriteLine("Application AppId: {0}  Name: {1}", app.AppId, app.DisplayName);
                    }
                    applications = applications.GetNextPageAsync().Result;
                } while (applications != null && applications.MorePagesAvailable);
            }

            #endregion

            #region User License Assignment

            //*********************************************************************************************
            // User License Assignment - assign EnterprisePack license to new user, and disable SharePoint service
            //   first get a list of Tenant's subscriptions and find the "Enterprisepack" one
            //   Enterprise Pack includes service Plans for ExchangeOnline, SharePointOnline and LyncOnline
            //   validate that Subscription is Enabled and there are enough units left to assign to users
            //*********************************************************************************************
            IPagedCollection <ISubscribedSku> skus = null;
            try
            {
                skus = activeDirectoryClient.SubscribedSkus.ExecuteAsync().Result;
            }
            catch (Exception e)
            {
                Console.WriteLine("\nError getting Applications {0} {1}", e.Message,
                                  e.InnerException != null ? e.InnerException.Message : "");
            }
            if (skus != null)
            {
                do
                {
                    List <ISubscribedSku> subscribedSkus = skus.CurrentPage.ToList();
                    foreach (ISubscribedSku sku in subscribedSkus)
                    {
                        if (sku.SkuPartNumber == "ENTERPRISEPACK")
                        {
                            if ((sku.PrepaidUnits.Enabled.Value > sku.ConsumedUnits) &&
                                (sku.CapabilityStatus == "Enabled"))
                            {
                                // create addLicense object and assign the Enterprise Sku GUID to the skuId
                                //
                                AssignedLicense addLicense = new AssignedLicense {
                                    SkuId = sku.SkuId.Value
                                };

                                // find plan id of SharePoint Service Plan
                                foreach (ServicePlanInfo servicePlan in sku.ServicePlans)
                                {
                                    if (servicePlan.ServicePlanName.Contains("SHAREPOINT"))
                                    {
                                        addLicense.DisabledPlans.Add(servicePlan.ServicePlanId.Value);
                                        break;
                                    }
                                }

                                IList <AssignedLicense> licensesToAdd    = new[] { addLicense };
                                IList <Guid>            licensesToRemove = new Guid[] {};

                                // attempt to assign the license object to the new user
                                try
                                {
                                    if (newUser.ObjectId != null)
                                    {
                                        newUser.AssignLicenseAsync(licensesToAdd, licensesToRemove).Wait();
                                        Console.WriteLine("\n User {0} was assigned license {1}",
                                                          newUser.DisplayName,
                                                          addLicense.SkuId);
                                    }
                                }
                                catch (Exception e)
                                {
                                    Console.WriteLine("\nLicense assingment failed {0} {1}", e.Message,
                                                      e.InnerException != null ? e.InnerException.Message : "");
                                }
                            }
                        }
                    }
                    skus = skus.GetNextPageAsync().Result;
                } while (skus != null && skus.MorePagesAvailable);
            }

            #endregion

            #region Switch to OAuth Authorization Code Grant (Acting as a user)

            activeDirectoryClient = AuthenticationHelper.GetActiveDirectoryClientAsUser();

            #endregion

            #region Create Application

            //*********************************************************************************************
            // Create a new Application object with App Role Assignment (Direct permission)
            //*********************************************************************************************
            Application appObject = new Application {
                DisplayName = "Test-Demo App" + Helper.GetRandomString(8)
            };
            appObject.IdentifierUris.Add("https://localhost/demo/" + Guid.NewGuid());
            appObject.ReplyUrls.Add("https://localhost/demo");
            AppRole appRole = new AppRole();
            appRole.Id        = Guid.NewGuid();
            appRole.IsEnabled = true;
            appRole.AllowedMemberTypes.Add("User");
            appRole.DisplayName = "Something";
            appRole.Description = "Anything";
            appRole.Value       = "policy.write";
            appObject.AppRoles.Add(appRole);

            // created Keycredential object for the new App object
            KeyCredential keyCredential = new KeyCredential
            {
                StartDate = DateTime.UtcNow,
                EndDate   = DateTime.UtcNow.AddYears(1),
                Type      = "Symmetric",
                Value     = Convert.FromBase64String("g/TMLuxgzurjQ0Sal9wFEzpaX/sI0vBP3IBUE/H/NS4="),
                Usage     = "Verify"
            };
            appObject.KeyCredentials.Add(keyCredential);

            try
            {
                activeDirectoryClient.Applications.AddApplicationAsync(appObject).Wait();
                Console.WriteLine("New Application created: " + appObject.ObjectId);
            }
            catch (Exception e)
            {
                Console.WriteLine("Application Creation execption: {0} {1}", e.Message,
                                  e.InnerException != null ? e.InnerException.Message : "");
            }

            #endregion

            #region Create Service Principal

            //*********************************************************************************************
            // create a new Service principal
            //*********************************************************************************************
            ServicePrincipal newServicePrincpal = new ServicePrincipal();
            if (appObject != null)
            {
                newServicePrincpal.DisplayName    = appObject.DisplayName;
                newServicePrincpal.AccountEnabled = true;
                newServicePrincpal.AppId          = appObject.AppId;
                try
                {
                    activeDirectoryClient.ServicePrincipals.AddServicePrincipalAsync(newServicePrincpal).Wait();
                    Console.WriteLine("New Service Principal created: " + newServicePrincpal.ObjectId);
                }
                catch (Exception e)
                {
                    Console.WriteLine("Service Principal Creation execption: {0} {1}", e.Message,
                                      e.InnerException != null ? e.InnerException.Message : "");
                }
            }

            #endregion

            #region Assign Direct Permission
            try
            {
                User user =
                    (User)activeDirectoryClient.Users.ExecuteAsync().Result.CurrentPage.ToList().FirstOrDefault();
                if (appObject.ObjectId != null && user != null && newServicePrincpal.ObjectId != null)
                {
                    AppRoleAssignment appRoleAssignment = new AppRoleAssignment();
                    appRoleAssignment.Id            = appRole.Id;
                    appRoleAssignment.ResourceId    = Guid.Parse(newServicePrincpal.ObjectId);
                    appRoleAssignment.PrincipalType = "User";
                    appRoleAssignment.PrincipalId   = Guid.Parse(user.ObjectId);
                    user.AppRoleAssignments.Add(appRoleAssignment);
                    user.UpdateAsync().Wait();
                    Console.WriteLine("User {0} is successfully assigned direct permission.", retrievedUser.DisplayName);
                }
            }
            catch (Exception e)
            {
                Console.WriteLine("Direct Permission Assignment failed: {0} {1}", e.Message,
                                  e.InnerException != null ? e.InnerException.Message : "");
            }

            #endregion

            #region Get Devices

            //*********************************************************************************************
            // Get a list of Mobile Devices from tenant
            //*********************************************************************************************
            Console.WriteLine("\nGetting Devices");
            IPagedCollection <IDevice> devices = null;
            try
            {
                devices = activeDirectoryClient.Devices.ExecuteAsync().Result;
            }
            catch (Exception e)
            {
                Console.WriteLine("/nError getting devices {0} {1}", e.Message,
                                  e.InnerException != null ? e.InnerException.Message : "");
            }

            if (devices != null)
            {
                do
                {
                    List <IDevice> devicesList = devices.CurrentPage.ToList();
                    foreach (IDevice device in devicesList)
                    {
                        if (device.ObjectId != null)
                        {
                            Console.WriteLine("Device ID: {0}, Type: {1}", device.DeviceId, device.DeviceOSType);
                            IPagedCollection <IDirectoryObject> registeredOwners = device.RegisteredOwners;
                            if (registeredOwners != null)
                            {
                                do
                                {
                                    List <IDirectoryObject> registeredOwnersList = registeredOwners.CurrentPage.ToList();
                                    foreach (IDirectoryObject owner in registeredOwnersList)
                                    {
                                        Console.WriteLine("Device Owner ID: " + owner.ObjectId);
                                    }
                                    registeredOwners = registeredOwners.GetNextPageAsync().Result;
                                } while (registeredOwners != null && registeredOwners.MorePagesAvailable);
                            }
                        }
                    }
                    devices = devices.GetNextPageAsync().Result;
                } while (devices != null && devices.MorePagesAvailable);
            }

            #endregion

            #region Create New Permission

            //*********************************************************************************************
            // Create new permission object
            //*********************************************************************************************
            OAuth2PermissionGrant permissionObject = new OAuth2PermissionGrant();
            permissionObject.ConsentType = "AllPrincipals";
            permissionObject.Scope       = "user_impersonation";
            permissionObject.StartTime   = DateTime.Now;
            permissionObject.ExpiryTime  = (DateTime.Now).AddMonths(12);

            // resourceId is objectId of the resource, in this case objectId of AzureAd (Graph API)
            permissionObject.ResourceId = "52620afb-80de-4096-a826-95f4ad481686";

            //ClientId = objectId of servicePrincipal
            permissionObject.ClientId = newServicePrincpal.ObjectId;
            try
            {
                activeDirectoryClient.Oauth2PermissionGrants.AddOAuth2PermissionGrantAsync(permissionObject).Wait();
                Console.WriteLine("New Permission object created: " + permissionObject.ObjectId);
            }
            catch (Exception e)
            {
                Console.WriteLine("Permission Creation exception: {0} {1}", e.Message, e.InnerException != null ? e.InnerException.Message : "");
            }

            #endregion

            #region Get All Permissions

            //*********************************************************************************************
            // get all Permission Objects
            //*********************************************************************************************
            Console.WriteLine("\n Getting Permissions");
            IPagedCollection <IOAuth2PermissionGrant> permissions = null;
            try
            {
                permissions = activeDirectoryClient.Oauth2PermissionGrants.ExecuteAsync().Result;
            }
            catch (Exception e)
            {
                Console.WriteLine("Error: {0} {1}", e.Message, e.InnerException != null ? e.InnerException.Message : "");
            }
            if (permissions != null)
            {
                do
                {
                    List <IOAuth2PermissionGrant> perms = permissions.CurrentPage.ToList();
                    foreach (IOAuth2PermissionGrant perm in perms)
                    {
                        Console.WriteLine("Permission: {0}  Name: {1}", perm.ClientId, perm.Scope);
                    }
                } while (permissions != null && permissions.MorePagesAvailable);
            }

            #endregion

            #region Delete Application

            //*********************************************************************************************
            // Delete Application Objects
            //*********************************************************************************************
            if (appObject.ObjectId != null)
            {
                try
                {
                    appObject.DeleteAsync().Wait();
                    Console.WriteLine("Deleted Application object: " + appObject.ObjectId);
                }
                catch (Exception e)
                {
                    Console.WriteLine("Application Deletion execption: {0} {1}", e.Message,
                                      e.InnerException != null ? e.InnerException.Message : "");
                }
            }

            #endregion

            #region Batch Operations

            //*********************************************************************************************
            // Show Batching with 3 operators.  Note: up to 5 operations can be in a batch
            //*********************************************************************************************
            IReadOnlyQueryableSet <User>          userQuery   = activeDirectoryClient.DirectoryObjects.OfType <User>();
            IReadOnlyQueryableSet <Group>         groupsQuery = activeDirectoryClient.DirectoryObjects.OfType <Group>();
            IReadOnlyQueryableSet <DirectoryRole> rolesQuery  =
                activeDirectoryClient.DirectoryObjects.OfType <DirectoryRole>();
            try
            {
                IBatchElementResult[] batchResult =
                    activeDirectoryClient.Context.ExecuteBatchAsync(userQuery, groupsQuery, rolesQuery).Result;
                int responseCount = 1;
                foreach (IBatchElementResult result in batchResult)
                {
                    if (result.FailureResult != null)
                    {
                        Console.WriteLine("Failed: {0} ",
                                          result.FailureResult.InnerException);
                    }
                    if (result.SuccessResult != null)
                    {
                        Console.WriteLine("Batch Item Result {0} succeeded",
                                          responseCount++);
                    }
                }
            }
            catch (Exception e)
            {
                Console.WriteLine("Batch execution failed. : {0} {1}", e.Message,
                                  e.InnerException != null ? e.InnerException.Message : "");
            }

            #endregion

            //*********************************************************************************************
            // End of Demo Console App
            //*********************************************************************************************

            Console.WriteLine("\nCompleted at {0} \n Press Any Key to Exit.", currentDateTime);
            Console.ReadKey();
        }
Esempio n. 15
0
 public async Task <AppRoleAssignment> AddApplicationRoleAssignment(Guid resourceId, [FromBody] AppRoleAssignment request)
 {
     request.ResourceId = resourceId;
     return(await _appsRepo.AssignAppRole(request));
 }
        protected async Task <Application> RegisterServiceApplicationAsync(
            string serviceApplicationName,
            DirectoryObject owner,
            IEnumerable <string> tags           = null,
            CancellationToken cancellationToken = default
            )
        {
            try {
                tags ??= new List <string>();

                Log.Information("Creating service application registration ...");

                // Setup AppRoles for service application
                var serviceApplicationAppRoles = new List <AppRole>();

                var serviceApplicationApproverRoleId = Guid.NewGuid();
                serviceApplicationAppRoles.Add(new AppRole {
                    DisplayName        = "Approver",
                    Value              = "Sign",
                    Description        = "Approvers have the ability to issue certificates.",
                    AllowedMemberTypes = new List <string> {
                        "User", "Application"
                    },
                    Id = serviceApplicationApproverRoleId
                });

                var serviceApplicationWriterRoleId = Guid.NewGuid();
                serviceApplicationAppRoles.Add(new AppRole {
                    DisplayName        = "Writer",
                    Value              = "Write",
                    Description        = "Writers Have the ability to change entities.",
                    AllowedMemberTypes = new List <string> {
                        "User", "Application"
                    },
                    Id = serviceApplicationWriterRoleId
                });

                var serviceApplicationAdministratorRoleId = Guid.NewGuid();
                serviceApplicationAppRoles.Add(new AppRole {
                    DisplayName        = "Administrator",
                    Value              = "Admin",
                    Description        = "Admins can access advanced features.",
                    AllowedMemberTypes = new List <string> {
                        "User", "Application"
                    },
                    Id = serviceApplicationAdministratorRoleId
                });

                // Setup RequiredResourceAccess for service application

                var keyVaultUserImpersonationRequiredResourceAccess = new RequiredResourceAccess {
                    ResourceAppId  = AzureAppsConstants.AzureKeyVault.AppId,
                    ResourceAccess = new List <ResourceAccess> {
                        new ResourceAccess {
                            Id   = AzureAppsConstants.AzureKeyVault.ResourceAccess["user_impersonation"],
                            Type = "Scope"
                        }
                    }
                };

                var microsoftGraphUserReadRequiredResourceAccess = new RequiredResourceAccess {
                    ResourceAppId  = AzureAppsConstants.MicrosoftGraph.AppId,
                    ResourceAccess = new List <ResourceAccess> {
                        new ResourceAccess {
                            Id   = AzureAppsConstants.MicrosoftGraph.ResourceAccess["User.Read"],
                            Type = "Scope"
                        }
                    }
                };

                var serviceApplicationRequiredResourceAccess = new List <RequiredResourceAccess>()
                {
                    keyVaultUserImpersonationRequiredResourceAccess,
                    microsoftGraphUserReadRequiredResourceAccess
                };

                // Add OAuth2Permissions
                var oauth2Permissions = new List <PermissionScope> {
                    new PermissionScope {
                        AdminConsentDescription = $"Allow the app to access {serviceApplicationName} on behalf of the signed-in user.",
                        AdminConsentDisplayName = $"Access {serviceApplicationName}",
                        Id        = Guid.NewGuid(),
                        IsEnabled = true,
                        Type      = "User",
                        UserConsentDescription = $"Allow the application to access {serviceApplicationName} on your behalf.",
                        UserConsentDisplayName = $"Access {serviceApplicationName}",
                        Value = "user_impersonation"
                    }
                };

                var serviceApplicationApiApplication = new ApiApplication {
                    Oauth2PermissionScopes = oauth2Permissions
                };

                // ODataType = null is a workaround for a bug:
                // https://github.com/microsoftgraph/msgraph-beta-sdk-dotnet/issues/87
                var serviceApplicationWebApplication = new WebApplication {
                    ImplicitGrantSettings = new ImplicitGrantSettings {
                        ODataType             = null,
                        EnableIdTokenIssuance = true
                    }
                };

                var serviceApplicationDefinition = new Application {
                    DisplayName            = serviceApplicationName,
                    IsFallbackPublicClient = false,
                    IdentifierUris         = new List <string> {
                        $"https://{_tenantId.ToString()}/{serviceApplicationName}"
                    },
                    Tags                   = tags,
                    SignInAudience         = "AzureADMyOrg",
                    AppRoles               = serviceApplicationAppRoles,
                    RequiredResourceAccess = serviceApplicationRequiredResourceAccess,
                    Api = serviceApplicationApiApplication,
                    Web = serviceApplicationWebApplication,
                    PasswordCredentials = new List <PasswordCredential> {
                    }
                };

                var serviceApplication = await _msGraphServiceClient
                                         .CreateApplicationAsync(
                    serviceApplicationDefinition,
                    cancellationToken
                    );

                // Add Service Key PasswordCredential
                var serviceKeyName = "Service Key";
                await _msGraphServiceClient
                .AddApplication2YPasswordCredentialAsync(
                    serviceApplication,
                    serviceKeyName,
                    cancellationToken
                    );

                // We need to create ServicePrincipal for this application.
                var serviceApplicationSP = await _msGraphServiceClient
                                           .CreateApplicationServicePrincipalAsync(
                    serviceApplication,
                    tags,
                    cancellationToken
                    );

                // Add app role assignment to owner as Approver, Writer and Administrator.
                string PrincipalType;

                if (owner is User)
                {
                    PrincipalType = "User";
                }
                else if (owner is ServicePrincipal)
                {
                    PrincipalType = "ServicePrincipal";
                }
                else if (owner is Group)
                {
                    PrincipalType = "Group";
                }
                else
                {
                    throw new ArgumentException($"Owner is of unknown type: {owner.GetType()}", "owner");
                }

                var approverAppRoleAssignmentDefinition = new AppRoleAssignment {
                    PrincipalType       = PrincipalType,
                    PrincipalId         = new Guid(owner.Id),
                    ResourceId          = new Guid(serviceApplicationSP.Id),
                    ResourceDisplayName = "Approver",
                    Id        = serviceApplicationApproverRoleId.ToString(),
                    AppRoleId = serviceApplicationApproverRoleId
                };

                var writerAppRoleAssignmentDefinition = new AppRoleAssignment {
                    PrincipalType       = PrincipalType,
                    PrincipalId         = new Guid(owner.Id),
                    ResourceId          = new Guid(serviceApplicationSP.Id),
                    ResourceDisplayName = "Writer",
                    Id        = serviceApplicationWriterRoleId.ToString(),
                    AppRoleId = serviceApplicationWriterRoleId
                };

                var administratorAppRoleAssignmentDefinition = new AppRoleAssignment {
                    PrincipalType       = PrincipalType,
                    PrincipalId         = new Guid(owner.Id),
                    ResourceId          = new Guid(serviceApplicationSP.Id),
                    ResourceDisplayName = "Administrator",
                    Id        = serviceApplicationAdministratorRoleId.ToString(),
                    AppRoleId = serviceApplicationAdministratorRoleId
                };

                await _msGraphServiceClient
                .AddServicePrincipalAppRoleAssignmentAsync(
                    serviceApplicationSP,
                    approverAppRoleAssignmentDefinition,
                    cancellationToken
                    );

                await _msGraphServiceClient
                .AddServicePrincipalAppRoleAssignmentAsync(
                    serviceApplicationSP,
                    writerAppRoleAssignmentDefinition,
                    cancellationToken
                    );

                await _msGraphServiceClient
                .AddServicePrincipalAppRoleAssignmentAsync(
                    serviceApplicationSP,
                    administratorAppRoleAssignmentDefinition,
                    cancellationToken
                    );

                // Get updated definition
                serviceApplication = await _msGraphServiceClient
                                     .GetApplicationAsync(
                    new Guid(serviceApplication.Id),
                    cancellationToken
                    );

                Log.Information("Created service application registration.");

                return(serviceApplication);
            }
            catch (Exception) {
                Log.Error("Failed to create service application registration.");
                throw;
            }
        }
Esempio n. 17
0
        private static void Main()
        {
            // record start DateTime of execution
            string currentDateTime = DateTime.Now.ToUniversalTime().ToString();

            #region Setup Active Directory Client

            //*********************************************************************
            // setup Active Directory Client
            //*********************************************************************
            ActiveDirectoryClient activeDirectoryClient;
            try
            {
                activeDirectoryClient = AuthenticationHelper.GetActiveDirectoryClientAsApplication();
            }
            catch (AuthenticationException ex)
            {
                Console.ForegroundColor = ConsoleColor.Red;
                Console.WriteLine("Acquiring a token failed with the following error: {0}", ex.Message);
                if (ex.InnerException != null)
                {
                    //You should implement retry and back-off logic per the guidance given here:http://msdn.microsoft.com/en-us/library/dn168916.aspx
                    //InnerException Message will contain the HTTP error status codes mentioned in the link above
                    Console.WriteLine("Error detail: {0}", ex.InnerException.Message);
                }
                Console.ResetColor();
                Console.ReadKey();
                return;
            }

            #endregion

            #region TenantDetails

            //*********************************************************************
            // Get Tenant Details
            // Note: update the string TenantId with your TenantId.
            // This can be retrieved from the login Federation Metadata end point:             
            // https://login.windows.net/GraphDir1.onmicrosoft.com/FederationMetadata/2007-06/FederationMetadata.xml
            //  Replace "GraphDir1.onMicrosoft.com" with any domain owned by your organization
            // The returned value from the first xml node "EntityDescriptor", will have a STS URL
            // containing your TenantId e.g. "https://sts.windows.net/4fd2b2f2-ea27-4fe5-a8f3-7b1a7c975f34/" is returned for GraphDir1.onMicrosoft.com
            //*********************************************************************
            VerifiedDomain initialDomain = new VerifiedDomain();
            VerifiedDomain defaultDomain = new VerifiedDomain();
            ITenantDetail tenant = null;
            Console.WriteLine("\n Retrieving Tenant Details");
            try
            {
                List<ITenantDetail> tenantsList = activeDirectoryClient.TenantDetails
                    .Where(tenantDetail => tenantDetail.ObjectId.Equals(Constants.TenantId))
                    .ExecuteAsync().Result.CurrentPage.ToList();
                if (tenantsList.Count > 0)
                {
                    tenant = tenantsList.First();
                }
            }
            catch (Exception e)
            {
                Console.WriteLine("\nError getting TenantDetails {0} {1}", e.Message,
                    e.InnerException != null ? e.InnerException.Message : "");
            }

            if (tenant == null)
            {
                Console.WriteLine("Tenant not found");
            }
            else
            {
                TenantDetail tenantDetail = (TenantDetail)tenant;
                Console.WriteLine("Tenant Display Name: " + tenantDetail.DisplayName);

                // Get the Tenant's Verified Domains 
                initialDomain = tenantDetail.VerifiedDomains.First(x => x.Initial.HasValue && x.Initial.Value);
                Console.WriteLine("Initial Domain Name: " + initialDomain.Name);
                defaultDomain = tenantDetail.VerifiedDomains.First(x => [email protected] && [email protected]);
                Console.WriteLine("Default Domain Name: " + defaultDomain.Name);

                // Get Tenant's Tech Contacts
                foreach (string techContact in tenantDetail.TechnicalNotificationMails)
                {
                    Console.WriteLine("Tenant Tech Contact: " + techContact);
                }
            }

            #endregion

            #region Create a new User

            IUser newUser = new User();
            if (defaultDomain.Name != null)
            {
                newUser.DisplayName = "Sample App Demo User (Manager)";
                newUser.UserPrincipalName = Helper.GetRandomString(10) + "@" + defaultDomain.Name;
                newUser.AccountEnabled = true;
                newUser.MailNickname = "SampleAppDemoUserManager";
                newUser.PasswordProfile = new PasswordProfile
                {
                    Password = "******",
                    ForceChangePasswordNextLogin = true
                };
                newUser.UsageLocation = "US";
                try
                {
                    activeDirectoryClient.Users.AddUserAsync(newUser).Wait();
                    Console.WriteLine("\nNew User {0} was created", newUser.DisplayName);
                }
                catch (Exception e)
                {
                    Console.WriteLine("\nError creating new user {0} {1}", e.Message,
                        e.InnerException != null ? e.InnerException.Message : "");
                }
            }

            #endregion

            #region List of max 4 Users by UPN

            //*********************************************************************
            // Demonstrate Getting a list of Users with paging (get 4 users), sorted by displayName
            //*********************************************************************
            int maxUsers = 4;
            try
            {
                Console.WriteLine("\n Retrieving Users");
                List<IUser> users = activeDirectoryClient.Users.OrderBy(user =>
                    user.UserPrincipalName).Take(maxUsers).ExecuteAsync().Result.CurrentPage.ToList();
                foreach (IUser user in users)
                {
                    Console.WriteLine("UserObjectId: {0}  UPN: {1}", user.ObjectId, user.UserPrincipalName);
                }
            }
            catch (Exception e)
            {
                Console.WriteLine("\nError getting Users. {0} {1}", e.Message,
                    e.InnerException != null ? e.InnerException.Message : "");
            }

            #endregion

            #region Create a User with a temp Password

            //*********************************************************************************************
            // Create a new User with a temp Password
            //*********************************************************************************************
            IUser userToBeAdded = new User();
            userToBeAdded.DisplayName = "Sample App Demo User";
            userToBeAdded.UserPrincipalName = Helper.GetRandomString(10) + "@" + defaultDomain.Name;
            userToBeAdded.AccountEnabled = true;
            userToBeAdded.MailNickname = "SampleAppDemoUser";
            userToBeAdded.PasswordProfile = new PasswordProfile
            {
                Password = "******",
                ForceChangePasswordNextLogin = true
            };
            userToBeAdded.UsageLocation = "US";
            try
            {
                activeDirectoryClient.Users.AddUserAsync(userToBeAdded).Wait();
                Console.WriteLine("\nNew User {0} was created", userToBeAdded.DisplayName);
            }
            catch (Exception e)
            {
                Console.WriteLine("\nError creating new user. {0} {1}", e.Message,
                    e.InnerException != null ? e.InnerException.Message : "");
            }

            #endregion

            #region Update newly created User

            //*******************************************************************************************
            // update the newly created user's Password, PasswordPolicies and City
            //*********************************************************************************************
            if (userToBeAdded.ObjectId != null)
            {
                // update User's city and reset their User's Password
                userToBeAdded.City = "Seattle";
                userToBeAdded.Country = "UK";
                PasswordProfile PasswordProfile = new PasswordProfile
                {
                    Password = "******",
                    ForceChangePasswordNextLogin = false
                };
                userToBeAdded.PasswordProfile = PasswordProfile;
                userToBeAdded.PasswordPolicies = "DisablePasswordExpiration, DisableStrongPassword";
                try
                {
                    userToBeAdded.UpdateAsync().Wait();
                    Console.WriteLine("\nUser {0} was updated", userToBeAdded.DisplayName);
                }
                catch (Exception e)
                {
                    Console.WriteLine("\nError Updating the user {0} {1}", e.Message,
                        e.InnerException != null ? e.InnerException.Message : "");
                }
            }

            #endregion

            #region Search User by UPN

            // search for a single user by UPN
            string searchString = "admin@" + initialDomain.Name;
            Console.WriteLine("\n Retrieving user with UPN {0}", searchString);
            User retrievedUser = new User();
            List<IUser> retrievedUsers = null;
            try
            {
                retrievedUsers = activeDirectoryClient.Users
                    .Where(user => user.UserPrincipalName.Equals(searchString))
                    .ExecuteAsync().Result.CurrentPage.ToList();
            }
            catch (Exception e)
            {
                Console.WriteLine("\nError getting new user {0} {1}", e.Message,
                    e.InnerException != null ? e.InnerException.Message : "");
            }
            // should only find one user with the specified UPN
            if (retrievedUsers != null && retrievedUsers.Count == 1)
            {
                retrievedUser = (User)retrievedUsers.First();
            }
            else
            {
                Console.WriteLine("User not found {0}", searchString);
            }

            #endregion

            #region User Operations

            if (retrievedUser.UserPrincipalName != null)
            {
                Console.WriteLine("\n Found User: "******"  UPN: " +
                                  retrievedUser.UserPrincipalName);

                #region Assign User a Manager

                //Assigning User a new manager.
                if (newUser.ObjectId != null)
                {
                    Console.WriteLine("\n Assign User {0}, {1} as Manager.", retrievedUser.DisplayName,
                        newUser.DisplayName);
                    retrievedUser.Manager = newUser as DirectoryObject;
                    try
                    {
                        newUser.UpdateAsync().Wait();
                        Console.Write("User {0} is successfully assigned {1} as Manager.", retrievedUser.DisplayName,
                            newUser.DisplayName);
                    }
                    catch (Exception e)
                    {
                        Console.WriteLine("\nError assigning manager to user. {0} {1}", e.Message,
                            e.InnerException != null ? e.InnerException.Message : "");
                    }
                }

                #endregion

                #region Get User's Manager

                //Get the retrieved user's manager.
                Console.WriteLine("\n Retrieving User {0}'s Manager.", retrievedUser.DisplayName);
                DirectoryObject usersManager = retrievedUser.Manager;
                if (usersManager != null)
                {
                    User manager = usersManager as User;
                    if (manager != null)
                    {
                        Console.WriteLine("User {0} Manager details: \nManager: {1}  UPN: {2}",
                            retrievedUser.DisplayName, manager.DisplayName, manager.UserPrincipalName);
                    }
                }
                else
                {
                    Console.WriteLine("Manager not found.");
                }

                #endregion

                #region Get User's Direct Reports

                //*********************************************************************
                // get the user's Direct Reports
                //*********************************************************************
                if (newUser.ObjectId != null)
                {
                    Console.WriteLine("\n Getting User{0}'s Direct Reports.", newUser.DisplayName);
                    IUserFetcher newUserFetcher = (IUserFetcher)newUser;
                    try
                    {
                        IPagedCollection<IDirectoryObject> directReports =
                            newUserFetcher.DirectReports.ExecuteAsync().Result;
                        do
                        {
                            List<IDirectoryObject> directoryObjects = directReports.CurrentPage.ToList();
                            foreach (IDirectoryObject directoryObject in directoryObjects)
                            {
                                if (directoryObject is User)
                                {
                                    User directReport = directoryObject as User;
                                    Console.WriteLine("User {0} Direct Report is {1}", newUser.UserPrincipalName,
                                        directReport.UserPrincipalName);
                                }
                            }
                            directReports = directReports.GetNextPageAsync().Result;
                        } while (directReports != null);
                    }
                    catch (Exception e)
                    {
                        Console.WriteLine("\nError getting direct reports of user. {0} {1}", e.Message,
                            e.InnerException != null ? e.InnerException.Message : "");
                    }
                }

                #endregion

                #region Get list of Group IDS, user is member of

                //*********************************************************************
                // get a list of Group IDs that the user is a member of
                //*********************************************************************
                //const bool securityEnabledOnly = false;
                //IEnumerable<string> memberGroups = retrievedUser.GetMemberGroupsAsync(securityEnabledOnly).Result;
                //Console.WriteLine("\n {0} is a member of the following Groups (IDs)", retrievedUser.DisplayName);
                //foreach (String memberGroup in memberGroups)
                //{
                //    Console.WriteLine("Member of Group ID: " + memberGroup);
                //}

                #endregion

                #region Get User's Group And Role Membership, Getting the complete set of objects

                //*********************************************************************
                // get the User's Group and Role membership, getting the complete set of objects
                //*********************************************************************
                Console.WriteLine("\n {0} is a member of the following Group and Roles (IDs)", retrievedUser.DisplayName);
                IUserFetcher retrievedUserFetcher = retrievedUser;
                try
                {
                    IPagedCollection<IDirectoryObject> pagedCollection = retrievedUserFetcher.MemberOf.ExecuteAsync().Result;
                    do
                    {
                        List<IDirectoryObject> directoryObjects = pagedCollection.CurrentPage.ToList();
                        foreach (IDirectoryObject directoryObject in directoryObjects)
                        {
                            if (directoryObject is Group)
                            {
                                Group group = directoryObject as Group;
                                Console.WriteLine(" Group: {0}  Description: {1}", group.DisplayName, group.Description);
                            }
                            if (directoryObject is DirectoryRole)
                            {
                                DirectoryRole role = directoryObject as DirectoryRole;
                                Console.WriteLine(" Role: {0}  Description: {1}", role.DisplayName, role.Description);
                            }
                        }
                        pagedCollection = pagedCollection.GetNextPageAsync().Result;
                    } while (pagedCollection != null);
                }
                catch (Exception e)
                {
                    Console.WriteLine("\nError getting user's groups and roles memberships. {0} {1}", e.Message,
                        e.InnerException != null ? e.InnerException.Message : "");
                }

                #endregion
            }

            #endregion

            #region Search for User (People Picker)

            //*********************************************************************
            // People picker
            // Search for a user using text string "Us" match against userPrincipalName, displayName, giveName, surname   
            //*********************************************************************
            searchString = "Us";
            Console.WriteLine("\nSearching for any user with string {0} in UPN,DisplayName,First or Last Name",
                searchString);
            List<IUser> usersList = null;
            IPagedCollection<IUser> searchResults = null;
            try
            {
                IUserCollection userCollection = activeDirectoryClient.Users;
                searchResults = userCollection.Where(user =>
                    user.UserPrincipalName.StartsWith(searchString) ||
                    user.DisplayName.StartsWith(searchString) ||
                    user.GivenName.StartsWith(searchString) ||
                    user.Surname.StartsWith(searchString)).ExecuteAsync().Result;
                usersList = searchResults.CurrentPage.ToList();
            }
            catch (Exception e)
            {
                Console.WriteLine("\nError getting User {0} {1}", e.Message,
                    e.InnerException != null ? e.InnerException.Message : "");
            }

            if (usersList != null && usersList.Count > 0)
            {
                do
                {
                    usersList = searchResults.CurrentPage.ToList();
                    foreach (IUser user in usersList)
                    {
                        Console.WriteLine("User DisplayName: {0}  UPN: {1}",
                            user.DisplayName, user.UserPrincipalName);
                    }
                    searchResults = searchResults.GetNextPageAsync().Result;
                } while (searchResults != null);
            }
            else
            {
                Console.WriteLine("User not found");
            }

            #endregion

            #region Search for Group using StartWith filter

            //*********************************************************************
            // Search for a group using a startsWith filter (displayName property)
            //*********************************************************************
            Group retrievedGroup = new Group();
            searchString = "My";
            List<IGroup> foundGroups = null;
            try
            {
                foundGroups = activeDirectoryClient.Groups
                    .Where(group => group.DisplayName.StartsWith(searchString))
                    .ExecuteAsync().Result.CurrentPage.ToList();
            }
            catch (Exception e)
            {
                Console.WriteLine("\nError getting Group {0} {1}",
                    e.Message, e.InnerException != null ? e.InnerException.Message : "");
            }
            if (foundGroups != null && foundGroups.Count > 0)
            {
                retrievedGroup = foundGroups.First() as Group;
            }
            else
            {
                Console.WriteLine("Group Not Found");
            }

            #endregion

            #region Assign Member to Group

            if (retrievedGroup.ObjectId != null)
            {
                try
                {
                    retrievedGroup.Members.Add(newUser as DirectoryObject);
                    retrievedGroup.UpdateAsync().Wait();
                }
                catch (Exception e)
                {
                    Console.WriteLine("\nError assigning member to group. {0} {1}",
                        e.Message, e.InnerException != null ? e.InnerException.Message : "");
                }

            }

            #endregion

            #region Get Group members

            if (retrievedGroup.ObjectId != null)
            {
                Console.WriteLine("\n Found Group: " + retrievedGroup.DisplayName + "  " + retrievedGroup.Description);

                //*********************************************************************
                // get the groups' membership - 
                // Note this method retrieves ALL links in one request - please use this method with care - this
                // may return a very large number of objects
                //*********************************************************************
                IGroupFetcher retrievedGroupFetcher = retrievedGroup;
                try
                {
                    IPagedCollection<IDirectoryObject> members = retrievedGroupFetcher.Members.ExecuteAsync().Result;
                    Console.WriteLine(" Members:");
                    do
                    {
                        List<IDirectoryObject> directoryObjects = members.CurrentPage.ToList();
                        foreach (IDirectoryObject member in directoryObjects)
                        {
                            if (member is User)
                            {
                                User user = member as User;
                                Console.WriteLine("User DisplayName: {0}  UPN: {1}",
                                    user.DisplayName,
                                    user.UserPrincipalName);
                            }
                            if (member is Group)
                            {
                                Group group = member as Group;
                                Console.WriteLine("Group DisplayName: {0}", group.DisplayName);
                            }
                            if (member is Contact)
                            {
                                Contact contact = member as Contact;
                                Console.WriteLine("Contact DisplayName: {0}", contact.DisplayName);
                            }
                        }
                        members = members.GetNextPageAsync().Result;
                    } while (members != null);
                }
                catch (Exception e)
                {
                    Console.WriteLine("\nError getting groups' membership. {0} {1}",
                        e.Message, e.InnerException != null ? e.InnerException.Message : "");
                }
            }

            #endregion

            #region Add User to Group

            //*********************************************************************************************
            // Add User to the "WA" Group 
            //*********************************************************************************************
            if (retrievedGroup.ObjectId != null)
            {
                try
                {
                    retrievedGroup.Members.Add(userToBeAdded as DirectoryObject);
                    retrievedGroup.UpdateAsync().Wait();
                }
                catch (Exception e)
                {
                    Console.WriteLine("\nAdding user to group failed {0} {1}", e.Message,
                        e.InnerException != null ? e.InnerException.Message : "");
                }
            }

            #endregion

            #region Create a new Group

            //*********************************************************************************************
            // Create a new Group
            //*********************************************************************************************
            Group californiaEmployees = new Group
            {
                DisplayName = "California Employees" + Helper.GetRandomString(8),
                Description = "Employees in the state of California",
                MailNickname = "CalEmployees",
                MailEnabled = false,
                SecurityEnabled = true
            };
            try
            {
                activeDirectoryClient.Groups.AddGroupAsync(californiaEmployees).Wait();
                Console.WriteLine("\nNew Group {0} was created", californiaEmployees.DisplayName);
            }
            catch (Exception e)
            {
                Console.WriteLine("\nError creating new Group {0} {1}", e.Message,
                    e.InnerException != null ? e.InnerException.Message : "");
            }

            #endregion

            #region Delete User

            //*********************************************************************************************
            // Delete the user that we just created
            //*********************************************************************************************
            if (userToBeAdded.ObjectId != null)
            {
                try
                {
                    userToBeAdded.DeleteAsync().Wait();
                    Console.WriteLine("\nUser {0} was deleted", userToBeAdded.DisplayName);
                }
                catch (Exception e)
                {
                    Console.WriteLine("Deleting User failed {0} {1}", e.Message,
                        e.InnerException != null ? e.InnerException.Message : "");
                }
            }
            if (newUser.ObjectId != null)
            {
                try
                {
                    newUser.DeleteAsync().Wait();
                    Console.WriteLine("\nUser {0} was deleted", newUser.DisplayName);
                }
                catch (Exception e)
                {
                    Console.WriteLine("Deleting User failed {0} {1}", e.Message,
                        e.InnerException != null ? e.InnerException.Message : "");
                }
            }

            #endregion

            #region Delete Group

            //*********************************************************************************************
            // Delete the Group that we just created
            //*********************************************************************************************
            if (californiaEmployees.ObjectId != null)
            {
                try
                {
                    californiaEmployees.DeleteAsync().Wait();
                    Console.WriteLine("\nGroup {0} was deleted", californiaEmployees.DisplayName);
                }
                catch (Exception e)
                {
                    Console.WriteLine("Deleting Group failed {0} {1}", e.Message,
                        e.InnerException != null ? e.InnerException.Message : "");
                }
            }

            #endregion

            #region Get All Roles

            //*********************************************************************
            // Get All Roles
            //*********************************************************************
            List<IDirectoryRole> foundRoles = null;
            try
            {
                foundRoles = activeDirectoryClient.DirectoryRoles.ExecuteAsync().Result.CurrentPage.ToList();
            }
            catch (Exception e)
            {
                Console.WriteLine("\nError getting Roles {0} {1}", e.Message,
                    e.InnerException != null ? e.InnerException.Message : "");
            }

            if (foundRoles != null && foundRoles.Count > 0)
            {
                foreach (IDirectoryRole role in foundRoles)
                {
                    Console.WriteLine("\n Found Role: {0} {1} {2} ",
                        role.DisplayName, role.Description, role.ObjectId);
                }
            }
            else
            {
                Console.WriteLine("Role Not Found {0}", searchString);
            }

            #endregion

            #region Get Service Principals

            //*********************************************************************
            // get the Service Principals
            //*********************************************************************
            IPagedCollection<IServicePrincipal> servicePrincipals = null;
            try
            {
                servicePrincipals = activeDirectoryClient.ServicePrincipals.ExecuteAsync().Result;
            }
            catch (Exception e)
            {
                Console.WriteLine("\nError getting Service Principal {0} {1}",
                    e.Message, e.InnerException != null ? e.InnerException.Message : "");
            }
            if (servicePrincipals != null)
            {
                do
                {
                    List<IServicePrincipal> servicePrincipalsList = servicePrincipals.CurrentPage.ToList();
                    foreach (IServicePrincipal servicePrincipal in servicePrincipalsList)
                    {
                        Console.WriteLine("Service Principal AppId: {0}  Name: {1}", servicePrincipal.AppId,
                            servicePrincipal.DisplayName);
                    }
                    servicePrincipals = servicePrincipals.GetNextPageAsync().Result;
                } while (servicePrincipals != null);
            }

            #endregion

            #region Get Applications

            //*********************************************************************
            // get the Application objects
            //*********************************************************************
            IPagedCollection<IApplication> applications = null;
            try
            {
                applications = activeDirectoryClient.Applications.Take(999).ExecuteAsync().Result;
            }
            catch (Exception e)
            {
                Console.WriteLine("\nError getting Applications {0} {1}", e.Message,
                    e.InnerException != null ? e.InnerException.Message : "");
            }
            if (applications != null)
            {
                do
                {
                    List<IApplication> appsList = applications.CurrentPage.ToList();
                    foreach (IApplication app in appsList)
                    {
                        Console.WriteLine("Application AppId: {0}  Name: {1}", app.AppId, app.DisplayName);
                    }
                    applications = applications.GetNextPageAsync().Result;
                } while (applications != null);
            }

            #endregion

            #region User License Assignment

            //*********************************************************************************************
            // User License Assignment - assign EnterprisePack license to new user, and disable SharePoint service
            //   first get a list of Tenant's subscriptions and find the "Enterprisepack" one
            //   Enterprise Pack includes service Plans for ExchangeOnline, SharePointOnline and LyncOnline
            //   validate that Subscription is Enabled and there are enough units left to assign to users
            //*********************************************************************************************
            IPagedCollection<ISubscribedSku> skus = null;
            try
            {
                skus = activeDirectoryClient.SubscribedSkus.ExecuteAsync().Result;
            }
            catch (Exception e)
            {
                Console.WriteLine("\nError getting Applications {0} {1}", e.Message,
                    e.InnerException != null ? e.InnerException.Message : "");
            }
            if (skus != null)
            {
                do
                {
                    List<ISubscribedSku> subscribedSkus = skus.CurrentPage.ToList();
                    foreach (ISubscribedSku sku in subscribedSkus)
                    {
                        if (sku.SkuPartNumber == "ENTERPRISEPACK")
                        {
                            if ((sku.PrepaidUnits.Enabled.Value > sku.ConsumedUnits) &&
                                (sku.CapabilityStatus == "Enabled"))
                            {
                                // create addLicense object and assign the Enterprise Sku GUID to the skuId
                                // 
                                AssignedLicense addLicense = new AssignedLicense { SkuId = sku.SkuId.Value };

                                // find plan id of SharePoint Service Plan
                                foreach (ServicePlanInfo servicePlan in sku.ServicePlans)
                                {
                                    if (servicePlan.ServicePlanName.Contains("SHAREPOINT"))
                                    {
                                        addLicense.DisabledPlans.Add(servicePlan.ServicePlanId.Value);
                                        break;
                                    }
                                }

                                IList<AssignedLicense> licensesToAdd = new[] { addLicense };
                                IList<Guid> licensesToRemove = new Guid[] { };

                                // attempt to assign the license object to the new user 
                                try
                                {
                                    if (newUser.ObjectId != null)
                                    {
                                        newUser.AssignLicenseAsync(licensesToAdd, licensesToRemove).Wait();
                                        Console.WriteLine("\n User {0} was assigned license {1}",
                                            newUser.DisplayName,
                                            addLicense.SkuId);
                                    }
                                }
                                catch (Exception e)
                                {
                                    Console.WriteLine("\nLicense assingment failed {0} {1}", e.Message,
                                        e.InnerException != null ? e.InnerException.Message : "");
                                }
                            }
                        }
                    }
                    skus = skus.GetNextPageAsync().Result;
                } while (skus != null);
            }

            #endregion

            #region Switch to OAuth Authorization Code Grant (Acting as a user)

            activeDirectoryClient = AuthenticationHelper.GetActiveDirectoryClientAsUser();

            #endregion

            #region Create Application

            //*********************************************************************************************
            // Create a new Application object with App Role Assignment (Direct permission)
            //*********************************************************************************************
            Application appObject = new Application { DisplayName = "Test-Demo App" + Helper.GetRandomString(8) };
            appObject.IdentifierUris.Add("https://localhost/demo/" + Guid.NewGuid());
            appObject.ReplyUrls.Add("https://localhost/demo");
            AppRole appRole = new AppRole();
            appRole.Id = Guid.NewGuid();
            appRole.IsEnabled = true;
            appRole.AllowedMemberTypes.Add("User");
            appRole.DisplayName = "Something";
            appRole.Description = "Anything";
            appRole.Value = "policy.write";
            appObject.AppRoles.Add(appRole);

            // created Keycredential object for the new App object
            KeyCredential keyCredential = new KeyCredential
            {
                StartDate = DateTime.UtcNow,
                EndDate = DateTime.UtcNow.AddYears(1),
                Type = "Symmetric",
                Value = Convert.FromBase64String("g/TMLuxgzurjQ0Sal9wFEzpaX/sI0vBP3IBUE/H/NS4="),
                Usage = "Verify"
            };
            appObject.KeyCredentials.Add(keyCredential);

            try
            {
                activeDirectoryClient.Applications.AddApplicationAsync(appObject).Wait();
                Console.WriteLine("New Application created: " + appObject.ObjectId);
            }
            catch (Exception e)
            {
                Console.WriteLine("Application Creation execption: {0} {1}", e.Message,
                    e.InnerException != null ? e.InnerException.Message : "");
            }

            #endregion

            #region Create Service Principal

            //*********************************************************************************************
            // create a new Service principal
            //*********************************************************************************************
            ServicePrincipal newServicePrincpal = new ServicePrincipal();
            if (appObject != null)
            {
                newServicePrincpal.DisplayName = appObject.DisplayName;
                newServicePrincpal.AccountEnabled = true;
                newServicePrincpal.AppId = appObject.AppId;
                try
                {
                    activeDirectoryClient.ServicePrincipals.AddServicePrincipalAsync(newServicePrincpal).Wait();
                    Console.WriteLine("New Service Principal created: " + newServicePrincpal.ObjectId);
                }
                catch (Exception e)
                {
                    Console.WriteLine("Service Principal Creation execption: {0} {1}", e.Message,
                        e.InnerException != null ? e.InnerException.Message : "");
                }
            }

            #endregion

            #region Create an Extension Property

            ExtensionProperty linkedInUserId = new ExtensionProperty
            {
                Name = "linkedInUserId",
                DataType = "String",
                TargetObjects = { "User" }
            };
            try
            {
                appObject.ExtensionProperties.Add(linkedInUserId);
                appObject.UpdateAsync().Wait();
                Console.WriteLine("\nUser object extended successfully.");
            }
            catch (Exception e)
            {
                Console.WriteLine("\nError extending the user object {0} {1}", e.Message,
                    e.InnerException != null ? e.InnerException.Message : "");
            }

            #endregion

            #region Manipulate an Extension Property

            try
            {
                if (retrievedUser != null && retrievedUser.ObjectId != null)
                {
                    retrievedUser.SetExtendedProperty(linkedInUserId.Name, "ExtensionPropertyValue");
                    retrievedUser.UpdateAsync().Wait();
                    Console.WriteLine("\nUser {0}'s extended property set successully.", retrievedUser.DisplayName);
                }
            }
            catch (Exception e)
            {
                Console.WriteLine("\nError Updating the user object {0} {1}", e.Message,
                    e.InnerException != null ? e.InnerException.Message : "");
            }

            #endregion

            #region Get an Extension Property

            try
            {
                if (retrievedUser != null && retrievedUser.ObjectId != null)
                {
                    IReadOnlyDictionary<string, object> extendedProperties = retrievedUser.GetExtendedProperties();
                    object extendedProperty = extendedProperties[linkedInUserId.Name];
                    Console.WriteLine("\n Retrieved User {0}'s extended property value is: {1}.", retrievedUser.DisplayName,
                        extendedProperty);
                }
            }
            catch (Exception e)
            {
                Console.WriteLine("\nError Updating the user object {0} {1}", e.Message,
                    e.InnerException != null ? e.InnerException.Message : "");
            }

            #endregion

            #region Assign Direct Permission
            try
            {
                User user =
                        (User)activeDirectoryClient.Users.ExecuteAsync().Result.CurrentPage.ToList().FirstOrDefault();
                if (appObject.ObjectId != null && user != null && newServicePrincpal.ObjectId != null)
                {
                    AppRoleAssignment appRoleAssignment = new AppRoleAssignment();
                    appRoleAssignment.Id = appRole.Id;
                    appRoleAssignment.ResourceId = Guid.Parse(newServicePrincpal.ObjectId);
                    appRoleAssignment.PrincipalType = "User";
                    appRoleAssignment.PrincipalId = Guid.Parse(user.ObjectId);
                    user.AppRoleAssignments.Add(appRoleAssignment);
                    user.UpdateAsync().Wait();
                    Console.WriteLine("User {0} is successfully assigned direct permission.", retrievedUser.DisplayName);
                }
            }
            catch (Exception e)
            {
                Console.WriteLine("Direct Permission Assignment failed: {0} {1}", e.Message,
                    e.InnerException != null ? e.InnerException.Message : "");
            }

            #endregion

            #region Get Devices

            //*********************************************************************************************
            // Get a list of Mobile Devices from tenant
            //*********************************************************************************************
            Console.WriteLine("\nGetting Devices");
            IPagedCollection<IDevice> devices = null;
            try
            {
                devices = activeDirectoryClient.Devices.ExecuteAsync().Result;
            }
            catch (Exception e)
            {
                Console.WriteLine("/nError getting devices {0} {1}", e.Message,
                    e.InnerException != null ? e.InnerException.Message : "");
            }

            if (devices != null)
            {
                do
                {
                    List<IDevice> devicesList = devices.CurrentPage.ToList();
                    foreach (IDevice device in devicesList)
                    {
                        if (device.ObjectId != null)
                        {
                            Console.WriteLine("Device ID: {0}, Type: {1}", device.DeviceId, device.DeviceOSType);
                            IPagedCollection<IDirectoryObject> registeredOwners = device.RegisteredOwners;
                            if (registeredOwners != null)
                            {
                                do
                                {
                                    List<IDirectoryObject> registeredOwnersList = registeredOwners.CurrentPage.ToList();
                                    foreach (IDirectoryObject owner in registeredOwnersList)
                                    {
                                        Console.WriteLine("Device Owner ID: " + owner.ObjectId);
                                    }
                                    registeredOwners = registeredOwners.GetNextPageAsync().Result;
                                } while (registeredOwners != null);
                            }
                        }
                    }
                    devices = devices.GetNextPageAsync().Result;
                } while (devices != null);
            }

            #endregion

            #region Create New Permission

            //*********************************************************************************************
            // Create new permission object
            //*********************************************************************************************
            OAuth2PermissionGrant permissionObject = new OAuth2PermissionGrant();
            permissionObject.ConsentType = "AllPrincipals";
            permissionObject.Scope = "user_impersonation";
            permissionObject.StartTime = DateTime.Now;
            permissionObject.ExpiryTime = (DateTime.Now).AddMonths(12);

            // resourceId is objectId of the resource, in this case objectId of AzureAd (Graph API)
            permissionObject.ResourceId = "52620afb-80de-4096-a826-95f4ad481686";

            //ClientId = objectId of servicePrincipal
            permissionObject.ClientId = newServicePrincpal.ObjectId;
            try
            {
                activeDirectoryClient.Oauth2PermissionGrants.AddOAuth2PermissionGrantAsync(permissionObject).Wait();
                Console.WriteLine("New Permission object created: " + permissionObject.ObjectId);
            }
            catch (Exception e)
            {
                Console.WriteLine("Permission Creation exception: {0} {1}", e.Message, e.InnerException != null ? e.InnerException.Message : "");
            }

            #endregion

            #region Get All Permissions

            //*********************************************************************************************
            // get all Permission Objects
            //*********************************************************************************************
            Console.WriteLine("\n Getting Permissions");
            IPagedCollection<IOAuth2PermissionGrant> permissions = null;
            try
            {
                permissions = activeDirectoryClient.Oauth2PermissionGrants.ExecuteAsync().Result;
            }
            catch (Exception e)
            {
                Console.WriteLine("Error: {0} {1}", e.Message, e.InnerException != null ? e.InnerException.Message : "");
            }
            if (permissions != null)
            {
                do
                {
                    List<IOAuth2PermissionGrant> perms = permissions.CurrentPage.ToList();
                    foreach (IOAuth2PermissionGrant perm in perms)
                    {
                        Console.WriteLine("Permission: {0}  Name: {1}", perm.ClientId, perm.Scope);
                    }
                    permissions = permissions.GetNextPageAsync().Result;
                } while (permissions != null);
            }

            #endregion

            #region Delete Application

            //*********************************************************************************************
            // Delete Application Objects
            //*********************************************************************************************
            if (appObject.ObjectId != null)
            {
                try
                {
                    appObject.DeleteAsync().Wait();
                    Console.WriteLine("Deleted Application object: " + appObject.ObjectId);
                }
                catch (Exception e)
                {
                    Console.WriteLine("Application Deletion execption: {0} {1}", e.Message,
                        e.InnerException != null ? e.InnerException.Message : "");
                }
            }

            #endregion

            #region Batch Operations

            //*********************************************************************************************
            // Show Batching with 3 operators.  Note: up to 5 operations can be in a batch
            //*********************************************************************************************
            IReadOnlyQueryableSet<User> userQuery = activeDirectoryClient.DirectoryObjects.OfType<User>();
            IReadOnlyQueryableSet<Group> groupsQuery = activeDirectoryClient.DirectoryObjects.OfType<Group>();
            IReadOnlyQueryableSet<DirectoryRole> rolesQuery =
                activeDirectoryClient.DirectoryObjects.OfType<DirectoryRole>();
            try
            {
                IBatchElementResult[] batchResult =
                    activeDirectoryClient.Context.ExecuteBatchAsync(userQuery, groupsQuery, rolesQuery).Result;
                int responseCount = 1;
                foreach (IBatchElementResult result in batchResult)
                {
                    if (result.FailureResult != null)
                    {
                        Console.WriteLine("Failed: {0} ",
                            result.FailureResult.InnerException);
                    }
                    if (result.SuccessResult != null)
                    {
                        Console.WriteLine("Batch Item Result {0} succeeded",
                            responseCount++);
                    }
                }
            }
            catch (Exception e)
            {
                Console.WriteLine("Batch execution failed. : {0} {1}", e.Message,
                    e.InnerException != null ? e.InnerException.Message : "");
            }

            #endregion

            //*********************************************************************************************
            // End of Demo Console App
            //*********************************************************************************************

            Console.WriteLine("\nCompleted at {0} \n Press Any Key to Exit.", currentDateTime);
            Console.ReadKey();
        }
        private static async Task <DeviceIdentity> CreateDeviceIdentityInCustomerTenantAsync(string deviceIdentityProvisioningAppId)
        {
            // Create the MSAL public client application to allow the customer tenant administrator to sign in.
            // https://github.com/AzureAD/microsoft-authentication-library-for-dotnet/wiki/System-Browser-on-.Net-Core
            var client = PublicClientApplicationBuilder.Create(deviceIdentityProvisioningAppId)
                         .WithRedirectUri("http://localhost")                     // Required for MSAL
                         .WithAuthority(AadAuthorityAudience.AzureAdMultipleOrgs) // For multi-tenant applications (excluding consumer accounts)
                         .Build();

            // Create the Graph Service client with an interactive authentication provider that uses the MSAL public client application.
            // Creating an Application or Service Principal using Delegated Permissions requires Application.ReadWrite.All, Directory.AccessAsUser.All (both require admin consent in the target tenant):
            // - https://docs.microsoft.com/en-us/graph/api/application-post-applications?view=graph-rest-1.0&tabs=http
            // - https://docs.microsoft.com/en-us/graph/api/serviceprincipal-post-serviceprincipals?view=graph-rest-1.0&tabs=http)
            // Note that these are the required permissions to create the device identity in the target tenant, which is unrelated from the final permissions the device will get.
            var scopes       = new[] { "Application.ReadWrite.All", "Directory.AccessAsUser.All" };
            var graphService = new GraphServiceClient(new InteractiveAuthenticationProvider(client, scopes, Microsoft.Identity.Client.Prompt.SelectAccount));

            // Get information about the customer tenant.
            var currentOrganization = (await graphService.Organization.Request().GetAsync()).Single();
            var currentTenantId     = currentOrganization.Id;

            // Register an application representing the device.
            var deviceIdentityApplication = new Application
            {
                DisplayName            = $"Device {Guid.NewGuid().ToString()}",
                Description            = "Created by Device Identity Provisioning Service",
                SignInAudience         = "AzureADMyOrg", // Limit exposure of this app registration to the customer tenant
                RequiredResourceAccess = new[]
                {
                    // Specify which permissions the device will ultimately need; in this case we use certain Graph API permissions to prove the point but this could be any Application Permission on any API.
                    new RequiredResourceAccess
                    {
                        ResourceAppId  = "00000003-0000-0000-c000-000000000000", // Request that the device can access the Microsoft Graph API
                        ResourceAccess = new []
                        {
                            new ResourceAccess {
                                Type = "Role", Id = new Guid("798ee544-9d2d-430c-a058-570e29e34338")
                            },                                                                                           // Request an Application Permission (i.e. "Role") for the permission "Calendars.Read"
                            new ResourceAccess {
                                Type = "Role", Id = new Guid("df021288-bdef-4463-88db-98f22de89214")
                            },                                                                                           // Request an Application Permission (i.e. "Role") for the permission "User.Read.All"
                        }
                    }
                }
            };

            deviceIdentityApplication = await graphService.Applications.Request().AddAsync(deviceIdentityApplication);

            Console.WriteLine($"Application created for device \"{deviceIdentityApplication.DisplayName}\": App ID = \"{deviceIdentityApplication.AppId}\"");
            await Task.Delay(1000); // Safety buffer

            // Create a client credential for the device.
            // https://docs.microsoft.com/en-us/graph/api/application-addpassword?view=graph-rest-1.0&tabs=http
            var clientCredential = await graphService.Applications[deviceIdentityApplication.Id].AddPassword(new PasswordCredential()).Request().PostAsync();

            Console.WriteLine($"Credential created for device: Client Secret = \"{clientCredential.SecretText}\"");
            await Task.Delay(1000); // Safety buffer

            // Create the Service Principal for the device's app registration, as this will ultimately receive the required permissions (App Roles).
            var deviceIdentityServicePrincipal = await graphService.ServicePrincipals.Request().AddAsync(new ServicePrincipal {
                AppId = deviceIdentityApplication.AppId
            });

            Console.WriteLine($"Service Principal created for device: ID = \"{deviceIdentityApplication.Id}\"");
            await Task.Delay(1000); // Safety buffer

            // Perform an admin consent (i.e. add the App Role Assignment) using the customer tenant admin's privileges for each requested resource access in the device app registration.
            foreach (var requiredResourceAccess in deviceIdentityApplication.RequiredResourceAccess)
            {
                // Look up the Service Principal of the Resource AppId in the target tenant.
                var targetResourceServicePrincipal = (await graphService.ServicePrincipals.Request().Filter($"appId eq '{requiredResourceAccess.ResourceAppId}'").GetAsync()).Single();

                // Create the App Role Assignment for each requested resource.
                foreach (var appRole in requiredResourceAccess.ResourceAccess)
                {
                    var deviceAppRoleAssignment = new AppRoleAssignment
                    {
                        AppRoleId   = appRole.Id,
                        PrincipalId = new Guid(deviceIdentityServicePrincipal.Id),
                        ResourceId  = new Guid(targetResourceServicePrincipal.Id)
                    };
                    // https://docs.microsoft.com/en-us/graph/api/serviceprincipal-post-approleassignments?view=graph-rest-1.0&tabs=http
                    deviceAppRoleAssignment = await graphService.ServicePrincipals[deviceIdentityServicePrincipal.Id].AppRoleAssignments.Request().AddAsync(deviceAppRoleAssignment);
                }
            }

            return(new DeviceIdentity
            {
                DisplayName = deviceIdentityApplication.DisplayName,
                Id = deviceIdentityApplication.Id,
                AppId = deviceIdentityApplication.AppId,
                TenantId = currentTenantId,
                ClientSecret = clientCredential.SecretText,
                CreatedDateTime = deviceIdentityApplication.CreatedDateTime
            });
        }