/// <summary>
        /// Create consumer user accounts
        /// When creating user accounts in a B2C tenant, you can send an HTTP POST request to the /users endpoint
        /// </summary>
        public async Task <bool> UpdateAccount(string objectId,
                                               string city)
        {
            if (string.IsNullOrEmpty(objectId))
            {
                throw new Exception("You must provide user's objectId");
            }

            try
            {
                // Create Graph json string from object
                GraphAccountModel graphUserModel = new GraphAccountModel()
                {
                    City = city
                };

                // Send the json to Graph API end point
                await SendGraphRequest($"/users/{objectId}", null, graphUserModel.ToString(), new HttpMethod("PATCH"));

                return(true);
            }
            catch (Exception ex)
            {
                // TBD: Error handling
                throw;
            }
        }
Пример #2
0
 public UserViewModel(GraphAccountModel account)
 {
     Id        = account.Id;
     Email     = account.OtherMails.FirstOrDefault();
     FirstName = account.GivenName;
     LastName  = account.Surname;
 }
Пример #3
0
        public async Task<ActionResult> Edit(string emailAddress)
        {
            AccountModel model;
            B2CGraphClient b2CGraphClient = new B2CGraphClient(_tenant, _clientId, _clientSecret);
            GraphAccountModel user = await b2CGraphClient.GetUser(emailAddress);

            if (user != null)
            {
                model = new AccountModel()
                {
                    signInName = user.signInNames[0].value,
                    displayName = user.displayName,
                    firstName = user.givenName,
                    lastName = user.surname,
                    extension_jdrfConsId = user.extension_jdrfConsId
                };
            }
            else
            {
                return RedirectToAction("Find");
            }

            return View(model);
        }
Пример #4
0
        public async Task <ActionResult> LoalAccountPasswordReset()
        {
            string input = null;

            // If not data came in, then return
            if (this.Request.Body == null)
            {
                return(StatusCode((int)HttpStatusCode.Conflict, new B2CResponseModel("Request content is null", HttpStatusCode.Conflict)));
            }

            // Read the input claims from the request body
            using (StreamReader reader = new StreamReader(Request.Body, Encoding.UTF8))
            {
                input = await reader.ReadToEndAsync();
            }

            // Check input content value
            if (string.IsNullOrEmpty(input))
            {
                return(StatusCode((int)HttpStatusCode.Conflict, new B2CResponseModel("Request content is empty", HttpStatusCode.Conflict)));
            }

            // Convert the input string into InputClaimsModel object
            InputClaimsModel inputClaims = InputClaimsModel.Parse(input);

            if (inputClaims == null)
            {
                return(StatusCode((int)HttpStatusCode.Conflict, new B2CResponseModel("Can not deserialize input claims", HttpStatusCode.Conflict)));
            }

            if (string.IsNullOrEmpty(inputClaims.signInName))
            {
                return(StatusCode((int)HttpStatusCode.Conflict, new B2CResponseModel("User 'signInName' is null or empty", HttpStatusCode.Conflict)));
            }

            if (string.IsNullOrEmpty(inputClaims.signInName))
            {
                return(StatusCode((int)HttpStatusCode.Conflict, new B2CResponseModel("Password is null or empty", HttpStatusCode.Conflict)));
            }

            // Create a retrieve operation that takes a customer entity.
            // Note: Azure Blob Table query is case sensitive, always set the input email to lower case
            var retrieveOperation = TableOperation.Retrieve <UserTableEntity>(Consts.MigrationTablePartition, inputClaims.signInName.ToLower());

            CloudTable table = await GetSignUpTable(this.AppSettings.BlobStorageConnectionString);

            // Execute the retrieve operation.
            TableResult userMigrationEntity = await table.ExecuteAsync(retrieveOperation);

            if (userMigrationEntity != null && userMigrationEntity.Result != null)
            {
                try
                {
                    try
                    {
                        await MigrateUser(inputClaims, table, userMigrationEntity);

                        // Wait until user is created
                        await Task.Delay(3000);
                    }
                    catch (Exception ex)
                    {
                        return(StatusCode((int)HttpStatusCode.Conflict, new B2CResponseModel("Can not migrate user", HttpStatusCode.Conflict)));
                    }
                }
                catch (Exception ex)
                {
                    return(StatusCode((int)HttpStatusCode.Conflict, new B2CResponseModel($"User migration error: {ex.Message}", HttpStatusCode.Conflict)));
                }
            }

            AzureADGraphClient azureADGraphClient = new AzureADGraphClient(this.AppSettings.Tenant, this.AppSettings.ClientId, this.AppSettings.ClientSecret);

            GraphAccountModel account = await azureADGraphClient.SearcUserBySignInNames(inputClaims.signInName);

            if (account == null)
            {
                return(StatusCode((int)HttpStatusCode.Conflict, new B2CResponseModel($"An account could not be found for the provided user ID. (user migration)", HttpStatusCode.Conflict)));
            }

            OutputClaimsModel output = new OutputClaimsModel();

            output.objectId = account.objectId;

            return(Ok(output));
        }
