module Network.OAuth.ThreeLegged (
ThreeLegged (..), parseThreeLegged, Callback (..),
requestTemporaryToken, buildAuthorizationUrl, requestPermanentToken,
requestTemporaryTokenRaw, requestPermanentTokenRaw,
requestTokenProtocol
) where
import Control.Applicative
import Control.Monad.Trans
import Control.Monad.Trans.Maybe
import qualified Data.ByteString.Lazy as SL
import qualified Data.ByteString as S
import Data.Data
import Network.HTTP.Client (httpLbs)
import Network.HTTP.Client.Request (getUri,parseUrl)
import Network.HTTP.Client.Types (Request (..), Response (..), HttpException)
import Network.HTTP.Types (renderQuery)
import Network.OAuth
import Network.OAuth.MuLens
import Network.OAuth.Stateful
import Network.OAuth.Types.Credentials
import Network.OAuth.Types.Params
import Network.URI
data ThreeLegged =
ThreeLegged { temporaryTokenRequest :: Request
, resourceOwnerAuthorization :: Request
, permanentTokenRequest :: Request
, callback :: Callback
}
deriving ( Show, Typeable )
parseThreeLegged :: String -> String -> String -> Callback -> Either HttpException ThreeLegged
parseThreeLegged a b c d = ThreeLegged <$> parseUrl a <*> parseUrl b <*> parseUrl c <*> pure d
requestTemporaryTokenRaw :: MonadIO m => ThreeLegged -> OAuthT Client m SL.ByteString
requestTemporaryTokenRaw (ThreeLegged {..}) = do
oax <- newParams
req <- sign (oax { workflow = TemporaryTokenRequest callback }) temporaryTokenRequest
resp <- withManager (liftIO . httpLbs req)
return $ responseBody resp
requestTemporaryToken :: MonadIO m => ThreeLegged -> OAuthT Client m (Maybe (Token Temporary))
requestTemporaryToken tl = do
raw <- requestTemporaryTokenRaw tl
s <- getServer
let mayToken = fromUrlEncoded $ SL.toStrict raw
return $ do
(confirmed, tok) <- mayToken
case oAuthVersion s of
OAuthCommunity1 -> return tok
_ -> if confirmed then return tok else fail "Must be confirmed"
buildAuthorizationUrl :: Monad m => ThreeLegged -> OAuthT Temporary m URI
buildAuthorizationUrl (ThreeLegged {..}) = do
c <- getCredentials
return $ getUri $ resourceOwnerAuthorization {
queryString = renderQuery True [ ("oauth_token", Just (c ^. resourceToken . key)) ]
}
requestPermanentTokenRaw :: MonadIO m => ThreeLegged -> Verifier -> OAuthT Temporary m SL.ByteString
requestPermanentTokenRaw (ThreeLegged {..}) verifier = do
oax <- newParams
req <- sign (oax { workflow = PermanentTokenRequest verifier }) permanentTokenRequest
resp <- withManager (liftIO . httpLbs req)
return $ responseBody resp
requestPermanentToken :: MonadIO m => ThreeLegged -> Verifier -> OAuthT Temporary m (Maybe (Token Permanent))
requestPermanentToken tl verifier = do
raw <- requestPermanentTokenRaw tl verifier
return $ fmap snd $ fromUrlEncoded $ SL.toStrict raw
requestTokenProtocol :: MonadIO m => ThreeLegged -> OAuthT Client m (Maybe (Token Permanent))
requestTokenProtocol threeLegged = runMaybeT $ do
cCred <- lift getCredentials
tok <- MaybeT (requestTemporaryToken threeLegged)
MaybeT $ withCred (temporaryCred tok cCred) $ do
url <- buildAuthorizationUrl threeLegged
code <- liftIO $ do
putStr "Please direct the user to the following address\n\n"
putStr " " >> print url >> putStr "\n\n"
putStrLn "... then enter the verification code below (no spaces)\n"
S.getLine
requestPermanentToken threeLegged code