public void ValidateAuthTest() { var key = new byte[] { 01, 02, 03, 04 }; var jwt = new JWTAuthorization(loggerMock.Object, key, TimeSpan.FromSeconds(1)); var claims = new AuthClaims() { UserId = Guid.Parse("D9C18D24-9D4F-4BE3-BF3F-1D1A438B8EFB"), SessionId = Guid.Parse("0952B304-EDB1-40DC-96AB-C4575FE45848"), }; var token = jwt.GetAuthToken(claims); var recoveredClaims = jwt.ValidateAuth(token); Assert.IsTrue(claims.UserId == recoveredClaims.UserId && claims.SessionId == recoveredClaims.SessionId); Assert.Throws <InvalidTokenPartsException>( () => jwt.ValidateAuth("invalidtoken")); var invalidTokenSplit = token.Split('.'); invalidTokenSplit[2] = "SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c"; Assert.Throws <SignatureVerificationException>( () => jwt.ValidateAuth(string.Join('.', invalidTokenSplit))); Thread.Sleep(1050); Assert.Throws <TokenExpiredException>( () => jwt.ValidateAuth(token)); }
public ClaimsIdentity GenerateClaimsIdentity(AuthClaims claims) { return(new ClaimsIdentity(new[] { new Claim(nameof(claims.Id), claims.Id.ToString()), new Claim(nameof(claims.IsParticipant), claims.IsParticipant.ToString()), new Claim(nameof(claims.IsLecturer), claims.IsLecturer.ToString()), new Claim(nameof(claims.IsAdmin), claims.IsAdmin.ToString()), new Claim(nameof(claims.IsCustom), claims.IsCustom.ToString()), new Claim(nameof(claims.Token), claims.Token), new Claim(nameof(claims.TokenSecret), claims.TokenSecret) })); }
public void GetAuthTokenTest() { var key = new byte[] { 01, 02, 03, 04 }; var jwt = new JWTAuthorization(loggerMock.Object, key, TimeSpan.FromMinutes(1)); var claims = new AuthClaims() { UserId = Guid.Parse("D9C18D24-9D4F-4BE3-BF3F-1D1A438B8EFB"), SessionId = Guid.Parse("0952B304-EDB1-40DC-96AB-C4575FE45848"), }; var token = jwt.GetAuthToken(claims); Assert.NotNull(token); }
public async Task <ActionResult <UserLoginViewModel> > Login( [FromBody] LoginModel login, [FromQuery] bool getSessionKey) { var user = await database .GetWhere <UserModel>(u => u.UserName.Equals(login.Ident) || string.IsNullOrEmpty(u.MailAddress) && u.MailAddress.Equals(login.Ident)) .FirstOrDefaultAsync(); if (user == null || !(await hasher.CompareEncodedHash(login.Password, user.PasswordHash))) { return(Unauthorized()); } user.LastLogin = DateTime.Now; database.Update(user); var expire = login.Remember ? EXTENDED_SESSION_EXPIRATION : DEFAULT_SESSION_EXPIRATION; var claims = new AuthClaims { Guid = user.Guid, }; var jwt = authorization.GetSessionKey(claims, expire); var cookieOptions = new CookieOptions { Expires = DateTime.Now.Add(expire), HttpOnly = true, SameSite = SameSiteMode.Strict, Secure = !bypassSecureCookies, }; Response.Cookies.Append(Constants.SessionCookieName, jwt, cookieOptions); await database.Commit(); var res = new UserLoginViewModel(user); if (getSessionKey) { res.SessionKey = jwt; } return(Ok(res)); }
public async Task <ActionResult <LoginResponseModel> > Login([FromBody] LoginModel login) { var user = await database.GetUserByUserName(login.Username); if (user == null) { return(Unauthorized()); } if (!hasher.Validate(login.Password, user.PasswordHash)) { return(Unauthorized()); } user.LastLogin = DateTime.Now; await database.Update(user); var expires = login.Remember ? EXTENDED_SESSION_EXPIRATION : DEFAULT_SESSION_EXPIRATION; var claims = new AuthClaims() { UserUid = user.Uid, UserName = user.UserName, }; var refreshToken = await refreshTokenHandler.GenerateAsync(claims, expires); var accessToken = accessTokenHandler.Generate(claims); var cookieOptions = new CookieOptions { Expires = refreshToken.Deadline, HttpOnly = true, #if !DEBUG SameSite = SameSiteMode.Strict, Secure = !bypassSecureCookies, #endif }; Response.Cookies.Append(Constants.REFRESH_TOKEN_COOKIE, refreshToken.Token, cookieOptions); return(Ok(new LoginResponseModel(user, accessToken))); }
public async Task <IActionResult> Authenticate() { var callbackUrl = HttpContext.GetBaseAddressWithPath(_usosOptions.CallbackEndpoint); var oauthRequest = HttpContext.BuildOAuthRequest(null, null, callback: callbackUrl); var response = await _usosService.GetRequestTokenAsync(oauthRequest); var claims = new AuthClaims { Id = string.Empty, Token = response.OAuthToken, TokenSecret = response.OAuthTokenSecret, }; var claimsIdentity = _jwtService.GenerateClaimsIdentity(claims); var jwt = _jwtService.GenerateJWE(claimsIdentity); HttpContext.Response.Cookies.Append(AuthenticationCookies.SecureToken, jwt, _jwtService.GetTokenCookieOptions()); HttpContext.Response.Cookies.Delete(AuthenticationCookies.SecureAuth, _jwtService.GetAuthCookieOptions()); HttpContext.Response.Cookies.Delete(AuthenticationCookies.SecureUser, _jwtService.GetUserCookieOptions()); HttpContext.Response.Cookies.Delete(AntiforgeryConsts.CookieName); HttpContext.Response.Cookies.Delete(AntiforgeryConsts.FormCookieName); return(new OkObjectResult(_usosService.GetRedirectAddress(response.OAuthToken).ToString())); }
public async Task OnActionExecutionAsyncTest() { // --- TEST SETUP --------------------------------------- const string passwordHash = "passwordHash"; string authToken = "authToken"; var user = new User() { Created = DateTime.Now, Id = Guid.NewGuid(), LoginName = "zekro", PasswordHash = passwordHash, }; var claims = new AuthClaims() { SessionId = Guid.NewGuid(), UserId = user.Id, }; var dbMock = new Mock <IContext>(); dbMock.Setup(c => c.Users.FindAsync(user.Id)).ReturnsAsync(user); var authMock = new Mock <IAuthorization>(); authMock.Setup(a => a.ValidateAuth(authToken)).Returns(claims); var httpContextMock = new Mock <HttpContext>(); var noToken = ""; httpContextMock.Setup(c => c.Request.Cookies.TryGetValue(Constants.SESSION_COOKIE_NAME, out noToken)).Returns(false); var contextMock = new ActionContext( httpContextMock.Object, Mock.Of <RouteData>(), Mock.Of <ActionDescriptor>()); var actionContextMock = new Mock <ActionExecutingContext>( contextMock, new List <IFilterMetadata>(), new Dictionary <string, object>(), Mock.Of <ControllerBase>()); var nextMock = new Mock <ActionExecutionDelegate>(); RequiresAuthorization GetFilter() => new RequiresAuthorization(dbMock.Object, authMock.Object); // --- TEST PROCEDURE ----------------------------------- Assert.ThrowsAsync <Exception>(() => GetFilter().OnActionExecutionAsync(actionContextMock.Object, () => null)); actionContextMock.Setup(c => c.Controller).Returns(new AuthorizedControllerBase()); await GetFilter().OnActionExecutionAsync(actionContextMock.Object, () => null); actionContextMock.VerifySet(c => c.Result = It.IsAny <UnauthorizedResult>()); var invalidToken = "invalid_token"; httpContextMock.Setup(c => c.Request.Cookies.TryGetValue(Constants.SESSION_COOKIE_NAME, out invalidToken)).Returns(true); await GetFilter().OnActionExecutionAsync(actionContextMock.Object, () => null); actionContextMock.VerifySet(c => c.Result = It.IsAny <UnauthorizedResult>()); var controller = new AuthorizedControllerBase(); actionContextMock.Setup(c => c.Controller).Returns(controller); httpContextMock.Setup(c => c.Request.Cookies.TryGetValue(Constants.SESSION_COOKIE_NAME, out authToken)).Returns(true); await GetFilter().OnActionExecutionAsync(actionContextMock.Object, nextMock.Object); nextMock.Verify(m => m.Invoke(), Times.AtLeastOnce()); Assert.AreSame(claims, controller.AuthClaims); Assert.AreSame(user, controller.AuthorizedUser); }
public void SetAuthClaims(AuthClaims claims) => authClaims = claims;
public async Task <IActionResult> Authorize(AuthorizeRequest request) { var accessTokenResponse = await _usosService.GetAccessTokenAsync(HttpContext.BuildOAuthRequest(token: request.OAuthToken, verifier: request.OAuthVerifier)); var oauthRequest = HttpContext.BuildOAuthRequest(accessTokenResponse.OAuthToken, accessTokenResponse.OAuthTokenSecret); //TODO: Clean up with GetUserPermission and such var usosUser = await _usosService.GetCurrentUser(oauthRequest); var currentTerm = await _usosService.GetCurrentTerm(oauthRequest); //TODO: Run requests in parallel bool?isParticipant = await _usosService.IsCurrentUserCourseParticipant(oauthRequest, currentTerm.Id); bool?isLecturer = await _usosService.IsCurrentUserCourseLecturer(oauthRequest, currentTerm.Id); bool?customAccess = null; var isAdmin = false; var user = await _userRepository.GetAsync(int.Parse(usosUser.Id)); if (usosUser.Id == _appOptions.DefaultAdministratorUsosId) { isAdmin = true; } ; if (user == null) { user = _mapper.Map <UsosUser, User>(usosUser); user.Email = usosUser.Email; user.FirstLoginAt = DateTime.Now; user.LastLoginAt = DateTime.Now; user.AdminAccess = isAdmin; await _userRepository.AddAsync(user); } else { if (!user.AdminAccess && isAdmin) { user.AdminAccess = isAdmin; } user.LastLoginAt = DateTime.Now; user.Email = usosUser.Email != null ? usosUser.Email : user.Email; await _userRepository.UpdateAsync(user); } //Fallback if (isParticipant == null) { isParticipant = _thesisService.IsAuthor(user); } //Fallback, for safety reason we only set custom access if (isLecturer == null) { customAccess = _thesisService.IsPromoter(user); } if (_appOptions.DebugMode) { isAdmin = true; isParticipant = true; isLecturer = true; } var authClaims = new AuthClaims { Id = usosUser.Id, IsParticipant = isParticipant.GetValueOrDefault(), IsLecturer = isLecturer.GetValueOrDefault(), IsAdmin = user.AdminAccess, IsCustom = customAccess ?? user.CustomAccess, //If fallback didn't applied the rule, we take info from database Token = accessTokenResponse.OAuthToken, TokenSecret = accessTokenResponse.OAuthTokenSecret }; var authClaimsIdentity = _jwtService.GenerateClaimsIdentity(authClaims); var authJWT = _jwtService.GenerateJWE(authClaimsIdentity); var userClaims = new UserClaims { Id = usosUser.Id, Name = $"{usosUser.FirstName} {usosUser.LastName}", Email = usosUser.Email ?? string.Empty, AvatarUrl = usosUser.PhotoUrls.FirstOrDefault().Value ?? string.Empty, IsParticipant = isParticipant.GetValueOrDefault(), IsLecturer = isLecturer.GetValueOrDefault(), IsAdmin = user.AdminAccess, IsCustom = customAccess ?? user.CustomAccess, //If fallback didn't applied the rule, we take info from database }; var userClaimsIdentity = _jwtService.GenerateClaimsIdentity(userClaims); var userJWT = _jwtService.GenerateJWS(userClaimsIdentity); HttpContext.Response.Cookies.Append(AuthenticationCookies.SecureAuth, authJWT, _jwtService.GetAuthCookieOptions()); HttpContext.Response.Cookies.Append(AuthenticationCookies.SecureUser, userJWT, _jwtService.GetUserCookieOptions()); HttpContext.Response.Cookies.Delete(AuthenticationCookies.SecureToken, _jwtService.GetTokenCookieOptions()); HttpContext.Response.Cookies.Delete(AntiforgeryConsts.CookieName); HttpContext.Response.Cookies.Delete(AntiforgeryConsts.FormCookieName); //TODO: Redirect user somewhere return(new OkResult()); }
// This method gets called by the runtime. Use this method to add services to the container. // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940 public void ConfigureServices(IServiceCollection services) { services.AddDbContext <SimpleSurveyContext>(options => options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"))); services.AddAuthentication(AzureADB2CDefaults.AuthenticationScheme) .AddAzureADB2C(options => Configuration.Bind("AzureAdB2C", options)); // This is where you wire up to events to detect when a user logs in services.Configure <OpenIdConnectOptions>(AzureADB2CDefaults.OpenIdScheme, options => { options.Events = new OpenIdConnectEvents { OnRedirectToIdentityProvider = async ctxt => { // Invoked before redirecting to the identity provider to authenticate. // This can be used to set ProtocolMessage.State // that will be persisted through the authentication process. // The ProtocolMessage can also be used to add or customize // parameters sent to the identity provider. await Task.Yield(); }, OnAuthenticationFailed = async ctxt => { // They tried to log in but it failed await Task.Yield(); }, OnTicketReceived = async ctxt => { if (ctxt.Principal.Identity is ClaimsIdentity identity) { // Set common values AuthClaims objAuthClaims = new AuthClaims(); var colClaims = await ctxt.Principal.Claims.ToDynamicListAsync(); objAuthClaims.IdentityProvider = colClaims.FirstOrDefault( c => c.Type == "http://schemas.microsoft.com/identity/claims/identityprovider")?.Value; objAuthClaims.Objectidentifier = colClaims.FirstOrDefault( c => c.Type == "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier")?.Value; objAuthClaims.EmailAddress = colClaims.FirstOrDefault( c => c.Type == "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress")?.Value; objAuthClaims.FirstName = colClaims.FirstOrDefault( c => c.Type == "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname")?.Value; objAuthClaims.LastName = colClaims.FirstOrDefault( c => c.Type == "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname")?.Value; objAuthClaims.AzureB2CFlow = colClaims.FirstOrDefault( c => c.Type == "http://schemas.microsoft.com/claims/authnclassreference")?.Value; objAuthClaims.auth_time = colClaims.FirstOrDefault( c => c.Type == "auth_time")?.Value; objAuthClaims.DisplayName = colClaims.FirstOrDefault( c => c.Type == "name")?.Value; objAuthClaims.idp_access_token = colClaims.FirstOrDefault( c => c.Type == "idp_access_token")?.Value; // Google login if (objAuthClaims.IdentityProvider.ToLower().Contains("google")) { objAuthClaims.AuthenticationType = "Google"; } // Microsoft account login if (objAuthClaims.IdentityProvider.ToLower().Contains("live")) { objAuthClaims.AuthenticationType = "Microsoft"; } // Twitter login if (objAuthClaims.IdentityProvider.ToLower().Contains("twitter")) { objAuthClaims.AuthenticationType = "Twitter"; } // Azure Active Directory login // But this will only work if Azure B2C Custom Policy is configured // to pass the idp_access_token // See \!AzureB2CConfig\TrustFrameworkExtensions.xml // for an example that does that if (objAuthClaims.idp_access_token != null) { objAuthClaims.AuthenticationType = "Azure Active Directory"; try { var token = new System.IdentityModel.Tokens.Jwt.JwtSecurityToken(objAuthClaims.idp_access_token); objAuthClaims.EmailAddress = token.Claims.FirstOrDefault(c => c.Type == "upn")?.Value; } catch (System.Exception) { // Could not decode - do nothing } } var request = ctxt.HttpContext.Request; var host = request.Host.ToUriComponent(); // Insert into Database var optionsBuilder = new DbContextOptionsBuilder <SimpleSurveyContext>(); optionsBuilder.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")); SimpleSurveyContext _context = new SimpleSurveyContext(optionsBuilder.Options); var ExistingUser = _context.Users .Where(x => x.Objectidentifier == objAuthClaims.Objectidentifier) .FirstOrDefault(); if (ExistingUser == null) { // New User // Create User object var objUser = new Users(); try { objUser.Objectidentifier = objAuthClaims.Objectidentifier; objUser.AuthenticationType = objAuthClaims.AuthenticationType; objUser.IdentityProvider = objAuthClaims.IdentityProvider; objUser.SigninMethod = objAuthClaims.AzureB2CFlow; objUser.DisplayName = objAuthClaims.DisplayName; objUser.Email = objAuthClaims.EmailAddress; objUser.FirstName = objAuthClaims.FirstName; objUser.LastName = objAuthClaims.LastName; objUser.LastAuthTime = Convert.ToInt32(objAuthClaims.auth_time); objUser.LastidpAccessToken = objAuthClaims.idp_access_token; objUser.LastIpaddress = host; objUser.CreatedDate = DateTime.Now; _context.Users.Add(objUser); _context.SaveChanges(); // Write to Log var objLogs = new Logs(); objLogs.LogType = "Login"; objLogs.LogDate = DateTime.Now; objLogs.LogDetail = "New User"; objLogs.LogUserId = objUser.Id; objLogs.LogIpaddress = host; _context.Logs.Add(objLogs); _context.SaveChanges(); } catch (Exception ex) { // Write to Log var objLogs = new Logs(); objLogs.LogType = "Login Error - New User"; objLogs.LogDate = DateTime.Now; objLogs.LogDetail = String.Format($"User: {objUser.DisplayName} Objectidentifier: {objUser.Objectidentifier} Message: {ex.GetBaseException().Message}"); objLogs.LogIpaddress = host; _context.Logs.Add(objLogs); _context.SaveChanges(); } } else { // Update Existing User try { ExistingUser.AuthenticationType = objAuthClaims.AuthenticationType; ExistingUser.IdentityProvider = objAuthClaims.IdentityProvider; ExistingUser.SigninMethod = objAuthClaims.AzureB2CFlow; ExistingUser.DisplayName = objAuthClaims.DisplayName; ExistingUser.Email = objAuthClaims.EmailAddress; ExistingUser.FirstName = objAuthClaims.FirstName; ExistingUser.LastName = objAuthClaims.LastName; ExistingUser.LastAuthTime = Convert.ToInt32(objAuthClaims.auth_time); ExistingUser.LastidpAccessToken = objAuthClaims.idp_access_token; ExistingUser.LastIpaddress = host; ExistingUser.UpdatedDate = DateTime.Now; _context.SaveChanges(); // Write to Log var objLogs = new Logs(); objLogs.LogType = "Login"; objLogs.LogDate = DateTime.Now; objLogs.LogDetail = "Existing User"; objLogs.LogUserId = ExistingUser.Id; objLogs.LogIpaddress = host; _context.Logs.Add(objLogs); _context.SaveChanges(); } catch (Exception ex) { // Write to Log var objLogs = new Logs(); objLogs.LogType = "Login Error - Existing User"; objLogs.LogDate = DateTime.Now; objLogs.LogUserId = ExistingUser.Id; objLogs.LogDetail = ex.GetBaseException().Message; objLogs.LogIpaddress = host; _context.Logs.Add(objLogs); _context.SaveChanges(); } } } await Task.Yield(); }, };