Пример #5
0
        public async Task <bool> UpdateAccount(
            string objectId,
            string userType,
            string signInName,
            string issuer,
            string issuerUserId,
            string email,
            string password,
            string displayName,
            string givenName,
            string surname,
            bool isActivated)
        {
            if (string.IsNullOrEmpty(signInName) && string.IsNullOrEmpty(issuerUserId))
            {
                throw new Exception("You must provide user's signInName or issuerUserId");
            }

            if (string.IsNullOrEmpty(displayName) || displayName.Length < 1)
            {
                throw new Exception("Dispay name is NULL or empty, you must provide valid dislay name");
            }

            try
            {
                // Create Graph json string from object
                GraphAccountModel graphUserModel = new GraphAccountModel(
                    Tenant,
                    userType,
                    signInName,
                    issuer,
                    issuerUserId,
                    email,
                    password,
                    displayName,
                    givenName,
                    surname);

                graphUserModel.objectId       = objectId;
                graphUserModel.accountEnabled = isActivated;


                // Send the json to Graph API end point
                await SendGraphRequest(string.Format("/users/{0}", graphUserModel.objectId), null, graphUserModel.ToString(), new HttpMethod("PATCH"));

                Console.WriteLine($"Azure AD user account '{displayName}' updated");

                return(true);
            }
            catch (Exception ex)
            {
                if (ex.Message.Contains("ObjectConflict"))
                {
                    if (ex.Message.Contains("signInNames "))
                    {
                        // TBD: Chnage to trace
                        Console.WriteLine($"User with same signInNames '{signInName}' already exists in Azure AD");
                    }
                    else if (ex.Message.Contains("userIdentities "))
                    {
                        // TBD: Chnage to trace
                        Console.WriteLine($"User with same userIdentities '{issuerUserId}' already exists in Azure AD");
                    }
                    else if (ex.Message.Contains("one or more"))
                    {
                        // TBD: Chnage to trace
                        Console.WriteLine($"User with same userIdentities '{issuerUserId}', and signInNames '{signInName}'  already exists in Azure AD");
                    }
                }

                return(false);
            }
        }
