Exemplo n.º 1
0
        public async Task <ActionResult> Generate()
        {
            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)));
            }

            try
            {
                // Define the URL for the QR code. When user scan this URL, it opens one of the
                // authentication apps running on the mobile device
                byte[] secretKey = KeyGeneration.GenerateRandomKey(20);

                string TOTPUrl = KeyUrl.GetTotpUrl(secretKey, $"{AppSettings.TOTPAccountPrefix}:{inputClaims.userName}",
                                                   AppSettings.TOTPTimestep);

                TOTPUrl = $"{TOTPUrl}&issuer={AppSettings.TOTPIssuer.Replace(" ", "%20")}";

                // Generate QR code for the above URL
                var              qrCodeGenerator = new QRCodeGenerator();
                QRCodeData       qrCodeData      = qrCodeGenerator.CreateQrCode(TOTPUrl, QRCodeGenerator.ECCLevel.L);
                BitmapByteQRCode qrCode          = new BitmapByteQRCode(qrCodeData);
                byte[]           qrCodeBitmap    = qrCode.GetGraphic(4);

                B2CResponseModel output = new B2CResponseModel(string.Empty, HttpStatusCode.OK)
                {
                    qrCodeBitmap = Convert.ToBase64String(qrCodeBitmap),
                    secretKey    = this.EncryptAndBase64(Convert.ToBase64String(secretKey))
                };

                return(Ok(output));
            }
            catch (Exception ex)
            {
                return(StatusCode((int)HttpStatusCode.Conflict, new B2CResponseModel($"General error (REST API): {ex.Message}", HttpStatusCode.Conflict)));
            }
        }
Exemplo n.º 2
0
        public IHttpActionResult Validate()
        {
            // Check the certificate
            if (IsValidClientCertificate() == false)
            {
                return(Content(HttpStatusCode.Conflict, new B2CResponseModel("Your client certificate is not valid", HttpStatusCode.Conflict)));
            }

            // If not data came in, then returen
            if (this.Request.Content == null)
            {
                throw new Exception();
            }

            // Read the input claims from the request body
            string input = Request.Content.ReadAsStringAsync().Result;

            // 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 = JsonConvert.DeserializeObject(input, typeof(InputClaimsModel)) as InputClaimsModel;

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

            //Check if the language parameter is presented
            if (string.IsNullOrEmpty(inputClaims.language))
            {
                return(Content(HttpStatusCode.Conflict, new B2CResponseModel("Language code is null or empty", HttpStatusCode.Conflict)));
            }

            //Check if the email parameter is presented
            if (string.IsNullOrEmpty(inputClaims.email))
            {
                return(Content(HttpStatusCode.Conflict, new B2CResponseModel("Email is null or empty", HttpStatusCode.Conflict)));
            }

            // Validate the email address
            if (inputClaims.email.ToLower().StartsWith("test"))
            {
                return(Content(HttpStatusCode.Conflict, new B2CResponseModel("Your email address can't start with 'test'", HttpStatusCode.Conflict)));
            }

            // Create output claims object and set the loyalty number with random value
            B2CResponseModel outputClaims = new B2CResponseModel(string.Empty, HttpStatusCode.OK);

            outputClaims.loyaltyNumber = inputClaims.language + "-" + rnd.Next(1000, 9999).ToString();
            outputClaims.email         = inputClaims.email.ToLower();

            // Return the output claim(s)
            return(Ok(outputClaims));
        }
Exemplo n.º 3
0
        public async Task <IActionResult> GenerateAsync(
            [HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = "totp/generate")]
            HttpRequest request, ILogger log)
        {
            log.LogInformation("Start QrCode Generate Function.");

            if (request.Body is null)
            {
                return(StatusCode((int)HttpStatusCode.Conflict, new B2CResponseModel("Request content is null", HttpStatusCode.Conflict)));
            }

            var input = await new StreamReader(request.Body, Encoding.UTF8).ReadToEndAsync();

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

            var inputClaims = InputClaimsModel.Parse(input);

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

            try
            {
                var secretKey = KeyGeneration.GenerateRandomKey(20);

                var TOTPUrl = GetTotpUrl(secretKey
                                         , inputClaims.UserName
                                         , _options.TOTPIssuer
                                         , _options.TOTPTimestep
                                         , _options.TOTPAccountPrefix);

                // Generate QR code for the above URL
                var qrCodeGenerator = new QRCodeGenerator();
                var qrCodeData      = qrCodeGenerator.CreateQrCode(TOTPUrl, QRCodeGenerator.ECCLevel.L);
                var qrCode          = new BitmapByteQRCode(qrCodeData);
                var qrCodeBitmap    = qrCode.GetGraphic(4);

                var output = new B2CResponseModel(string.Empty, HttpStatusCode.OK)
                {
                    QrCodeBitmap = Convert.ToBase64String(qrCodeBitmap),
                    SecretKey    = EncryptAndBase64(Convert.ToBase64String(secretKey))
                };

                return(Ok(output));
            }
            catch (Exception e)
            {
                return(StatusCode((int)HttpStatusCode.Conflict, new B2CResponseModel($"General error (REST API): {e.Message}", HttpStatusCode.Conflict)));
            }
        }
