Data class used in conjunction with AuthenticationTicket This is part of the mod_auth_tkt algorithm implementation
예제 #1
0
        /// <summary>
        /// Parses the decoded ticket.
        /// </summary>
        /// <param name="ticket">Ticket to be parsed.</param>
        /// <returns>AuthenticationTicketData instance containing the parsed ticket data.</returns>
        /// <remarks>
        /// The expected format of the ticket is:
        ///     digest (32 chars) + hex timestamp (8 chars) + user ID + '!' + user data
        /// OR
        ///     digest (32 chars) + hex timestamp (8 chars) + user ID + '!' + tokens + '!' user data
        /// </remarks>
        private static AuthenticationTicketData Parse(string ticket)
        {
            if (string.IsNullOrWhiteSpace(ticket) || ticket.Length < 40)
            {
                return(null);
            }

            string[] ticketParts = (ticket.Length > 40) ? ticket.Substring(40).Split('!') : null;
            int      length      = (ticketParts != null) ? ticketParts.Length : 0;

            if (ticketParts == null)
            {
                return(null);
            }

            var ticketData = new AuthenticationTicketData
            {
                Digest         = ticket.Substring(0, 32),
                HexTimeStamp   = ticket.Substring(32, 8),
                UserId         = (length > 0) ? ticketParts[0] : string.Empty,
                TokensAsString = (length > 2) ? ticketParts[1] : string.Empty,
                UserData       = (length > 1) ? ticketParts[length - 1] : string.Empty
            };

            return(ticketData);
        }
예제 #2
0
        /// <summary>
        /// Creates a Base64-encoded ticket based on the provided data.
        /// </summary>
        /// <param name="userId">User ID</param>
        /// <param name="userData">User Data</param>
        /// <param name="tokens">Comma-delimited string of data</param>
        /// <param name="timeStamp">Time Stamp</param>
        /// <param name="secret">Secret key used to create the ticket</param>
        /// <param name="encode">True if the user id, user data, and tokens are to be encoded; false otherwise</param>
        /// <param name="ipAddress">IP Address</param>
        /// <param name="version">Version of the mod_auth_tkt algorithm used to create the ticket</param>
        /// <returns>String ticket</returns>
        /// <remarks>The ticket is created using the mod_auth_tkt algorithm.</remarks>
        public static string Create(string userId, string userData, string tokens, DateTime timeStamp, string secret,
                                    bool encode    = false, string ipAddress = AuthenticationTicketData.DefaultIPAddress,
                                    string version = AuthenticationTicketData.DefaultVersion)
        {
            var ticketData = new AuthenticationTicketData
            {
                UserId         = userId,
                UserData       = userData,
                TokensAsString = tokens,
                IPAddress      = ipAddress,
                TimeStamp      = timeStamp,
                Version        = version
            };

            return(Create(ticketData, secret, encode));
        }
        /// <summary>
        /// Creates a Base64-encoded ticket based on the provided data.
        /// </summary>
        /// <param name="ticketData">Data used to create the ticket.</param>
        /// <param name="secret">Secret key used to create the ticket.</param>
        /// <param name="encode">True if the user id, user data, and tokens are to be encoded; false otherwise</param>
        /// <returns>String ticket</returns>
        /// <remarks>The ticket is created using the mod_auth_tkt algorithm.</remarks>
        public static string Create(AuthenticationTicketData ticketData, string secret, bool encode = false)
        {
            if (ticketData == null)
            {
                return null;
            }

            string digest = CreateDigest(ticketData, secret);
            string userId = (encode) ? Encode(ticketData.UserId, secret, ticketData.UnixTimeStamp, 0) : ticketData.UserId;
            string tokens = (encode)
                                ? Encode(ticketData.TokensAsString, secret, ticketData.UnixTimeStamp, 4)
                                : ticketData.TokensAsString;
            string userData = (encode) ? Encode(ticketData.UserData, secret, ticketData.UnixTimeStamp, 8) : ticketData.UserData;

            string ticket = digest + ticketData.HexTimeStamp + userId + '!';
            ticket += (string.IsNullOrEmpty(tokens)) ? userData : tokens + '!' + userData;

            return Base64Helper.Encode(ticket);
        }
예제 #4
0
        /// <summary>
        /// Validates a ticket based on the provided data.
        /// </summary>
        /// <param name="ticket">Base64-encoded ticket to be validated</param>
        /// <param name="secret">Secret key used to create the ticket</param>
        /// <param name="encoded">True if the user id, user data, and tokens are encoded; false otherwise </param>
        /// <param name="ipAddress">IP Address used to create the ticket</param>
        /// <param name="version">Version of the mod_auth_tkt algorithm used to validate the ticket</param>
        /// <returns>True if ticket is valid, false otherwise</returns>
        public static bool Validate(string ticket, string secret, bool encoded = false,
                                    string ipAddress = AuthenticationTicketData.DefaultIPAddress,
                                    string version   = AuthenticationTicketData.DefaultVersion)
        {
            AuthenticationTicketData ticketData = ExtractData(ticket, secret, encoded, ipAddress);
            string digest = null;

            if (ticketData != null)
            {
                ticketData.Version = version;
                digest             = ticketData.Digest;
            }

            string expectedDigest = CreateDigest(ticketData, secret);

            bool valid = (!string.IsNullOrEmpty(digest) && !string.IsNullOrEmpty(expectedDigest) && expectedDigest == digest);

            return(valid);
        }