Пример #6
0
        public IHttpActionResult Migrate()
        {
            string input = Request.Content.ReadAsStringAsync().Result;

            // If not data came in, then return
            if (this.Request.Content == null)
            {
                return(Content(HttpStatusCode.Conflict, new B2CResponseModel("Request content is null", HttpStatusCode.Conflict)));
            }

            //// Read the input claims from the request body
            //using (StreamReader reader = new StreamReader(Request.Body, Encoding.UTF8))
            //{
            //    input = await reader.ReadToEndAsync();
            //}

            // Check input content value
            if (string.IsNullOrEmpty(input))
            {
                return(Content(HttpStatusCode.Conflict, new B2CResponseModel("Request content is empty", HttpStatusCode.Conflict)));
            }

            // Convert the input string into InputClaimsModel object
            InputClaimsModel inputClaims = InputClaimsModel.Parse(input);

            if (inputClaims == null)
            {
                return(Content(HttpStatusCode.Conflict, new B2CResponseModel("Can not deserialize input claims", HttpStatusCode.Conflict)));
            }

            if (string.IsNullOrEmpty(inputClaims.signInName))
            {
                return(Content(HttpStatusCode.Conflict, new B2CResponseModel("User 'signInName' is null or empty", HttpStatusCode.Conflict)));
            }

            //if (string.IsNullOrEmpty(inputClaims.password))
            //{
            //    return Content(HttpStatusCode.Conflict, new B2CResponseModel("Password is null or empty", HttpStatusCode.Conflict));
            //}


            AzureADGraphClient azureADGraphClient = new AzureADGraphClient(ConfigurationManager.AppSettings["Tenant"],
                                                                           ConfigurationManager.AppSettings["ClientId"],
                                                                           ConfigurationManager.AppSettings["ClientSecret"]);

            GraphAccountModel account = azureADGraphClient.SearcUserBySignInNames(inputClaims.signInName).Result;

            // User already exists, no need to migrate.
            if (account != null)
            {
                return(Ok());
            }

            B2CResponseModel outputClaimsCol = new B2CResponseModel("", HttpStatusCode.OK);

            Ldap.Controllers.ValuesController tmp = new Ldap.Controllers.ValuesController();
            outputClaimsCol.isMigrated = false;
            outputClaimsCol.email      = inputClaims.signInName;

            //Only migrate account that is not migrated already, and verified successfully within the local LDAP store.
            if (account == null && tmp.VerifyCredentials(inputClaims.signInName, inputClaims.password))
            {
                inputClaims.sn        = "EID";
                inputClaims.givenName = inputClaims.signInName;
                inputClaims.email     = string.Format("{0}@noreply.com", inputClaims.signInName);

                bool result = MigrateUser(azureADGraphClient, inputClaims);
                if (result)
                {
                    outputClaimsCol.displayName = inputClaims.sn;
                    outputClaimsCol.givenName   = inputClaims.givenName;
                    outputClaimsCol.surName     = inputClaims.email;
                    outputClaimsCol.password    = inputClaims.password;
                    outputClaimsCol.isMigrated  = true;
                }
            }
            return(Ok(outputClaimsCol));

            //// Initiate the output claim object
            //B2CResponseModel outputClaims = new B2CResponseModel("", HttpStatusCode.OK);
            //outputClaims.newPassword = inputClaims.password;
            //outputClaims.email = inputClaims.signInName;
            //outputClaims.needToMigrate = "null";

            //Ldap.Controllers.ValuesController tmp = new Ldap.Controllers.ValuesController();
            //if (tmp.VerifyCredentials(inputClaims.signInName, inputClaims.password))
            //{

            //    outputClaims.givenName = "Test " + DateTime.UtcNow.ToLongTimeString();
            //    outputClaims.surName = "User " + DateTime.UtcNow.ToLongDateString();
            //    outputClaims.needToMigrate = "local";
            //}



            //outputClaims.displayName = userMigrationEntity.DisplayName;
            //outputClaims.surName = userMigrationEntity.LastName;
            //outputClaims.givenName = userMigrationEntity.FirstName;

            // Create a retrieve operation that takes a customer entity.
            // Note: Azure Blob Table query is case sensitive, always set the input email to lower case
            //var retrieveOperation = TableOperation.Retrieve<UserTableEntity>(Consts.MigrationTablePartition, inputClaims.signInName.ToLower());

            //CloudTable table = await GetSignUpTable(this.AppSettings.BlobStorageConnectionString);

            // Execute the retrieve operation.
            //TableResult tableEntity = await table.ExecuteAsync(retrieveOperation);

            //TableResult tableEntity = null;

            //if (tableEntity != null && tableEntity.Result != null)
            //{
            //    UserTableEntity userMigrationEntity = ((UserTableEntity)tableEntity.Result);
            //    try
            //    {
            //        outputClaims.needToMigrate = "local";

            //        // Compare the password entered by the user and the one in the migration table.
            //        // Don't compare in password reset flow (useInputPassword is true)
            //        if (inputClaims.useInputPassword || (inputClaims.password == userMigrationEntity.Password))
            //        {
            //            outputClaims.newPassword = inputClaims.password;
            //            outputClaims.email = inputClaims.signInName;
            //            outputClaims.displayName = userMigrationEntity.DisplayName;
            //            outputClaims.surName = userMigrationEntity.LastName;
            //            outputClaims.givenName = userMigrationEntity.FirstName;

            //            // Remove the user entity from migration table
            //            TableOperation deleteOperation = TableOperation.Delete((UserTableEntity)tableEntity.Result);
            //            //await table.ExecuteAsync(deleteOperation);
            //        }
            //        else
            //        {
            //            return Content(HttpStatusCode.Conflict, new B2CResponseModel("Your password is incorrect (migration API)", HttpStatusCode.Conflict));
            //        }
            //    }
            //    catch (Exception ex)
            //    {
            //        return Content(HttpStatusCode.Conflict, new B2CResponseModel($"User migration error: {ex.Message}", HttpStatusCode.Conflict));
            //    }
            //}

            //return Ok(outputClaims);
        }
