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);
        }
Beispiel #4
0
        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));
        }
Beispiel #5
0
        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)));
        }
Beispiel #6
0
        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);
        }
Beispiel #8
0
 public void SetAuthClaims(AuthClaims claims) =>
 authClaims = claims;
Beispiel #9
0
        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());
        }
Beispiel #10
0
        // 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();
                    },
                };