예제 #5
0
        /// <summary>
        /// Creates a Base64-encoded ticket based on the provided data.
        /// </summary>
        /// <param name="ticketData">Data used to create the ticket.</param>
        /// <param name="secret">Secret key used to create the ticket.</param>
        /// <param name="encode">True if the user id, user data, and tokens are to be encoded; false otherwise</param>
        /// <returns>String ticket</returns>
        /// <remarks>The ticket is created using the mod_auth_tkt algorithm.</remarks>
        public static string Create(AuthenticationTicketData ticketData, string secret, bool encode = false)
        {
            if (ticketData == null)
            {
                return(null);
            }

            string digest = CreateDigest(ticketData, secret);
            string userId = (encode) ? Encode(ticketData.UserId, secret, ticketData.UnixTimeStamp, 0) : ticketData.UserId;
            string tokens = (encode)
                                                                ? Encode(ticketData.TokensAsString, secret, ticketData.UnixTimeStamp, 4)
                                                                : ticketData.TokensAsString;
            string userData = (encode) ? Encode(ticketData.UserData, secret, ticketData.UnixTimeStamp, 8) : ticketData.UserData;

            string ticket = digest + ticketData.HexTimeStamp + userId + '!';

            ticket += (string.IsNullOrEmpty(tokens)) ? userData : tokens + '!' + userData;

            return(Base64Helper.Encode(ticket));
        }
예제 #6
0
        /// <summary>
        /// Creates the digest portion of the ticket from the provided data.
        /// </summary>
        /// <param name="ticketData">Data used to create the digest</param>
        /// <param name="secret">Secret key used to create the digest</param>
        /// <returns>Digest string</returns>
        /// <remarks>
        /// The algorithm for the digest is as follows:
        ///     digest = MD5(digest0 + key)
        /// where
        ///     Version 1.3: digest0 = MD5(iptstamp + key + user_id + user_data)
        ///     Version 2.0: digest0 = MD5(iptstamp + key + user_id + '\0' + token_list + '\0' + user_data)
        /// </remarks>
        private static string CreateDigest(AuthenticationTicketData ticketData, string secret)
        {
            if (ticketData == null)
            {
                return(null);
            }

            if (string.IsNullOrWhiteSpace(secret))
            {
                secret = DefaultSecret;
            }

            string iptStamp = CreateIPTimeStamp(ticketData.IPAddressAsInt, ticketData.UnixTimeStamp);
            string digest;
            const HashHelper.HashType hashType = HashHelper.HashType.MD5;

            switch (ticketData.Version)
            {
            case "1.3":
                digest = HashHelper.Hash(iptStamp + secret + ticketData.UserId + ticketData.UserData, hashType);
                digest = HashHelper.Hash(digest + secret, hashType);
                break;

            case "2.0":
                digest =
                    HashHelper.Hash(
                        iptStamp + secret + ticketData.UserId + '\0' + ticketData.TokensAsString + '\0' + ticketData.UserData, hashType);
                digest = HashHelper.Hash(digest + secret, hashType);
                break;

            default:
                throw new NotSupportedException(string.Format("Version {0} of the mod_auth_tkt algorithm is not supported",
                                                              ticketData.Version));
            }

            return(digest);
        }
