/// <summary>
        /// Creates a new instance populated with values from the form encoded body parameters.
        /// </summary>
        /// <param name="parameters">Form encoded body parameters from a request.</param>
        public TokenEndpointRequest(IReadableStringCollection parameters)
        {
            if (parameters == null)
            {
                throw new ArgumentNullException("parameters");
            }

            Parameters = parameters;
            GrantType  = parameters[Constants.Parameters.GrantType];
            ClientId   = parameters[Constants.Parameters.ClientId];
            if (string.Equals(GrantType, Constants.GrantTypes.AuthorizationCode, StringComparison.Ordinal))
            {
                AuthorizationCodeGrant = new TokenEndpointRequestAuthorizationCode
                {
                    Code        = parameters[Constants.Parameters.Code],
                    RedirectUri = parameters[Constants.Parameters.RedirectUri],
                };
            }
            else if (string.Equals(GrantType, Constants.GrantTypes.ClientCredentials, StringComparison.Ordinal))
            {
                ClientCredentialsGrant = new TokenEndpointRequestClientCredentials
                {
                    Scope = ((string)parameters[Constants.Parameters.Scope] ?? string.Empty).Split(' ')
                };
            }
            else if (string.Equals(GrantType, Constants.GrantTypes.RefreshToken, StringComparison.Ordinal))
            {
                RefreshTokenGrant = new TokenEndpointRequestRefreshToken
                {
                    RefreshToken = parameters[Constants.Parameters.RefreshToken],
                    Scope        = ((string)parameters[Constants.Parameters.Scope] ?? string.Empty).Split(' ')
                };
            }
            else if (string.Equals(GrantType, Constants.GrantTypes.Password, StringComparison.Ordinal))
            {
                ResourceOwnerPasswordCredentialsGrant = new TokenEndpointRequestResourceOwnerPasswordCredentials
                {
                    UserName = parameters[Constants.Parameters.Username],
                    Password = parameters[Constants.Parameters.Password],
                    Scope    = ((string)parameters[Constants.Parameters.Scope] ?? string.Empty).Split(' ')
                };
            }
            else if (!string.IsNullOrEmpty(GrantType))
            {
                CustomExtensionGrant = new TokenEndpointRequestCustomExtension
                {
                    Parameters = parameters,
                };
            }
        }
        /// <summary>
        /// Creates a new instance populated with values from the form encoded body parameters.
        /// </summary>
        /// <param name="parameters">Form encoded body parameters from a request.</param>
        public TokenEndpointRequest(IDictionary <string, StringValues> parameters)
        {
            if (parameters == null)
            {
                throw new ArgumentNullException("parameters");
            }

            Parameters = parameters;

            StringValues grantTypeValue;

            parameters.TryGetValue(Constants.Parameters.GrantType, out grantTypeValue);
            GrantType = grantTypeValue;

            StringValues clientIdValue;

            parameters.TryGetValue(Constants.Parameters.ClientId, out clientIdValue);
            ClientId = clientIdValue;

            if (string.Equals(GrantType, Constants.GrantTypes.AuthorizationCode, StringComparison.Ordinal))
            {
                StringValues codeValue;
                parameters.TryGetValue(Constants.Parameters.Code, out codeValue);

                StringValues redirectUrlValue;
                parameters.TryGetValue(Constants.Parameters.RedirectUri, out redirectUrlValue);

                AuthorizationCodeGrant = new TokenEndpointRequestAuthorizationCode
                {
                    Code        = codeValue,
                    RedirectUri = redirectUrlValue
                };
            }
            else if (string.Equals(GrantType, Constants.GrantTypes.ClientCredentials, StringComparison.Ordinal))
            {
                StringValues scopeValue;
                parameters.TryGetValue(Constants.Parameters.Scope, out scopeValue);

                ClientCredentialsGrant = new TokenEndpointRequestClientCredentials
                {
                    Scope = ((string)scopeValue ?? string.Empty).Split(' ')
                };
            }
            else if (string.Equals(GrantType, Constants.GrantTypes.RefreshToken, StringComparison.Ordinal))
            {
                StringValues refreshTokenValue;
                parameters.TryGetValue(Constants.Parameters.RefreshToken, out refreshTokenValue);

                StringValues scopeValue;
                parameters.TryGetValue(Constants.Parameters.Scope, out scopeValue);

                RefreshTokenGrant = new TokenEndpointRequestRefreshToken
                {
                    RefreshToken = refreshTokenValue,
                    Scope        = ((string)scopeValue ?? string.Empty).Split(' ')
                };
            }
            else if (string.Equals(GrantType, Constants.GrantTypes.Password, StringComparison.Ordinal))
            {
                StringValues usernameValue;
                parameters.TryGetValue(Constants.Parameters.Username, out usernameValue);

                StringValues passwordValue;
                parameters.TryGetValue(Constants.Parameters.Scope, out passwordValue);

                StringValues scopeValue;
                parameters.TryGetValue(Constants.Parameters.Scope, out scopeValue);

                ResourceOwnerPasswordCredentialsGrant = new TokenEndpointRequestResourceOwnerPasswordCredentials
                {
                    UserName = usernameValue,
                    Password = passwordValue,
                    Scope    = ((string)scopeValue ?? string.Empty).Split(' ')
                };
            }
            else if (!string.IsNullOrEmpty(GrantType))
            {
                CustomExtensionGrant = new TokenEndpointRequestCustomExtension
                {
                    Parameters = parameters,
                };
            }
        }