private async Task <Entities.User> AutoProvisionWindowsUser(string provider, string providerUserId, IEnumerable <Claim> claims) { if (_windowsKeyMap.ContainsKey(providerUserId)) { // find matching user var existingUser = await _localUserService.GetUserBySubjectAsync(_windowsKeyMap[providerUserId]); if (existingUser != null) { await _localUserService.AddExternalProviderToUser( existingUser.Subject, provider, providerUserId); await _localUserService.SaveChangesAsync(); return(existingUser); } } var user = _localUserService.ProvisionUserFromExternalIdentity(provider, providerUserId, new List <Claim>()); await _localUserService.SaveChangesAsync(); return(user); }
public async Task <IActionResult> RegisterForMfa(string returnUrl) { var secret = string.Empty; using (var rng = new RNGCryptoServiceProvider()) { byte[] tokenData = new byte[64]; rng.GetBytes(tokenData); var result = new StringBuilder(16); for (int i = 0; i < 16; i++) { var rnd = BitConverter.ToUInt32(tokenData, i * 4); var idx = rnd % chars.Length; result.Append(chars[idx]); } secret = result.ToString(); } // read identity from the temporary cookie var resultIdent = await HttpContext.AuthenticateAsync("idsrv.mfa"); if (resultIdent?.Succeeded != true) { throw new Exception("MFA authentication error"); } var subject = resultIdent.Principal.FindFirst(JwtClaimTypes.Subject)?.Value; var user = await _localUserService.GetUserBySubjectAsync(subject); var keyUri = string.Format( "otpauth://totp/{0}:{1}?secret={2}&issuer={0}", WebUtility.UrlEncode("Marvin"), WebUtility.UrlEncode(user.Email), secret); var vm = new RegisterForMfaViewModel() { KeyUri = keyUri, Secret = secret, ReturnUrl = returnUrl }; return(View(vm)); }
public async Task GetProfileDataAsync(ProfileDataRequestContext context) { var subjectId = context.Subject.GetSubjectId(); var claimsForUser = (await _localUserService.GetUserClaimsBySubjectAsync(subjectId)) .ToList(); var user = await _localUserService.GetUserBySubjectAsync(subjectId); var claims = new List <Claim>(); if (user != null) { if (!String.IsNullOrEmpty(user?.FirstName)) { claims.Add(new Claim("given_name", user.FirstName)); } if (!String.IsNullOrEmpty(user?.LastName)) { claims.Add(new Claim("family_name", user.LastName)); } if (!String.IsNullOrEmpty(user?.UserName)) { claims.Add(new Claim("name", user.UserName)); } if (!String.IsNullOrEmpty(user?.Email)) { claims.Add(new Claim("email", user.Email)); } if (context.RequestedClaimTypes.Contains("role")) { foreach (var userUserRole in user.Roles) { claims.Add(new Claim("role", userUserRole.Name)); } } } context.AddRequestedClaims(claims); context.AddRequestedClaims( claimsForUser.Select(c => new Claim(c.Type, c.Value)).ToList()); }
public async Task <IActionResult> RegisterForMfa() { var secret = string.Empty; using (var rng = new RNGCryptoServiceProvider()) { byte[] tokenData = new byte[64]; rng.GetBytes(tokenData); var result = new StringBuilder(16); for (int i = 0; i < 16; i++) { var rnd = BitConverter.ToUInt32(tokenData, i * 4); var idx = rnd % chars.Length; result.Append(chars[idx]); } secret = result.ToString(); } var subject = User.FindFirst(JwtClaimTypes.Subject)?.Value; var user = await _localUserService.GetUserBySubjectAsync(subject); var keyUri = string.Format( "otpauth://totp/{0}:{1}?secret={2}&issuer={0}", WebUtility.UrlEncode("Marvin"), WebUtility.UrlEncode(user.Email), secret); var vm = new RegisterForMfaViewModel() { KeyUri = keyUri, Secret = secret }; return(View(vm)); }
public async Task <IActionResult> LoginExternal([FromBody] ExternalLoginModel model) { var resultmodel = new LoginResultModel(); resultmodel.ReturnUrl = model.ReturnUrl; // we will issue the external cookie and then redirect the // user back to the external callback, in essence, treating windows // auth the same as any other external authentication mechanism var props = new AuthenticationProperties() { RedirectUri = model.ReturnUrl, Items = { { "returnUrl", model.ReturnUrl }, { "scheme", model.Scheme }, } }; // see if windows auth has already been requested and succeeded AuthenticateResult result = await HttpContext.AuthenticateAsync(model.Scheme); if (result.Principal != null) { var authHandler = _authenticationProvider.GetHandler(model.Scheme); var factory = authHandler.GetUserFactory(result.Principal); var subject = factory.GetSubject(); var mUser = await _localUserService.GetUserBySubjectAsync(subject); if (mUser == null) { mUser = factory.BuildUser(); await _localUserService.AddUserAsync(mUser); } else { factory.UpdateClaims(mUser); await _usersService.UpdateUserAsync(mUser); } await HttpContext.SignInAsync(new IdentityServerUser(mUser.Subject) { DisplayName = mUser.UserName, IdentityProvider = model.Scheme, AuthenticationTime = DateTime.Now }); await HttpContext.SignOutAsync(IdentityServerConstants.ExternalCookieAuthenticationScheme); if (_interaction.IsValidReturnUrl(model.ReturnUrl) || Url.IsLocalUrl(model.ReturnUrl)) { return(Ok(resultmodel.WithStatus(Status.Ok))); } resultmodel.ReturnUrl = "/"; return(Ok(resultmodel.WithStatus(Status.Ok))); } else { // trigger windows auth // since windows auth don't support the redirect uri, // this URL is re-triggered when we call challenge return(Challenge(model.Scheme)); } }
public async Task <IActionResult> AdditionalAuthenticationFactor( AdditionalAuthenticationFactorViewModel model) { // check if we are in the context of an authorization request var context = await _interaction.GetAuthorizationContextAsync(model.ReturnUrl); if (ModelState.IsValid) { // read identity from the temporary cookie var result = await HttpContext.AuthenticateAsync("idsrv.mfa"); if (result?.Succeeded != true) { throw new Exception("MFA authentication error"); } var subject = result.Principal.FindFirst(JwtClaimTypes.Subject)?.Value; var user = await _localUserService.GetUserBySubjectAsync(subject); var userSecret = await _localUserService.GetUserSecret(subject, "TOTP"); var authenticator = new TwoStepsAuthenticator.TimeAuthenticator(); if (!authenticator.CheckCode(userSecret.Secret, model.Totp, user)) { ModelState.AddModelError("totp", "TOTP is invalid."); return(View(model)); } await _events.RaiseAsync( new UserLoginSuccessEvent( user.Username, user.Subject, user.Username, clientId : context?.Client.ClientId)); // only set explicit expiration here if user chooses "remember me". // otherwise we rely upon expiration configured in cookie middleware. AuthenticationProperties props = null; if (AccountOptions.AllowRememberLogin && model.RememberLogin) { props = new AuthenticationProperties { IsPersistent = true, ExpiresUtc = DateTimeOffset.UtcNow.Add(AccountOptions.RememberMeLoginDuration) }; } ; // delete temporary cookie used during mfa await HttpContext.SignOutAsync("idsrv.mfa"); // issue authentication cookie with subject ID and username var isuser = new IdentityServerUser(user.Subject) { DisplayName = user.Username }; await HttpContext.SignInAsync(isuser, props); if (context != null) { if (context.IsNativeClient()) { // The client is native, so this change in how to // return the response is for better UX for the end user. return(this.LoadingPage("Redirect", model.ReturnUrl)); } // we can trust model.ReturnUrl since GetAuthorizationContextAsync returned non-null return(Redirect(model.ReturnUrl)); } // request for a local page if (Url.IsLocalUrl(model.ReturnUrl)) { return(Redirect(model.ReturnUrl)); } else if (string.IsNullOrEmpty(model.ReturnUrl)) { return(Redirect("~/")); } else { // user might have clicked on a malicious link - should be logged throw new Exception("invalid return URL"); } } return(View(model)); }