public static async Task SignInAsync_SuccessfulSignInWithNullContext_RaisesLoginSuccessEvent() { int eventCount = 0; UserLoginSuccessEvent raisedEvent = null; void EventCallback(UserLoginSuccessEvent evt) { eventCount++; raisedEvent = evt; } const string userId = "UserId"; const string username = "******"; using var loginService = new LoginServiceBuilder() .WithEventServiceCallback <UserLoginSuccessEvent>(EventCallback) .WithSignInResult(IdentitySignInResult.Success) .WithFindUserResult(ApplicationUserBuilder .Create() .WithUserId(userId) .WithUsername(username) .Build()) .Build(); await loginService.SignInAsync("user", "pass", new Uri("~/", UriKind.Relative)); eventCount.Should().Be(1); Assert.NotNull(raisedEvent); raisedEvent.ClientId.Should().BeNull(); raisedEvent.DisplayName.Should().Be(username); raisedEvent.Message.Should().BeNull(); raisedEvent.SubjectId.Should().Be(userId); raisedEvent.Username.Should().Be(username); }
public async Task RaiseAsync(Event evt) { if (evt.Name.Contains("Login")) { if (evt.EventType == EventTypes.Success) { UserLoginSuccessEvent successEvent = evt as UserLoginSuccessEvent; UserAudit user = UserAudit.CreateAuditEvent(successEvent.SubjectId.ToString(), successEvent.Username, successEvent.DisplayName, successEvent.Name, successEvent.Id.ToString(), evt.EventType.ToString(), evt.RemoteIpAddress); await _context.UserAuditEvents.AddAsync(user); await _context.SaveChangesAsync(); } else { UserLoginFailureEvent failEvent = evt as UserLoginFailureEvent; UserAudit user = UserAudit.CreateAuditEvent(failEvent.Username.ToString(), failEvent.Id.ToString(), failEvent.Name, failEvent.EventType.ToString(), evt.RemoteIpAddress); await _context.UserAuditEvents.AddAsync(user); await _context.SaveChangesAsync(); } } else if (evt.Name.Contains("Logout")) { UserLogoutSuccessEvent failEvent = evt as UserLogoutSuccessEvent; UserAudit user = UserAudit.CreateAuditEvent(failEvent.SubjectId.ToString(), failEvent.DisplayName, failEvent.DisplayName, failEvent.Name, failEvent.Id.ToString(), evt.EventType.ToString(), evt.RemoteIpAddress); await _context.UserAuditEvents.AddAsync(user); await _context.SaveChangesAsync(); } }
public void Create_WhenUserLoginSuccessEvent_WillReturnUserLoginSuccessAdapter() { // Arrange var evt = new UserLoginSuccessEvent(string.Empty, string.Empty, string.Empty, string.Empty); var sut = new AdapterFactory(); // Act var adapter = sut.Create(evt); // Assert Assert.IsType <UserLoginSuccessEventAdapter>(adapter); }
public async Task <IActionResult> Login(LoginInputModel model, string button) { // check if we are in the context of an authorization request var context = await _interaction.GetAuthorizationContextAsync(model.ReturnUrl); // the user clicked the "cancel" button if (button != "login") { if (context != null) { // if the user cancels, send a result back into IdentityServer as if they // denied the consent (even if this client does not require consent). // this will send back an access denied OIDC error response to the client. await _interaction.GrantConsentAsync(context, ConsentResponse.Denied); // we can trust model.ReturnUrl since GetAuthorizationContextAsync returned non-null if (await _clientStore.IsPkceClientAsync(context.ClientId)) { // if the client is PKCE then we assume it's native, so this change in how to // return the response is for better UX for the end user. return(View("Redirect", new RedirectViewModel { RedirectUrl = model.ReturnUrl })); } return(Redirect(model.ReturnUrl)); } else { // since we don't have a valid context, then we just go back to the home page return(Redirect("~/")); } } if (ModelState.IsValid) { // validate username/password against in-memory store if (_userContext.ValidateCredentials(model.Username, model.Password)) { var user = _userContext.FindByUsername(model.Username); var login = new UserLoginSuccessEvent(user.Username, user.Id.ToString(), user.FullName, clientId: context?.ClientId); await _events.RaiseAsync(login); // 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) }; } ; // issue authentication cookie with subject ID and username await HttpContext.SignInAsync(user.Username, user.Username, props); if (context != null) { if (await _clientStore.IsPkceClientAsync(context.ClientId)) { // if the client is PKCE then we assume it's native, so this change in how to // return the response is for better UX for the end user. return(View("Redirect", new RedirectViewModel { RedirectUrl = 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"); } } await _events.RaiseAsync(new UserLoginFailureEvent(model.Username, "invalid credentials", clientId : context?.ClientId)); ModelState.AddModelError(string.Empty, AccountOptions.InvalidCredentialsErrorMessage); } // something went wrong, show form with error var vm = await BuildLoginViewModelAsync(model); return(View(vm)); }
public UserLoginSuccessEventAdapter(UserLoginSuccessEvent evt) { this.evt = evt ?? throw new ArgumentNullException(nameof(evt)); }
public async Task <IActionResult> Login(LoginInputModel model) { // check if we are in the context of an authorization request var context = await _interaction.GetAuthorizationContextAsync(model.ReturnUrl); if (ModelState.IsValid) { AuthenticationProperties props = null; IdentityServerUser isuser = null; UserLoginSuccessEvent successEvent = null; bool isValid = false; string errMsg = null; // 测试用户 var testUser = OAuthConfig.GetTestUsers().Find(t => t.Username == model.Username && t.Password == model.Password); if (testUser != null) { successEvent = new UserLoginSuccessEvent(testUser.Username, testUser.SubjectId, testUser.Username, clientId: context?.Client.ClientId); // issue authentication cookie with subject ID and username isuser = new IdentityServerUser(testUser.SubjectId) { DisplayName = testUser.Username, AdditionalClaims = { new Claim(UserClaimEnum.UserId.ToString(), testUser.SubjectId), new Claim(UserClaimEnum.UserName.ToString(), testUser.Username) } }; isValid = true; } else { //E登账号 var edUser = _edApiService.GetEdUser(model.Username, model.Password, out string msg); errMsg = msg; if (edUser != null) { successEvent = new UserLoginSuccessEvent(edUser.LoginName, edUser.ID.ToString(), edUser.EmployeeName, clientId: context?.Client.ClientId); // issue authentication cookie with subject ID and username isuser = new IdentityServerUser(edUser.ID.ToString()) { DisplayName = edUser.EmployeeName, AdditionalClaims = { new Claim(UserClaimEnum.UserId.ToString(), edUser.ID.ToString()), new Claim(UserClaimEnum.UserName.ToString(), edUser.EmployeeName.ToString()) } }; isValid = true; } } if (isValid) { //身份认证通过 await _events.RaiseAsync(successEvent); // only set explicit expiration here if user chooses "remember me". // otherwise we rely upon expiration configured in cookie middleware. if (AccountOptions.AllowRememberLogin && model.RememberLogin) { props = new AuthenticationProperties { IsPersistent = true, ExpiresUtc = DateTimeOffset.UtcNow.Add(AccountOptions.RememberMeLoginDuration) }; } ; 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("无效的返回URL"); } } await _events.RaiseAsync(new UserLoginFailureEvent(model.Username, "无效的证书", clientId : context?.Client.ClientId)); ModelState.AddModelError(string.Empty, errMsg ?? AccountOptions.InvalidCredentialsErrorMessage); } // something went wrong, show form with error var vm = await BuildLoginViewModelAsync(model); return(View(vm)); }