예제 #7
0
        /// <summary>
        /// Extracts the data from a provided ticket.
        /// </summary>
        /// <param name="ticket">Base64-encoded ticket to parse for data</param>
        /// <param name="secret">Secret key used to create the ticket</param>
        /// <param name="encoded">True if the user id, user data, and tokens are encoded; false otherwise</param>
        /// <param name="ipAddress">IP Address used to create the ticket</param>
        /// <returns>AuthenticationTicketData instance containing the parsed ticket data.</returns>
        public static AuthenticationTicketData ExtractData(string ticket, string secret = null, bool encoded = false,
                                                           string ipAddress             = AuthenticationTicketData.DefaultIPAddress)
        {
            if (string.IsNullOrWhiteSpace(ticket))
            {
                return(null);
            }

            if (string.IsNullOrWhiteSpace(secret))
            {
                secret = DefaultSecret;
            }

            AuthenticationTicketData ticketData = null;

            ticket = Base64Helper.DecodeToString(ticket);

            if (!string.IsNullOrWhiteSpace(ticket) && ticket.Length >= 40)
            {
                ticketData = Parse(ticket);

                if (ticketData != null)
                {
                    ticketData.IPAddress = ipAddress;

                    if (encoded)
                    {
                        ticketData.UserId         = Decode(ticketData.UserId, secret, ticketData.UnixTimeStamp, 0);
                        ticketData.TokensAsString = Decode(ticketData.TokensAsString, secret, ticketData.UnixTimeStamp, 4);
                        ticketData.UserData       = Decode(ticketData.UserData, secret, ticketData.UnixTimeStamp, 8);
                    }
                }
            }

            return(ticketData);
        }
        /// <summary>
        /// Creates a Base64-encoded ticket based on the provided data.
        /// </summary>
        /// <param name="userId">User ID</param>
        /// <param name="userData">User Data</param>
        /// <param name="tokens">Comma-delimited string of data</param>
        /// <param name="timeStamp">Time Stamp</param>
        /// <param name="secret">Secret key used to create the ticket</param>
        /// <param name="encode">True if the user id, user data, and tokens are to be encoded; false otherwise</param>
        /// <param name="ipAddress">IP Address</param>
        /// <param name="version">Version of the mod_auth_tkt algorithm used to create the ticket</param>
        /// <returns>String ticket</returns>
        /// <remarks>The ticket is created using the mod_auth_tkt algorithm.</remarks>
        public static string Create(string userId, string userData, string tokens, DateTime timeStamp, string secret,
            bool encode = false, string ipAddress = AuthenticationTicketData.DefaultIPAddress,
            string version = AuthenticationTicketData.DefaultVersion)
        {
            var ticketData = new AuthenticationTicketData
                             {
                                UserId = userId,
                                UserData = userData,
                                TokensAsString = tokens,
                                IPAddress = ipAddress,
                                TimeStamp = timeStamp,
                                Version = version
                             };

            return Create(ticketData, secret, encode);
        }
        /// <summary>
        /// Parses the decoded ticket.
        /// </summary>
        /// <param name="ticket">Ticket to be parsed.</param>
        /// <returns>AuthenticationTicketData instance containing the parsed ticket data.</returns>
        /// <remarks>
        /// The expected format of the ticket is:
        ///     digest (32 chars) + hex timestamp (8 chars) + user ID + '!' + user data
        /// OR
        ///     digest (32 chars) + hex timestamp (8 chars) + user ID + '!' + tokens + '!' user data
        /// </remarks>
        private static AuthenticationTicketData Parse(string ticket)
        {
            if (string.IsNullOrWhiteSpace(ticket) || ticket.Length < 40)
            {
                return null;
            }

            string[] ticketParts = (ticket.Length > 40) ? ticket.Substring(40).Split('!') : null;
            int length = (ticketParts != null) ? ticketParts.Length : 0;

            if (ticketParts == null) return null;

            var ticketData = new AuthenticationTicketData
                             {
                                Digest = ticket.Substring(0, 32),
                                HexTimeStamp = ticket.Substring(32, 8),
                                UserId = (length > 0) ? ticketParts[0] : string.Empty,
                                TokensAsString = (length > 2) ? ticketParts[1] : string.Empty,
                                UserData = (length > 1) ? ticketParts[length - 1] : string.Empty
                             };

            return ticketData;
        }
        /// <summary>
        /// Creates the digest portion of the ticket from the provided data.
        /// </summary>
        /// <param name="ticketData">Data used to create the digest</param>
        /// <param name="secret">Secret key used to create the digest</param>
        /// <returns>Digest string</returns>
        /// <remarks>
        /// The algorithm for the digest is as follows:
        /// 	digest = MD5(digest0 + key)
        /// where
        ///     Version 1.3: digest0 = MD5(iptstamp + key + user_id + user_data) 
        ///     Version 2.0: digest0 = MD5(iptstamp + key + user_id + '\0' + token_list + '\0' + user_data)
        /// </remarks>
        private static string CreateDigest(AuthenticationTicketData ticketData, string secret)
        {
            if (ticketData == null)
            {
                return null;
            }

            if (string.IsNullOrWhiteSpace(secret))
            {
                secret = DefaultSecret;
            }

            string iptStamp = CreateIPTimeStamp(ticketData.IPAddressAsInt, ticketData.UnixTimeStamp);
            string digest;
            const HashHelper.HashType hashType = HashHelper.HashType.MD5;

            switch (ticketData.Version)
            {
                case "1.3":
                    digest = HashHelper.Hash(iptStamp + secret + ticketData.UserId + ticketData.UserData, hashType);
                    digest = HashHelper.Hash(digest + secret, hashType);
                    break;

                case "2.0":
                    digest =
                        HashHelper.Hash(
                            iptStamp + secret + ticketData.UserId + '\0' + ticketData.TokensAsString + '\0' + ticketData.UserData, hashType);
                    digest = HashHelper.Hash(digest + secret, hashType);
                    break;

                default:
                    throw new NotSupportedException(string.Format("Version {0} of the mod_auth_tkt algorithm is not supported",
                                                                  ticketData.Version));
            }

            return digest;
        }