Exemplo n.º 4
0
        public IHttpActionResult Loyalty()
        {
            // If not data came in, then returen
            if (this.Request.Content == null)
            {
                throw new Exception();
            }

            // Read the input claims from the request body
            string input = Request.Content.ReadAsStringAsync().Result;

            // 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 = JsonConvert.DeserializeObject(input, typeof(InputClaimsModel)) as InputClaimsModel;

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

            //Check if the language parameter is presented
            if (string.IsNullOrEmpty(inputClaims.language))
            {
                return(Content(HttpStatusCode.Conflict, new B2CResponseModel("Language code is null or empty", HttpStatusCode.Conflict)));
            }

            //Check if the objectId parameter is presented
            if (string.IsNullOrEmpty(inputClaims.objectId))
            {
                return(Content(HttpStatusCode.Conflict, new B2CResponseModel("User object Id is null or empty", HttpStatusCode.Conflict)));
            }

            // Create output claims object and set the loyalty number with random value
            B2CResponseModel outputClaims = new B2CResponseModel(string.Empty, HttpStatusCode.OK);

            outputClaims.loyaltyNumber = inputClaims.language + "-" + rnd.Next(1000, 9999).ToString();

            // Return the output claim(s)
            return(Ok(outputClaims));
        }
Exemplo n.º 5
0
        public async Task <ActionResult> LoginCallbackJSON()
        {
            string input = null;

            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
            CallbackClaimsModel inputClaims = CallbackClaimsModel.Parse(input);

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

            byte[]           data          = Convert.FromBase64String(inputClaims.callback);
            string           decodedString = Encoding.UTF8.GetString(data);
            CredentialsModel cm            = JsonConvert.DeserializeObject <CredentialsModel>(decodedString);

            B2CResponseModel b2crm = LoginCallbackAPI(cm);

            return(Ok(b2crm));
        }
Exemplo n.º 6
0
        public async Task <IActionResult> VerifyAsync(
            [HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = "totp/verify")]
            HttpRequest request, ILogger log)
        {
            log.LogInformation("Start code Verify Function.");
            if (request.Body is null)
            {
                return(StatusCode((int)HttpStatusCode.Conflict, new B2CResponseModel("Request content is null", HttpStatusCode.Conflict)));
            }

            var input = await new StreamReader(request.Body, Encoding.UTF8).ReadToEndAsync();

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

            var inputClaims = InputClaimsModel.Parse(input);

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

            try
            {
                var secretKey = Convert.FromBase64String(DecryptAndBase64(inputClaims.SecretKey));

                var totp = new Totp(secretKey);

                // Verify the TOTP code provided by the users
                var verificationResult = totp.VerifyTotp(
                    inputClaims.TotpCode,
                    out var timeStepMatched,
                    VerificationWindow.RfcSpecifiedNetworkDelay);

                if (!verificationResult)
                {
                    return(StatusCode((int)HttpStatusCode.Conflict, new B2CResponseModel("The verification code is invalid.", HttpStatusCode.Conflict)));
                }
                // Using the input claim 'timeStepMatched', we check whether the verification code has already been used.
                // For sign-up, the 'timeStepMatched' input claim is null and should not be evaluated
                // For sign-in, the 'timeStepMatched' input claim contains the last time a code matched (from the user profile), and if equal to
                // the last time matched from the verify totp step, we know this code has already been used and can reject
                if (!string.IsNullOrEmpty(inputClaims.TimeStepMatched) && (inputClaims.TimeStepMatched).Equals(timeStepMatched.ToString()))
                {
                    return(StatusCode((int)HttpStatusCode.Conflict, new B2CResponseModel("The verification code has already been used.", HttpStatusCode.Conflict)));
                }

                var output = new B2CResponseModel(string.Empty, HttpStatusCode.OK)
                {
                    TimeStepMatched = timeStepMatched.ToString()
                };

                return(Ok(output));
            }
            catch (Exception e)
            {
                return(StatusCode((int)HttpStatusCode.Conflict, new B2CResponseModel($"General error (REST API): {e.Message}", HttpStatusCode.Conflict)));
            }
        }