Пример #7
0
        private IHttpActionResult ProcessRequest()
        {
            string input = Request.Content.ReadAsStringAsync().Result;

            // If not data came in, then return
            if (this.Request.Content == null)
            {
                return(Content(HttpStatusCode.Conflict, new B2CResponseModel("Request content is null", HttpStatusCode.Conflict)));
            }

            //// Read the input claims from the request body
            //using (StreamReader reader = new StreamReader(Request.Body, Encoding.UTF8))
            //{
            //    input = await reader.ReadToEndAsync();
            //}

            // Check input content value
            if (string.IsNullOrEmpty(input))
            {
                return(Content(HttpStatusCode.Conflict, new B2CResponseModel("Request content is empty", HttpStatusCode.Conflict)));
            }

            // Convert the input string into InputClaimsModel object
            PeopleSoftInputClaimsModel inputClaims = PeopleSoftInputClaimsModel.Parse(input);

            if (inputClaims == null)
            {
                return(Content(HttpStatusCode.Conflict, new B2CResponseModel("Can not deserialize input claims", HttpStatusCode.Conflict)));
            }

            if (string.IsNullOrEmpty(inputClaims.uid))
            {
                return(Content(HttpStatusCode.Conflict, new B2CResponseModel("User 'uid' is null or empty", HttpStatusCode.Conflict)));
            }

            if (string.IsNullOrEmpty(inputClaims.password))
            {
                return(Content(HttpStatusCode.Conflict, new B2CResponseModel("Password is null or empty", HttpStatusCode.Conflict)));
            }

            //bool isEmail = Regex.IsMatch(emailString, @"\A(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?)\Z", RegexOptions.IgnoreCase);

            if (string.IsNullOrEmpty(inputClaims.email) ||
                !Regex.IsMatch(inputClaims.email, @"\A(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?)\Z", RegexOptions.IgnoreCase))
            {
                return(Content(HttpStatusCode.Conflict, new B2CResponseModel("Email is empty or not in the correct format", HttpStatusCode.Conflict)));
            }

            AzureADGraphClient azureADGraphClient = new AzureADGraphClient(ConfigurationManager.AppSettings["Tenant"],
                                                                           ConfigurationManager.AppSettings["ClientId"],
                                                                           ConfigurationManager.AppSettings["ClientSecret"]);

            GraphAccountModel          account         = azureADGraphClient.SearcUserBySignInNames(inputClaims.uid).Result;
            B2CPeopleSoftResponseModel outputClaimsCol = new B2CPeopleSoftResponseModel("", HttpStatusCode.OK);

            Ldap.Controllers.ValuesController tmp = new Ldap.Controllers.ValuesController();
            outputClaimsCol.isMigrated = false;
            outputClaimsCol.username   = inputClaims.uid;


            //Only migrate account that is not migrated already, and verified successfully within the local LDAP store.
            if (account == null)
            {
                inputClaims.givenname = GetClaimValue(inputClaims.givenname);
                inputClaims.sn        = GetClaimValue(inputClaims.sn);

                bool result = CreateUser(azureADGraphClient, inputClaims);
                if (result)
                {
                    outputClaimsCol.password    = GetClaimValue(inputClaims.password);
                    outputClaimsCol.displayName = GetClaimValue(inputClaims.sn);
                    outputClaimsCol.email       = inputClaims.email;
                    outputClaimsCol.givenName   = inputClaims.givenname;
                    outputClaimsCol.surName     = inputClaims.givenname;
                    outputClaimsCol.isMigrated  = false;
                }
            }
            //Update user
            else
            {
                //TODO: Check for pasword as may want to stop update to it.
                inputClaims.givenname   = inputClaims.givenname == null ? account.surname : inputClaims.givenname;
                inputClaims.sn          = inputClaims.sn == null ? account.displayName : inputClaims.sn;
                inputClaims.email       = inputClaims.email == null ? account.givenName : inputClaims.email;
                inputClaims.isActivated = inputClaims.isActivated == null ? account.accountEnabled : inputClaims.isActivated;


                bool result = UpdateUser(azureADGraphClient, inputClaims, account.objectId);
                if (result)
                {
                    outputClaimsCol.password    = GetClaimValue(inputClaims.password);
                    outputClaimsCol.displayName = GetClaimValue(inputClaims.sn);
                    outputClaimsCol.email       = inputClaims.email;
                    outputClaimsCol.givenName   = inputClaims.givenname;
                    outputClaimsCol.surName     = inputClaims.givenname;
                    outputClaimsCol.isActivated = (bool)inputClaims.isActivated;
                    //outputClaimsCol.isMigrated = false;
                }
                //return Content(HttpStatusCode.Conflict, new B2CResponseModel($"User already exists {inputClaims.uid}", HttpStatusCode.Conflict));
            }
            return(Ok(outputClaimsCol));
        }
