示例#1
0
        public async Task <string> UpdateUser(string objectId, string json, ILogger log)
        {
            return(await Task.Run(() =>
            {
                if (users.ContainsKey(objectId.ToString()))
                {
                    return (string)null;
                }

                B2CUser user = users.GetValueOrDefault(objectId.ToString());
                dynamic wrapper = JsonConvert.DeserializeObject <dynamic>(json);

                if (wrapper != null && IsDynamicPropertyExist(wrapper, "displayName"))
                {
                    user.DisplayName = wrapper.displayName;
                }

                if (wrapper != null && IsDynamicPropertyExist(wrapper, "passwordPolicies"))
                {
                    user.PasswordPolicies = wrapper.passwordPolicies;
                }

                if (wrapper != null && IsDynamicPropertyExist(wrapper, "passwordProfile"))
                {
                    user.PasswordProfile = wrapper.passwordProfile;
                }

                return (string)null;
            }));
        }
示例#2
0
 public async Task <string> GetUserByObjectId(string objectId, ILogger log)
 {
     return(await Task.Run(() =>
     {
         if (users.ContainsKey(objectId.ToString()))
         {
             return (string)null;
         }
         B2CUser user = users.GetValueOrDefault(objectId.ToString());
         return JsonConvert.SerializeObject(user);
     }));
 }
示例#3
0
        public async Task <string> CreateUser(B2CUser user, ILogger log)
        {
            return(await Task.Run(() =>
            {
                user.ObjectId = Guid.NewGuid().ToString();
                users.Add(user.ObjectId, user);

                JsonSerializerSettings B2CJsonSerializerSettings = new JsonSerializerSettings {
                    ContractResolver = new B2CUserAttributeContractResolver()
                };

                return JsonConvert.SerializeObject(user, B2CJsonSerializerSettings);
            }));
        }
示例#4
0
        private async Task <string> SendGraphPostRequest(string api, B2CUser user, ILogger log)
        {
            AuthenticationResult result = await authContext.AcquireTokenAsync(aadGraphResourceId, credential);

            string url = $"{aadGraphEndpoint}{aadTenant}{api}?{aadGraphVersion}";

            log.LogInformation($"POST {url}");
            log.LogDebug($"Authorization: Bearer {result.AccessToken.Substring(0, 20)}...");

            JsonSerializerSettings B2CJsonSerializerSettings = new JsonSerializerSettings {
                ContractResolver = new B2CUserAttributeContractResolver()
            };
            var serializedB2CUser = JsonConvert.SerializeObject(user, B2CJsonSerializerSettings);

            HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, url);

            request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", result.AccessToken);
            request.Content = new StringContent(serializedB2CUser, Encoding.UTF8, "application/json");
            HttpResponseMessage response = await httpClient.SendAsync(request);

            if (!response.IsSuccessStatusCode)
            {
                string errorJson = await response.Content.ReadAsStringAsync();

                var error = JsonConvert.DeserializeObject <B2CErrorRoot>(errorJson).Error;

                if (error.Code == "Request_BadRequest" && (error.Values?.Any(x => x.Item == "PropertyName" && x.Value == "signInNames") ?? false))
                {
                    throw new B2CUserExistsException($"B2C user '{user?.SignInNames[0]?.Value}' already exists.");
                }
                else
                {
                    throw new WebException($"Error Calling the Graph API: \n{JsonConvert.SerializeObject(error, Formatting.Indented)}");
                }
            }

            log.LogInformation($"{(int)response.StatusCode}: {response.ReasonPhrase}");

            return(await response.Content.ReadAsStringAsync());
        }
