twill-0.1.0.3: src/Service/Twilio.hs
{-# LANGUAGE OverloadedStrings, DeriveDataTypeable, NamedFieldPuns #-}
-- | Just re-exports a few of the types from
-- "Service.Twilio.Types". There are a number of helper functions
-- which are currently exposed by "Service.Twilio.Types" that aren't
-- exposed here.
module Service.Twilio (
-- * Base Twilio types
Price, -- type synonym for 'Int'
Passport (..),
PhoneNumber (..),
SendStatus (..),
APIKind (..),
SMSKind (..),
Id (..), uri,
SMSCore (..),
SMS (..),
-- * Parsing
FromFormUrlencoded (..),
-- * Request signing
requestSignature
) where
import Prelude hiding (id)
import Service.Twilio.Types
import Data.ByteString (ByteString)
import qualified Data.ByteString.Base64 as B64
import Data.Monoid
import Data.List
import Data.Ord
import Crypto.Hash.SHA1 (hash)
import Crypto.MAC.HMAC (hmac)
-- | Given a Passport, a target URL, the raw query string, and a set
-- of body parameters, this function computes the canonical request
-- signature Twilio uses to authenticate itself.
--
-- A more flexible form of 'requestSignature' could be used with the
-- API inconsistencies for HTTP call requests and HTTPS call
-- requests. See the bottom of <http://www.twilio.com/docs/security>
-- for more details.
requestSignature :: Passport
-> ByteString -- ^ The full URL
-> ByteString -- ^ The raw query string including the "?"
-> [(ByteString, ByteString)] -- ^ Post parameters in Body
-> ByteString
requestSignature (Passport _ token) url qs headers =
encode $ url <> qs <> canonize headers
where encode = B64.encode . hmac hash 64 token
canonize = mconcat . map (uncurry mappend) . sortBy (comparing fst)