Пример #8
0
        /// <summary>
        /// Migrate users with random password
        /// </summary>
        /// <returns></returns>
        static async Task MigrateUsersWithRandomPasswordAsync()
        {
            string appDirecotyPath = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
            string dataFilePath    = Path.Combine(appDirecotyPath, Program.MigrationFile);

            // Check file existence
            if (!File.Exists(dataFilePath))
            {
                Console.ForegroundColor = ConsoleColor.Red;
                Console.WriteLine($"File '{dataFilePath}' not found");
                Console.ResetColor();
                return;
            }

            // Read the data file and convert to object
            LocalAccountsModel users = LocalAccountsModel.Parse(File.ReadAllText(dataFilePath));

            // Create B2C graph client object
            B2CGraphClient b2CGraphClient = new B2CGraphClient(Program.Tenant, Program.ClientId, Program.ClientSecret);

            // Create Search client object
            SearchClient searchClient = new SearchClient(new Uri(ConfigurationManager.AppSettings["AZURE_SEARCH_URI"]), ConfigurationManager.AppSettings["AZURE_SEARCH_INDEX"], new AzureKeyCredential(ConfigurationManager.AppSettings["AZURE_SEARCH_KEY"]));

            int successes = 0;
            int fails     = 0;

            foreach (var item in users.Users)
            {
                GraphAccountModel newUser = await b2CGraphClient.CreateAccount(users.userType,
                                                                               item.signInName,
                                                                               item.issuer,
                                                                               item.issuerUserId,
                                                                               item.email,
                                                                               item.password,
                                                                               item.displayName,
                                                                               item.firstName,
                                                                               item.lastName,
                                                                               item.extension_Organization,
                                                                               item.extension_UserRole,
                                                                               true);

                if (newUser != null)
                {
                    // Update the Azure Search Index
                    string signInName = string.Empty;
                    string issuer     = string.Empty;
                    string issuerId   = string.Empty;
                    string email      = string.Empty;
                    if (newUser.signInNames != null && newUser.signInNames.Count > 0)
                    {
                        signInName = newUser.signInNames[0].value;
                    }
                    if (newUser.userIdentities != null && newUser.userIdentities.Count > 0)
                    {
                        issuer   = newUser.userIdentities[0].issuer;
                        issuerId = newUser.userIdentities[0].issuerUserId;
                    }
                    if (newUser.otherMails != null && newUser.otherMails.Count > 0)
                    {
                        email = newUser.otherMails[0];
                    }
                    Document document = new Document()
                    {
                        id           = newUser.objectId,
                        signInName   = signInName,
                        issuer       = issuer,
                        issuerId     = issuerId,
                        email        = email,
                        displayName  = newUser.displayName,
                        firstName    = newUser.givenName,
                        lastName     = newUser.surname,
                        organization = newUser.extension_Organization,
                        userRole     = newUser.extension_UserRole
                    };
                    List <Document> documents = new List <Document>()
                    {
                        document
                    };
                    IndexDocumentsResult indexResults = await searchClient.MergeOrUploadDocumentsAsync(documents);

                    successes += 1;
                }
                else
                {
                    fails += 1;
                }
            }

            Console.ForegroundColor = ConsoleColor.Yellow;
            Console.WriteLine($"\r\nUsers migration report:\r\n\tSuccesses: {successes}\r\n\tFails: {fails} ");
            Console.ResetColor();
        }
        public async Task <ActionResult> SignUp()
        {
            string input = null;

            // If not data came in, then return
            if (this.Request.Body == null)
            {
                return(StatusCode((int)HttpStatusCode.Conflict, new B2CResponseModel("Request content is null", HttpStatusCode.Conflict)));
            }

            // Read the input claims from the request body
            using (StreamReader reader = new StreamReader(Request.Body, Encoding.UTF8))
            {
                input = await reader.ReadToEndAsync();
            }

            // Check input content value
            if (string.IsNullOrEmpty(input))
            {
                return(StatusCode((int)HttpStatusCode.Conflict, new B2CResponseModel("Request content is empty", HttpStatusCode.Conflict)));
            }

            // Convert the input string into InputClaimsModel object
            InputClaimsModel inputClaims = InputClaimsModel.Parse(input);

            if (inputClaims == null)
            {
                return(StatusCode((int)HttpStatusCode.Conflict, new B2CResponseModel("Can not deserialize input claims", HttpStatusCode.Conflict)));
            }

            if (string.IsNullOrEmpty(inputClaims.signInName))
            {
                return(StatusCode((int)HttpStatusCode.Conflict, new B2CResponseModel("User 'signInName' is null or empty", HttpStatusCode.Conflict)));
            }

            if (string.IsNullOrEmpty(inputClaims.password))
            {
                return(StatusCode((int)HttpStatusCode.Conflict, new B2CResponseModel("Password is null or empty", HttpStatusCode.Conflict)));
            }

            try
            {
                AzureADGraphClient azureADGraphClient = new AzureADGraphClient(this.AppSettings.Tenant, this.AppSettings.ClientId, this.AppSettings.ClientSecret);

                GraphAccountModel account = await azureADGraphClient.SearcUserBySignInNames(inputClaims.signInName);

                // Return an error if user already exists
                if (account != null)
                {
                    return(StatusCode((int)HttpStatusCode.Conflict, new B2CResponseModel($"A user with the specified ID already exists. Please choose a different one. (REST API)", HttpStatusCode.Conflict)));
                }

                // If user is not exist, return the password back to B2C
                OutputClaimsModel outputClaims = new OutputClaimsModel()
                {
                    password = inputClaims.password
                };
                return(Ok(outputClaims));
            }
            catch (Exception ex)
            {
                return(StatusCode((int)HttpStatusCode.Conflict, new B2CResponseModel($"General error (REST API): {ex.Message}", HttpStatusCode.Conflict)));
            }
        }