Example #1
0
        public static AuthHeaders ParseHeaders(IHeaderDictionary headers)
        {
            var result = new AuthHeaders();

            if (Configuration.Security.ForcedKey != null && Configuration.Security.ForcedPlayerId != null && Configuration.Security.ForcedTribeId != null)
            {
                result.AuthToken = Configuration.Security.ForcedKey;
                result.PlayerId  = Configuration.Security.ForcedPlayerId;
                result.TribeId   = Configuration.Security.ForcedTribeId;
                result.IsSitter  = false;
                return(result);
            }

            var combinedTokenString = headers["X-V-TOKEN"].FirstOrDefault();

            combinedTokenString = String.IsNullOrWhiteSpace(combinedTokenString) ? null : combinedTokenString;

            if (combinedTokenString != null)
            {
                var tokenParts = combinedTokenString.Split(':');

                var playerIdString  = tokenParts.Length > 0 ? tokenParts[0] : null;
                var tribeIdString   = tokenParts.Length > 1 ? tokenParts[1] : null;
                var authTokenString = tokenParts.Length > 2 ? tokenParts[2] : null;
                var sitterString    = tokenParts.Length > 3 ? tokenParts[3] : null;

                int playerId, tribeId;
                if (int.TryParse(playerIdString, out playerId))
                {
                    result.PlayerId = playerId;
                }
                if (int.TryParse(tribeIdString, out tribeId))
                {
                    result.TribeId = tribeId;
                }

                bool isSitter;
                if (bool.TryParse(sitterString, out isSitter))
                {
                    result.IsSitter = isSitter;
                }
                else
                {
                    result.IsSitter = true;
                }


                try
                {
                    result.AuthToken = Guid.Parse(authTokenString);
                }
                catch { }
            }

            return(result);
        }
        public override void OnException(ExceptionContext context)
        {
            Security.AuthHeaders auth = null;
            try { auth = Security.AuthenticationUtil.ParseHeaders(context.HttpContext.Request.Headers); }
            catch { }

            if (!(context.Exception is TaskCanceledException))
            {
                String message = "Exception thrown at endpoint: {endpoint}";
                if (auth != null)
                {
                    message += " from request by user with token: " + auth.AuthToken;
                }
                else
                {
                    message += " (auth token unavailable)";
                }
                logger.Error(message, context.HttpContext.Request.Path.Value);
            }

            base.OnException(context);
        }
