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; })); }
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); })); }
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); })); }
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()); }
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 }); }