Exemplo n.º 7
0
        public async Task <ActionResult> Verify()
        {
            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)));
            }

            try
            {
                byte[] secretKey = Convert.FromBase64String(this.DecryptAndBase64(inputClaims.secretKey));

                Totp totp = new Totp(secretKey);
                long timeStepMatched;

                // Verify the TOTP code provided by the users
                bool verificationResult = totp.VerifyTotp(
                    inputClaims.totpCode,
                    out timeStepMatched,
                    VerificationWindow.RfcSpecifiedNetworkDelay);

                if (!verificationResult)
                {
                    return(StatusCode((int)HttpStatusCode.Conflict, new B2CResponseModel("The verification code is invalid.", HttpStatusCode.Conflict)));
                }

                // Using the input claim 'timeStepMatched', we check whether the verification code has already been used.
                // For sign-up, the 'timeStepMatched' input claim is null and should not be evaluated
                // For sign-in, the 'timeStepMatched' input claim contains the last time last matched (from the user profile), and evaluated with
                // the value of the result of the TOTP out 'timeStepMatched' variable
                if ((string.IsNullOrEmpty(inputClaims.timeStepMatched) == false) &&
                    !(inputClaims.timeStepMatched).Equals(timeStepMatched.ToString()))
                {
                    return(StatusCode((int)HttpStatusCode.Conflict, new B2CResponseModel("The verification code has already been used.", HttpStatusCode.Conflict)));
                }

                B2CResponseModel output = new B2CResponseModel(string.Empty, HttpStatusCode.OK)
                {
                    timeStepMatched = timeStepMatched.ToString()
                };

                return(Ok(output));
            }
            catch (Exception ex)
            {
                return(StatusCode((int)HttpStatusCode.Conflict, new B2CResponseModel($"General error (REST API): {ex.Message}", HttpStatusCode.Conflict)));
            }
        }
        public async Task <ActionResult> Send()
        {
            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)));
            }

            // Check input email address. If phone number is empty, the user not found in the directory. So, return a random value
            if (string.IsNullOrEmpty(inputClaims.phoneNumber))
            {
                B2CResponseModel b2CResponseModel = new B2CResponseModel("Ok", HttpStatusCode.OK);
                b2CResponseModel.verificationCode = Guid.NewGuid().ToString();

                return(Ok(b2CResponseModel));
            }

            try
            {
                int code = random.Next(1593, 9937);

                TwilioClient.Init(this.AppSettings.SMSUsername, this.AppSettings.SMSPassword);

                var message = MessageResource.Create(
                    from: new Twilio.Types.PhoneNumber(this.AppSettings.SMSFromPhoneNumber),
                    body: $"{this.AppSettings.SMSMessage}\r\n{code}",
                    to: new Twilio.Types.PhoneNumber(inputClaims.phoneNumber)
                    );

                //Output claims
                B2CResponseModel b2CResponseModel = new B2CResponseModel("Ok", HttpStatusCode.OK);
                b2CResponseModel.verificationCode = code.ToString();

                return(Ok(b2CResponseModel));
            }
            catch (Exception ex)
            {
                return(StatusCode((int)HttpStatusCode.Conflict, new B2CResponseModel("An unexpected error occurred. " + ex.Message, HttpStatusCode.Conflict)));
            }
        }
Exemplo n.º 9
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);
        }