Example #3
0
        public override void OnActionExecuting(ActionExecutingContext context)
        {
            var failedAuthMessage = $"Say hello to our log files, Mr. or Ms. {context.HttpContext.Connection.RemoteIpAddress.ToString()}";

            AuthHeaders authHeaders = null;

            authHeaders = AuthenticationUtil.ParseHeaders(context.HttpContext.Request.Headers);

            if (!authHeaders.IsValid)
            {
                var failedRequest = AuthenticationUtil.MakeFailedRecord(context.HttpContext, authHeaders);
                failedRequest.Reason = "Invalid authentication headers: ";
                var exactReasons = new List <String>();
                if (authHeaders.AuthToken == null)
                {
                    exactReasons.Add("AuthToken missing or invalid");
                }
                if (authHeaders.PlayerId == null)
                {
                    exactReasons.Add("PlayerId missing or invalid");
                }
                if (authHeaders.TribeId == null)
                {
                    exactReasons.Add("TribeId missing or invalid");
                }

                failedRequest.Reason += String.Join(", ", exactReasons);

                dbContext.Add(failedRequest);
                dbContext.SaveChanges();

                LogFailedRequest(failedRequest);

                context.Result = new ContentResult {
                    Content = failedAuthMessage, ContentType = "text/plain", StatusCode = 401
                };
                return;
            }

            var requestedWorld = context.RouteData.Values["worldName"] as String;

            if (requestedWorld == null)
            {
                var failedRequest = AuthenticationUtil.MakeFailedRecord(context.HttpContext, authHeaders);
                failedRequest.Reason = "Attempted to request a protected endpoint without worldName [programmer error]";

                dbContext.Add(failedRequest);
                dbContext.SaveChanges();

                LogFailedRequest(failedRequest);

                context.Result = new StatusCodeResult(401);
                return;
            }

            var world = dbContext.World.Where(w => w.Name == requestedWorld).FirstOrDefault();

            if (world == null)
            {
                var failedRequest = AuthenticationUtil.MakeFailedRecord(context.HttpContext, authHeaders);
                failedRequest.Reason = "Attempted to request a protected endpoint for a world that does not exist";

                dbContext.Add(failedRequest);
                dbContext.SaveChanges();

                LogFailedRequest(failedRequest);

                context.Result = new StatusCodeResult(401);
                return;
            }

            var authToken      = authHeaders.AuthToken;
            var discoveredUser = (
                from user in dbContext.User
                where user.AuthToken == authToken && (user.WorldId == null || user.WorldId == world.Id)
                select user
                ).FirstOrDefault();

            if (discoveredUser == null || !discoveredUser.Enabled)
            {
                var failedRequest = AuthenticationUtil.MakeFailedRecord(context.HttpContext, authHeaders);
                if (discoveredUser == null)
                {
                    failedRequest.Reason = $"No user found with given token: '{authToken}'";
                    context.Result       = new ContentResult {
                        Content = failedAuthMessage, ContentType = "text/plain", StatusCode = 401
                    };
                }
                else
                {
                    var disablingEvent = dbContext.UserLog.Where(u => u.Id == discoveredUser.Uid).OrderByDescending(l => l.TransactionTime).FirstOrDefault();
                    var disablingAdmin = disablingEvent?.AdminPlayerId == null
                        ? null
                        : dbContext.Player.Where(p => p.PlayerId == disablingEvent.AdminPlayerId.Value).FirstOrDefault();

                    failedRequest.Reason = "Requested by disabled user";
                    context.Result       = new ContentResult
                    {
                        Content = JsonConvert.SerializeObject(new
                        {
                            Enabled    = false,
                            DisabledBy = disablingAdmin?.PlayerName ?? "Unknown",
                            DisabledAt = disablingEvent?.TransactionTime
                        }),
                        ContentType = MediaTypeNames.Application.Json,
                        StatusCode  = 401
                    };
                }

                dbContext.Add(failedRequest);
                dbContext.SaveChanges();

                LogFailedRequest(failedRequest);
                return;
            }

            if (discoveredUser.PlayerId != authHeaders.PlayerId.Value)
            {
                var failedRequest = AuthenticationUtil.MakeFailedRecord(context.HttpContext, authHeaders);
                failedRequest.Reason = $"Player ID {authHeaders.PlayerId.Value} did not match the player ID associated with for token, got PID {discoveredUser.PlayerId}";

                dbContext.Add(failedRequest);
                dbContext.SaveChanges();
                context.Result = new ContentResult {
                    Content = failedAuthMessage, ContentType = "text/plain", StatusCode = 401
                };
                return;
            }

            if (discoveredUser.PermissionsLevel < Configuration.Security.MinimumRequiredPriveleges)
            {
                var failedRequest = AuthenticationUtil.MakeFailedRecord(context.HttpContext, authHeaders);
                failedRequest.Reason = $"User privileges '{discoveredUser.PermissionsLevel}' was less than the minimum '{Configuration.Security.MinimumRequiredPriveleges}'";

                dbContext.Add(failedRequest);
                dbContext.SaveChanges();
                context.Result = new ContentResult {
                    Content = failedAuthMessage, ContentType = "text/plain", StatusCode = 401
                };
                return;
            }

            context.HttpContext.Items["UserId"]       = discoveredUser.Uid;
            context.HttpContext.Items["UserIsSitter"] = authHeaders.IsSitter;

            context.HttpContext.Items["UserPermissions"] =
                authHeaders.IsSitter && Configuration.Security.RestrictSitterAccess
                    ? (short)PermissionLevel.Default
                    : discoveredUser.PermissionsLevel;

            context.HttpContext.Items["PlayerId"]      = authHeaders.PlayerId.Value;
            context.HttpContext.Items["TribeId"]       = authHeaders.TribeId.Value;
            context.HttpContext.Items["AuthToken"]     = authHeaders.AuthToken.Value;
            context.HttpContext.Items["AccessGroupId"] = discoveredUser.AccessGroupId;

            context.HttpContext.Items["User"] = discoveredUser;
        }
Example #4
0
        public static Scaffold.FailedAuthorizationRecord MakeFailedRecord(HttpContext httpContext, AuthHeaders headers)
        {
            var ip = httpContext.Connection.RemoteIpAddress;

            return(new Scaffold.FailedAuthorizationRecord
            {
                Ip = ip,
                OccurredAt = DateTime.UtcNow,
                PlayerId = headers?.PlayerId,
                TribeId = headers?.TribeId,
                RequestedEndpoint = httpContext.Request.Path.Value
            });
        }