public async Task <UserSettings> PostValidate() { UserInfo user = await GetUserInfoAsync(); if (user == null) { Dictionary <string, string> claims = await GetApiTokenClaimsAsync(); string email = claims[ClaimTypes.Email]; if (!await UserOperations.CheckNewUserAllowed(DbContext, email)) { throw new HttpResponseException(HttpStatusCode.Forbidden); } // User must either be on the master list, or invited. if (!MasterEmails.Contains(email)) { Invitation inv = await DbContext.Invitations.SingleOrDefaultAsync(i => i.Email == email); if (inv == null) { throw new HttpResponseException(new HttpResponseMessage(HttpStatusCode.Forbidden) { Content = new StringContent("Not invited") }); } } string msaKey = claims[ClaimTypes.NameIdentifier]; string msaName = claims[ClaimTypes.Name]; user = new UserInfo { UserInfoId = Guid.NewGuid().ToString("d"), Email = email, MicrosoftAccountProviderKeyApi = msaKey, Name = msaName, }; DbContext.UserInfos.Add(user); await DbContext.SaveChangesAsync(); } return(UserOperations.GetUserSettings(user)); }
public async Task <ActionResult> ExternalLoginCallback(string returnUrl) { var loginInfo = await AuthenticationManager.GetExternalLoginInfoAsync(); if (loginInfo == null) { return(RedirectToAction("Login")); } // Sign in the user with this external login provider if the user already has a login SignInStatus result = await SignInManager.ExternalSignInAsync(loginInfo, isPersistent : false); switch (result) { case SignInStatus.Success: return(RedirectToLocal(returnUrl)); case SignInStatus.LockedOut: return(View("Lockout")); case SignInStatus.RequiresVerification: return(RedirectToAction("SendCode", new { ReturnUrl = returnUrl, RememberMe = false })); case SignInStatus.Failure: default: // It's possible the account already exists through API use, in which case // we need to store the web MSA account key in the same account. ApplicationDbContext dbContext = Request.GetOwinContext().Get <ApplicationDbContext>(); UserInfo existingUser = await dbContext.UserInfos .SingleOrDefaultAsync(u => u.Email == loginInfo.Email); if (existingUser != null) { existingUser.MicrosoftAccountProviderKeyWeb = loginInfo.Login.ProviderKey; await dbContext.SaveChangesAsync(); result = await SignInManager.ExternalSignInAsync(loginInfo, isPersistent : false); return(RedirectToLocal(returnUrl)); } if (!await UserOperations.CheckNewUserAllowed(dbContext, loginInfo.Email)) { return(RedirectToAction("Login")); } // Because we set up the MSA scopes to include wl.emails, we'll have // the user's primary email at this point. We also get their display // name thanks to wl.basic, so we can create the account right // now. But first we need to check it they're invited (or on the master // list). var user = new ApplicationUser(loginInfo); if (!UiControllerBase.MasterEmails.Contains(user.Email)) { Invitation inv = await dbContext.Invitations.SingleOrDefaultAsync(i => i.Email == user.Email); if (inv == null) { return(RedirectToAction("NotInvited")); } } IdentityResult createUserResult = await UserManager.CreateAsync(user); if (createUserResult.Succeeded) { // Usually at this point you'd call UserManager.AddLoginAsync // to associate the external login with the new user. However, // our user accounts are inextricably linked to the MSA login, // so a) we don't need to and b) we can't - AddLoginAsync first // checks that there isn't already an account associated with // this login before proceeding, but of course it will find // the user we just created when it does that. // So we're done now, and just need to ask the sign in manager // to set up the cookie for us. await SignInManager.SignInAsync(user, isPersistent : false, rememberBrowser : false); return(RedirectToLocal(returnUrl)); } AddErrors(createUserResult); return(View("Error")); } }