Exemplo n.º 10
0
        public async Task <ActionResult> Register()
        {
            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)));
            }

            // Check input email address for local and social accounts
            if (string.IsNullOrEmpty(inputClaims.email) && string.IsNullOrEmpty(inputClaims.signInName))
            {
                return(StatusCode((int)HttpStatusCode.Conflict, new B2CResponseModel("Email address is empty", HttpStatusCode.Conflict)));
            }

            // Check input phone number
            if (string.IsNullOrEmpty(inputClaims.phoneNumber))
            {
                return(StatusCode((int)HttpStatusCode.Conflict, new B2CResponseModel("Phone number is empty", HttpStatusCode.Conflict)));
            }

            var phoneNumberMatch = Regex.Match(inputClaims.phoneNumber, @"\+(9[976]\d|8[987530]\d|6[987]\d|5[90]\d|42\d|3[875]\d|2[98654321]\d|9[8543210]|8[6421]|6[6543210]|5[87654321]|4[987654310]|3[9643210]|2[70]|7|1)(\d{1,14})$");

            if (!phoneNumberMatch.Success || phoneNumberMatch.Groups.Count != 3)
            {
                return(StatusCode((int)HttpStatusCode.Conflict, new B2CResponseModel("Phone number is not in the correct format", HttpStatusCode.Conflict)));
            }

            using (var client = new HttpClient())
            {
                var requestUri  = $"https://api.authy.com/protected/json/users/new";
                var requestForm = new Dictionary <string, string>();
                requestForm.Add("user[email]", inputClaims.GetEamilAddress());
                requestForm.Add("user[cellphone]", phoneNumberMatch.Groups[2].Value);
                requestForm.Add("user[country_code]", phoneNumberMatch.Groups[1].Value);
                var requestContent = new FormUrlEncodedContent(requestForm);
                client.DefaultRequestHeaders.Add("X-Authy-API-Key", AppSettings.Key);

                try
                {
                    var response = await client.PostAsync(requestUri, requestContent);

                    response.EnsureSuccessStatusCode();
                    dynamic responseContent = JsonConvert.DeserializeObject(await response.Content.ReadAsStringAsync());
                    string  authyId         = "";

                    if ((bool)responseContent.success)
                    {
                        authyId = (string)responseContent.user.id;
                    }
                    else
                    {
                        return(StatusCode((int)HttpStatusCode.Conflict, new B2CResponseModel("An unexpected error occurred creating the Authy user.", HttpStatusCode.Conflict)));
                    }

                    B2CResponseModel outputClaims = new B2CResponseModel()
                    {
                        authyId = authyId
                    };

                    return(Ok(outputClaims));
                }
                catch (Exception ex)
                {
                    return(StatusCode((int)HttpStatusCode.Conflict, new B2CResponseModel("An unexpected error occurred creating the Authy user." + ex.Message, HttpStatusCode.Conflict)));
                }
            }
        }
        public async Task <ActionResult> Migrate()
        {
            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));
            //}

            // Initiate the output claim object
            B2CResponseModel outputClaims = new B2CResponseModel("", HttpStatusCode.OK);

            // 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);


            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(StatusCode((int)HttpStatusCode.Conflict, new B2CResponseModel("Your password is incorrect (migration API)", HttpStatusCode.Conflict)));
                    }
                }
                catch (Exception ex)
                {
                    return(StatusCode((int)HttpStatusCode.Conflict, new B2CResponseModel($"User migration error: {ex.Message}", HttpStatusCode.Conflict)));
                }
            }

            return(Ok(outputClaims));
        }
Exemplo n.º 12
0
        public async Task <ActionResult> CheckAppAttributes()
        {
            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.correlationId))
            {
                return(StatusCode((int)HttpStatusCode.Conflict, new B2CResponseModel("User 'requestId' is null or empty", HttpStatusCode.Conflict)));
            }

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

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

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

            string requestId = Guid.NewGuid().ToString();

            try
            {
                if (inputClaims.appId == "0239a9cc-309c-4d41-87f1-31288feb2e82" && string.IsNullOrEmpty(inputClaims.city))
                {
                    CloudTable table = await GetSignUpTable();

                    IdentityEntity identityEntity = new IdentityEntity("SignInRequest", requestId);
                    identityEntity.ipAddress     = this.Request.HttpContext.Connection.RemoteIpAddress.ToString();
                    identityEntity.userId        = inputClaims.userId;
                    identityEntity.appId         = inputClaims.appId;
                    identityEntity.correlationId = inputClaims.correlationId.ToString();

                    TableOperation insertOperation = TableOperation.InsertOrReplace(identityEntity);
                    await table.ExecuteAsync(insertOperation);

                    //Output claims
                    B2CResponseModel b2CResponseModel = new B2CResponseModel("Ok", HttpStatusCode.OK);
                    b2CResponseModel.collectData = true;
                    b2CResponseModel.requestId   = EncryptAndBase64(requestId);

                    return(Ok(b2CResponseModel));
                }
                else
                {
                    //Output claims
                    B2CResponseModel b2CResponseModel = new B2CResponseModel("Ok", HttpStatusCode.OK);
                    b2CResponseModel.collectData = false;

                    return(Ok(b2CResponseModel));
                }
            }
            catch (Exception ex)
            {
                return(StatusCode((int)HttpStatusCode.Conflict, new B2CResponseModel(ex.Message, HttpStatusCode.Conflict)));
            }
        }