public static async void AuthSessionHandler(AuthSession authSession, CharacterSession session)
        {
            var accountParts = authSession.Account.Split(new[] { '#' });
            var authResult = AuthResult.Ok;

            if (accountParts.Length == 2)
            {
                var accountId = int.Parse(accountParts[0]);
                var gameIndex = byte.Parse(accountParts[1]);

                session.Account = DB.Auth.Single<Account>(a => a.Id == accountId);

                if (session.Account != null)
                    session.GameAccount = session.Account.GameAccounts.SingleOrDefault(ga => ga.Index == gameIndex);

                if (session.GameAccount != null)
                    session.Crypt = new WoWCrypt(session.GameAccount.SessionKey.ToByteArray());
                else
                    authResult = AuthResult.Failed;
            }

            session.Realm = DB.Auth.Single<Realm>(r => r.Id == authSession.RealmID);

            if (authSession.LoginServerType != (sbyte)LoginServerTypes.Battlenet || session.Realm == null)
                authResult = AuthResult.Reject;

            if (authResult == AuthResult.Ok)
            {
                var sha1 = new Sha1();

                sha1.Process(authSession.Account);
                sha1.Process(0u);
                sha1.Process(authSession.LocalChallenge);
                sha1.Process(session.Challenge);
                sha1.Finish(session.GameAccount.SessionKey.ToByteArray(), 40);

                // Check the password digest.
                if (!sha1.Digest.Compare(authSession.Digest))
                    authResult = AuthResult.Failed;
            }

            var authResponse = new AuthResponse
            {
                Result = authResult,
                HasSuccessInfo = authResult == AuthResult.Ok,
            };

            if (authResponse.HasSuccessInfo)
            {
                session.State = SessionState.Authenticated;

                var addonData = AddonHandler.GetAddonInfoData(session, authSession.AddonInfo, authSession.CompressedAddonInfoSize, authSession.UncompressedAddonInfoSize);

                if (addonData != null && addonData.Length != authSession.UncompressedAddonInfoSize)
                {
                    Log.Error("Addon Info data size mismatch.");

                    session.Dispose();

                    return;
                }

                authResponse.SuccessInfo.ActiveExpansionLevel  = session.GameAccount.BoxLevel;
                authResponse.SuccessInfo.AccountExpansionLevel = session.GameAccount.BoxLevel;
                authResponse.SuccessInfo.AvailableRaces        = Manager.GameAccount.GetAvailableRaces(session.GameAccount, session.Realm);
                authResponse.SuccessInfo.AvailableClasses      = Manager.GameAccount.GetAvailableClasses(session.GameAccount, session.Realm);
                authResponse.SuccessInfo.Templates             = Manager.GameAccount.GetAvailableCharacterTemplates(session.GameAccount, session.Realm);

                await session.Send(authResponse);

                AddonHandler.HandleAddonInfo(session, addonData);

                await session.Send(new TutorialFlags());
            }
            else
                await session.Send(authResponse);
        }
        public static void OnAuthSession(Packet packet, RealmSession session)
        {
            // Part of the header
            packet.Read<ushort>();

            var loginServerId   = packet.Read<uint>();
            var build           = packet.Read<short>();
            var localChallenge  = packet.Read<uint>();
            var siteId          = packet.Read<uint>();
            var realmId         = packet.Read<uint>();
            var loginServerType = packet.Read<LoginServerTypes>();
            var buildType       = packet.Read<sbyte>();
            var regionId        = packet.Read<uint>();
            var dosResponse     = packet.Read<ulong>();
            var digest          = packet.ReadBytes(20);
            var accountName     = packet.ReadString(11);
            var useIPv6         = packet.GetBit();

            // AddonInfo stuff
            var compressedAddonInfoSize   = packet.Read<int>();
            var uncompressedAddonInfoSize = packet.Read<int>();
            var compressedAddonData       = packet.ReadBytes(compressedAddonInfoSize - 4);

            var accountParts = accountName.Split(new[] { '#' });
            var authResult = AuthResults.Ok;

            if (loginServerType != LoginServerTypes.Battlenet)
                authResult = AuthResults.Reject;

            if (authResult == AuthResults.Ok)
            {
                if (accountParts.Length == 2)
                {
                    var accountId = int.Parse(accountParts[0]);
                    var gameIndex = byte.Parse(accountParts[1]);

                    var gameAccount = DB.Auth.GameAccounts.SingleOrDefault(ga => ga.AccountId == accountId && ga.Index == gameIndex);

                    if (gameAccount != null)
                    {
                        var sha1 = new Sha1();

                        sha1.Process(accountName);
                        sha1.Process(0u);
                        sha1.Process(localChallenge);
                        sha1.Process(session.Challenge);
                        sha1.Finish(gameAccount.SessionKey.ToByteArray(), 40);

                        // Check the password digest.
                        if (sha1.Digest.Compare(digest))
                        {
                            session.GameAccount = gameAccount;

                            AddonHandler.LoadAddonInfoData(session, compressedAddonData, compressedAddonInfoSize, uncompressedAddonInfoSize);
                        }
                        else
                            authResult = AuthResults.IncorrectPassword;
                    }
                    else
                        authResult = AuthResults.UnknownAccount;
                }
                else
                    authResult = AuthResults.UnknownAccount;
            }

            HandleAuthResponse(authResult, session);

            //TODO [partially done] Implement security checks & field handling.
            //TODO Implement AuthResponse.
        }