/// <summary> /// Begins handling the current user, whether to create the user in the database. /// </summary> /// <param name="context">The owin context</param> /// <returns>An awaitable task</returns> public async override Task Invoke(IOwinContext context) { try { if (context.IsOptionsRequest()) { await Next.Invoke(context); return; } logger.Debug("Method: Invoke, BEGIN"); logger.Trace("Request is preflight request?: {0}", context.IsOptionsRequest()); var identity = context.Authentication.User.Identity; var username = identity.Name.Substring(identity.Name.LastIndexOf(@"\", StringComparison.OrdinalIgnoreCase) + 1); logger.Trace("Trying to retrieve user {0} from the database", username); var user = await userDatabaseRepository.Get(username); var error = false; var roles = new List<Role>(); if (!user.HasValue) { logger.Trace("User {0} does not exist in database", username); logger.Trace("Retrieve \"User\" role from database"); var role = (await roleRepository.GetAll()) .FirstOrDefault(r => r.Name.Equals("User", StringComparison.OrdinalIgnoreCase)); roles.Add(role); Debug.Assert(role != null, "Must have a predefined role: \"User\""); logger.Trace("Retrieve user information from Active Directory"); var adUser = await userActiveDirectoryRepository.Get(username); error = await adUser.Match(async u => { logger.Trace("User info retrieved from Active Directory!"); u.Roles = roles; logger.Trace("Creating user {0} in the database", username); var onCreated = new Func<User, Task<bool>>(createdUser => { return Task.FromResult(true); }); var created = await userDatabaseRepository.Create(u, onCreated); if (!created.HasValue) { // Error, couldn't create user in DB logger.Error("Could not create user {0} in the database!", username); return true; } logger.Trace("Created user {0} in the database!", username); user = created; return false; }, () => { // Error user, does not exist in AD logger.Error("No user information for {0} in Active Directory!", username); return Task.FromResult(true); }); } if (error) { logger.Trace("Returning with error 500. Reason given earlier"); context.Response.StatusCode = (int)HttpStatusCode.InternalServerError; return; } // Set principal roles var actualUser = user.ValueOrFailure(); logger.Trace("Extracting user {1} with ID {0}...", actualUser.ID, username); //// Note: .NET Framework 1.1 and onwards IsInRole is case-insensitive! //// source: https://msdn.microsoft.com/en-us/library/fs485fwh(v=vs.110).aspx logger.Trace("Setting authenticated user to principal"); var claimsPrincipal = new ClaimsPrincipal(); var claimsIdentity = new ClaimsIdentity(AuthenticationTypes.Windows); logger.Trace("Filtering out the claims..."); var claims = context.Authentication.User.Claims.Where(c => !c.Type.Equals(ClaimTypes.Name, StringComparison.OrdinalIgnoreCase)); logger.Trace("Adding filtered claims..."); claimsIdentity.AddClaims(claims); logger.Trace("Setting claim to username: {0}", actualUser.Username); claimsIdentity.AddClaim(new Claim(ClaimTypes.Name, actualUser.Username)); foreach (var role in actualUser.Roles) { logger.Trace("Adding role \"{0}\" to claims", role.Name); claimsIdentity.AddClaim(new Claim(ClaimTypes.Role, role.Name)); } logger.Trace("Adding identity to principal..."); claimsPrincipal.AddIdentity(claimsIdentity); logger.Trace("Setting context to principal..."); context.Authentication.User = claimsPrincipal; logger.Trace("Saving user in owin context: ({0}, {1})...", Constants.CURRENT_USER, actualUser.Username); context.Set(Constants.CURRENT_USER, actualUser); logger.Trace("Proceeding with the owin middleware pipeline"); await Next.Invoke(context); logger.Debug("Method: Invoke, END"); } catch (Exception ex) { logger.Error(ex); throw; } }