示例#5
0
 public async Task <string> CreateUser(B2CUser user, ILogger log)
 {
     return(await SendGraphPostRequest("/users/", user, log));
 }
        public async Task <IActionResult> Run(
            [HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = "users")]
            [RequestBodyType(typeof(User), "User")]
            HttpRequest req, ILogger log, ExecutionContext context)
        {
            log.LogInformation($"{context?.FunctionName} processed a HTTP request.");
            // TelemetryClient.Context.Operation.Id = context?.InvocationId.ToString(); // No longer needed?

            string requestBody = new StreamReader(req.Body).ReadToEnd();
            var    user        = JsonConvert.DeserializeObject <User>(requestBody);

            if (user is null)
            {
                return(new BadRequestObjectResult("No user definition specified in body."));
            }

            if (string.IsNullOrWhiteSpace(user.Id))
            {
                user.Id = Guid.NewGuid().ToString();
            }

            if (string.IsNullOrWhiteSpace(user.PartitionKey))
            {
                user.PartitionKey = user.Id;
            }

            if (string.IsNullOrWhiteSpace(user.DocumentType))
            {
                user.DocumentType = "user";
            }

            var missingProperties = new List <string>();


            // Check required user properties are present otherwise return 400.

            if (string.IsNullOrWhiteSpace(user.PrimaryEmailAddress))
            {
                missingProperties.Add("primaryEmailAddress");
            }
            if (string.IsNullOrWhiteSpace(user.FirstName))
            {
                missingProperties.Add("firstName");
            }
            if (string.IsNullOrWhiteSpace(user.LastName))
            {
                missingProperties.Add("lastName");
            }

            if (missingProperties.Count > 0)
            {
                return(new BadRequestObjectResult($"User definition is missing required properties... {((missingProperties.Count > 1) ? string.Join(", ", missingProperties) : missingProperties[0])}."));
            }


            // CHECK USER NOT IN GRAPH

            try
            {
                var filterProperties = new { userName = user.UserName, primaryEmailAddress = user.PrimaryEmailAddress };
                var query            = GremlinHelper.GetVertexQuery(filterProperties, true);
                var response         = new GraphResponse(await GremlinClient.SubmitAsync <dynamic>(query));

                GremlinHelper.ThrowIfResponseInvalid(response);

                if (response.Entities != null && response.Entities.Count() > 0)
                {
                    return(new ConflictObjectResult("User already exists (graph)."));
                }
            }
            catch (ResponseException ex)
            {
                GremlinHelper.HandleGraphResponseException(ex, log, context, TelemetryClient);
            }
            catch (Exception ex)
            {
                GremlinHelper.HandleGeneralException(ex, log, context, TelemetryClient);
            }


            // CREATE USER ON B2C

            if (string.IsNullOrWhiteSpace(user.Password))
            {
                user.Password = Guid.NewGuid().ToString();
                user.CustomProperties.Add("PasswordAutoGenerated", "true");
            }

            var b2cUser = new B2CUser()
            {
                DisplayName = user.Id, // We do not store user profile data on B2C identity - simply use the customer user id for display name.
                UserAttribute_CustomerUserId = user.Id,
                SignInNames = new List <B2CSignInName>()
                {
                    new B2CSignInName()
                    {
                        Type = "emailAddress", Value = user.PrimaryEmailAddress
                    }
                },
                PasswordProfile = new B2CPasswordProfile()
                {
                    Password = user.Password,
                    ForceChangePasswordNextLogin = false
                }
            };

            // Remove password value from user object.
            user.Password = null;

            try
            {
                var b2cCreatedUserResult = await B2CGraphClient.CreateUser(b2cUser, log);

                var b2cCreatedUser = JsonConvert.DeserializeObject <dynamic>(b2cCreatedUserResult);
                user.IdentityId = b2cCreatedUser?.objectId;
                user.UserStatus = UserStatus.Active;
            }
            catch (B2CUserExistsException)
            {
                // User already exists on B2C
                return(new ConflictObjectResult("User already exists (identity)."));
            }
            catch (B2CPasswordComplexityException)
            {
                return(new BadRequestObjectResult("The specified password does not comply with password complexity requirements. Please provide a different password."));
            }
            catch (Exception ex)
            {
                var ignoreTask = Task.Run(() =>
                {
                    log.LogError($"{context?.FunctionName} Create B2C User Error: {ex.Message}");
                    TelemetryClient.TrackException(ex, new Dictionary <string, string>()
                    {
                        { "ExceptionType", "B2CUserCreateError" }, { "UserName", user?.UserName }, { "EmailAddress", user?.PrimaryEmailAddress }
                    }, null);
                });

                return(new OkObjectResult("Failed to create user (identity).")
                {
                    StatusCode = 500
                });
            }


            // CREATE USER IN GRAPH

            try
            {
                var query    = GremlinHelper.CreateVertexQuery(user, log);
                var response = new GraphResponse(await GremlinClient.SubmitAsync <dynamic>(query));

                GremlinHelper.ThrowIfResponseInvalid(response);

                GremlinHelper.GraphTelemetryEvent(TelemetryClient, "GraphVertexCreate", response, "vertex", "user");

                user = response.GetEntityAsType <User>();
            }
            catch (ResponseException ex)
            {
                GremlinHelper.HandleGraphResponseException(ex, log, context, TelemetryClient);
            }
            catch (Exception ex)
            {
                GremlinHelper.HandleGeneralException(ex, log, context, TelemetryClient);
            }

            return(user != null ?
                   new OkObjectResult(user)
            {
                StatusCode = 201
            } :
                   new OkObjectResult("Failed to create user.")
            {
                StatusCode = 500
            });
        }