Migrate to http-enumerator
This commit is contained in:
parent
8227bb17a9
commit
7ebf584f52
@ -1,11 +1,13 @@
|
|||||||
{-# LANGUAGE FlexibleContexts #-}
|
{-# LANGUAGE FlexibleContexts #-}
|
||||||
module Web.Authenticate.Facebook where
|
module Web.Authenticate.Facebook where
|
||||||
|
|
||||||
import Network.HTTP.Wget
|
import Network.HTTP.Enumerator
|
||||||
import Data.List (intercalate)
|
import Data.List (intercalate)
|
||||||
import Data.Object
|
import Data.Object
|
||||||
import Data.Object.Json
|
import Data.Object.Json
|
||||||
import Data.ByteString.Char8 (pack)
|
import qualified Data.ByteString.Lazy.Char8 as L8
|
||||||
|
import qualified Data.ByteString.Lazy as L
|
||||||
|
import qualified Data.ByteString as S
|
||||||
|
|
||||||
data Facebook = Facebook
|
data Facebook = Facebook
|
||||||
{ facebookClientId :: String
|
{ facebookClientId :: String
|
||||||
@ -43,8 +45,8 @@ accessTokenUrl fb code = concat
|
|||||||
getAccessToken :: Facebook -> String -> IO AccessToken
|
getAccessToken :: Facebook -> String -> IO AccessToken
|
||||||
getAccessToken fb code = do
|
getAccessToken fb code = do
|
||||||
let url = accessTokenUrl fb code
|
let url = accessTokenUrl fb code
|
||||||
b <- wget url [] []
|
b <- simpleHttp url
|
||||||
let (front, back) = splitAt 13 b
|
let (front, back) = splitAt 13 $ L8.unpack b
|
||||||
case front of
|
case front of
|
||||||
"access_token=" -> return $ AccessToken back
|
"access_token=" -> return $ AccessToken back
|
||||||
_ -> error $ "Invalid facebook response: " ++ back
|
_ -> error $ "Invalid facebook response: " ++ back
|
||||||
@ -60,5 +62,5 @@ graphUrl (AccessToken s) func = concat
|
|||||||
getGraphData :: AccessToken -> String -> IO StringObject
|
getGraphData :: AccessToken -> String -> IO StringObject
|
||||||
getGraphData at func = do
|
getGraphData at func = do
|
||||||
let url = graphUrl at func
|
let url = graphUrl at func
|
||||||
b <- wget url [] []
|
b <- simpleHttp url
|
||||||
decode $ pack b
|
decode $ S.concat $ L.toChunks b
|
||||||
|
|||||||
@ -23,7 +23,7 @@ module Web.Authenticate.OpenId
|
|||||||
, AuthenticateException (..)
|
, AuthenticateException (..)
|
||||||
) where
|
) where
|
||||||
|
|
||||||
import Network.HTTP.Wget
|
import Network.HTTP.Enumerator
|
||||||
import Text.HTML.TagSoup
|
import Text.HTML.TagSoup
|
||||||
import Numeric (showHex)
|
import Numeric (showHex)
|
||||||
import "transformers" Control.Monad.IO.Class
|
import "transformers" Control.Monad.IO.Class
|
||||||
@ -31,6 +31,7 @@ import Data.Data
|
|||||||
import Control.Failure hiding (Error)
|
import Control.Failure hiding (Error)
|
||||||
import Control.Exception
|
import Control.Exception
|
||||||
import Control.Monad (liftM)
|
import Control.Monad (liftM)
|
||||||
|
import qualified Data.ByteString.Lazy.Char8 as L8
|
||||||
|
|
||||||
-- | An openid identifier (ie, a URL).
|
-- | An openid identifier (ie, a URL).
|
||||||
newtype Identifier = Identifier { identifier :: String }
|
newtype Identifier = Identifier { identifier :: String }
|
||||||
@ -44,12 +45,16 @@ instance Monad Error where
|
|||||||
fail s = Error s
|
fail s = Error s
|
||||||
|
|
||||||
-- | Returns a URL to forward the user to in order to login.
|
-- | Returns a URL to forward the user to in order to login.
|
||||||
getForwardUrl :: (MonadIO m, Failure WgetException m)
|
getForwardUrl :: (MonadIO m,
|
||||||
|
Failure InvalidUrlException m,
|
||||||
|
Failure HttpException m
|
||||||
|
)
|
||||||
=> String -- ^ The openid the user provided.
|
=> String -- ^ The openid the user provided.
|
||||||
-> String -- ^ The URL for this application\'s complete page.
|
-> String -- ^ The URL for this application\'s complete page.
|
||||||
-> m String -- ^ URL to send the user to.
|
-> m String -- ^ URL to send the user to.
|
||||||
getForwardUrl openid complete = do
|
getForwardUrl openid complete = do
|
||||||
bodyIdent <- wget openid [] []
|
bodyIdent' <- simpleHttp openid
|
||||||
|
let bodyIdent = L8.unpack bodyIdent'
|
||||||
server <- getOpenIdVar "server" bodyIdent
|
server <- getOpenIdVar "server" bodyIdent
|
||||||
let delegate = maybe openid id
|
let delegate = maybe openid id
|
||||||
$ getOpenIdVar "delegate" bodyIdent
|
$ getOpenIdVar "delegate" bodyIdent
|
||||||
@ -70,25 +75,28 @@ getOpenIdVar var content = do
|
|||||||
mhead [] = fail $ "Variable not found: openid." ++ var -- FIXME
|
mhead [] = fail $ "Variable not found: openid." ++ var -- FIXME
|
||||||
mhead (x:_) = return x
|
mhead (x:_) = return x
|
||||||
|
|
||||||
constructUrl :: String -> [(String, String)] -> String
|
constructUrl :: String -> [(String, String)] -> String -- FIXME no longer needed, use Request value directly
|
||||||
constructUrl url [] = url
|
constructUrl url [] = url
|
||||||
constructUrl url args = url ++ "?" ++ queryString args
|
constructUrl url args = url ++ "?" ++ queryString' args
|
||||||
where
|
where
|
||||||
queryString [] = error "queryString with empty args cannot happen"
|
queryString' [] = error "queryString with empty args cannot happen"
|
||||||
queryString [first] = onePair first
|
queryString' [first] = onePair first
|
||||||
queryString (first:rest) = onePair first ++ "&" ++ queryString rest
|
queryString' (first:rest) = onePair first ++ "&" ++ queryString' rest
|
||||||
onePair (x, y) = urlEncode x ++ "=" ++ urlEncode y
|
onePair (x, y) = urlEncode x ++ "=" ++ urlEncode y
|
||||||
|
|
||||||
-- | Handle a redirect from an OpenID provider and check that the user
|
-- | Handle a redirect from an OpenID provider and check that the user
|
||||||
-- logged in properly. If it was successfully, 'return's the openid.
|
-- logged in properly. If it was successfully, 'return's the openid.
|
||||||
-- Otherwise, 'failure's an explanation.
|
-- Otherwise, 'failure's an explanation.
|
||||||
authenticate :: (MonadIO m, Failure WgetException m,
|
authenticate :: (MonadIO m,
|
||||||
Failure AuthenticateException m)
|
Failure AuthenticateException m,
|
||||||
|
Failure InvalidUrlException m,
|
||||||
|
Failure HttpException m)
|
||||||
=> [(String, String)]
|
=> [(String, String)]
|
||||||
-> m Identifier
|
-> m Identifier
|
||||||
authenticate req = do -- FIXME check openid.mode == id_res (not cancel)
|
authenticate req = do -- FIXME check openid.mode == id_res (not cancel)
|
||||||
authUrl <- getAuthUrl req
|
authUrl <- getAuthUrl req
|
||||||
content <- wget authUrl [] []
|
content' <- simpleHttp authUrl
|
||||||
|
let content = L8.unpack content'
|
||||||
let isValid = contains "is_valid:true" content
|
let isValid = contains "is_valid:true" content
|
||||||
if isValid
|
if isValid
|
||||||
then Identifier `liftM` alookup "openid.identity" req
|
then Identifier `liftM` alookup "openid.identity" req
|
||||||
@ -99,7 +107,7 @@ alookup :: (Failure AuthenticateException m, Monad m)
|
|||||||
-> [(String, String)]
|
-> [(String, String)]
|
||||||
-> m String
|
-> m String
|
||||||
alookup k x = case lookup k x of
|
alookup k x = case lookup k x of
|
||||||
Just k -> return k
|
Just k' -> return k'
|
||||||
Nothing -> failure $ MissingOpenIdParameter k
|
Nothing -> failure $ MissingOpenIdParameter k
|
||||||
|
|
||||||
data AuthenticateException = AuthenticateException String
|
data AuthenticateException = AuthenticateException String
|
||||||
@ -107,14 +115,14 @@ data AuthenticateException = AuthenticateException String
|
|||||||
deriving (Show, Typeable)
|
deriving (Show, Typeable)
|
||||||
instance Exception AuthenticateException
|
instance Exception AuthenticateException
|
||||||
|
|
||||||
getAuthUrl :: (MonadIO m,
|
getAuthUrl :: (MonadIO m, Failure AuthenticateException m,
|
||||||
Failure AuthenticateException m,
|
Failure InvalidUrlException m,
|
||||||
Failure WgetException m)
|
Failure HttpException m)
|
||||||
=> [(String, String)] -> m String
|
=> [(String, String)] -> m String
|
||||||
getAuthUrl req = do
|
getAuthUrl req = do
|
||||||
identity <- alookup "openid.identity" req
|
identity <- alookup "openid.identity" req
|
||||||
idContent <- wget identity [] []
|
idContent <- simpleHttp identity
|
||||||
helper idContent
|
helper $ L8.unpack idContent
|
||||||
where
|
where
|
||||||
helper idContent = do
|
helper idContent = do
|
||||||
server <- getOpenIdVar "server" idContent
|
server <- getOpenIdVar "server" idContent
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
{-# LANGUAGE FlexibleContexts #-}
|
{-# LANGUAGE FlexibleContexts #-}
|
||||||
{-# LANGUAGE CPP #-}
|
{-# LANGUAGE CPP #-}
|
||||||
{-# LANGUAGE PackageImports #-}
|
{-# LANGUAGE PackageImports #-}
|
||||||
|
{-# LANGUAGE OverloadedStrings #-}
|
||||||
---------------------------------------------------------
|
---------------------------------------------------------
|
||||||
--
|
--
|
||||||
-- Module : Web.Authenticate.Rpxnow
|
-- Module : Web.Authenticate.Rpxnow
|
||||||
@ -21,13 +22,15 @@ module Web.Authenticate.Rpxnow
|
|||||||
|
|
||||||
import Data.Object
|
import Data.Object
|
||||||
import Data.Object.Json
|
import Data.Object.Json
|
||||||
import Network.HTTP.Wget
|
import Network.HTTP.Enumerator
|
||||||
import "transformers" Control.Monad.IO.Class
|
import "transformers" Control.Monad.IO.Class
|
||||||
import Control.Failure
|
import Control.Failure
|
||||||
import Data.Maybe
|
import Data.Maybe
|
||||||
import Web.Authenticate.OpenId (AuthenticateException (..))
|
import Web.Authenticate.OpenId (AuthenticateException (..))
|
||||||
import Control.Monad
|
import Control.Monad
|
||||||
import Data.ByteString.Char8 (pack)
|
import qualified Data.ByteString.Char8 as S
|
||||||
|
import qualified Data.ByteString.Lazy.Char8 as L
|
||||||
|
import Control.Exception (throwIO)
|
||||||
|
|
||||||
-- | Information received from Rpxnow after a valid login.
|
-- | Information received from Rpxnow after a valid login.
|
||||||
data Identifier = Identifier
|
data Identifier = Identifier
|
||||||
@ -37,7 +40,8 @@ data Identifier = Identifier
|
|||||||
|
|
||||||
-- | Attempt to log a user in.
|
-- | Attempt to log a user in.
|
||||||
authenticate :: (MonadIO m,
|
authenticate :: (MonadIO m,
|
||||||
Failure WgetException m,
|
Failure HttpException m,
|
||||||
|
Failure InvalidUrlException m,
|
||||||
Failure AuthenticateException m,
|
Failure AuthenticateException m,
|
||||||
Failure ObjectExtractError m,
|
Failure ObjectExtractError m,
|
||||||
Failure JsonDecodeError m)
|
Failure JsonDecodeError m)
|
||||||
@ -45,16 +49,34 @@ authenticate :: (MonadIO m,
|
|||||||
-> String -- ^ Token passed by client.
|
-> String -- ^ Token passed by client.
|
||||||
-> m Identifier
|
-> m Identifier
|
||||||
authenticate apiKey token = do
|
authenticate apiKey token = do
|
||||||
b <- wget "https://rpxnow.com/api/v2/auth_info"
|
let body = L.fromChunks
|
||||||
[]
|
[ "apiKey="
|
||||||
[ ("apiKey", apiKey)
|
, S.pack apiKey
|
||||||
, ("token", token)
|
, "&token="
|
||||||
]
|
, S.pack token
|
||||||
o <- decode $ pack b
|
]
|
||||||
|
let req =
|
||||||
|
Request
|
||||||
|
{ method = "POST"
|
||||||
|
, secure = True
|
||||||
|
, host = "rpxnow.com"
|
||||||
|
, port = 443
|
||||||
|
, path = "api/v2/auth_info"
|
||||||
|
, queryString = []
|
||||||
|
, requestHeaders =
|
||||||
|
[ ("Content-Type", "application/x-www-form-urlencoded")
|
||||||
|
]
|
||||||
|
, requestBody = body
|
||||||
|
}
|
||||||
|
res <- httpLbsRedirect req
|
||||||
|
let b = responseBody res
|
||||||
|
unless (200 <= statusCode res && statusCode res < 300) $
|
||||||
|
liftIO $ throwIO $ HttpException (statusCode res) b
|
||||||
|
o <- decode $ S.concat $ L.toChunks b
|
||||||
m <- fromMapping o
|
m <- fromMapping o
|
||||||
stat <- lookupScalar "stat" m
|
stat <- lookupScalar "stat" m
|
||||||
unless (stat == "ok") $ failure $ AuthenticateException $
|
unless (stat == "ok") $ failure $ AuthenticateException $
|
||||||
"Rpxnow login not accepted: " ++ stat ++ "\n" ++ b
|
"Rpxnow login not accepted: " ++ stat ++ "\n" ++ L.unpack b
|
||||||
parseProfile m
|
parseProfile m
|
||||||
|
|
||||||
parseProfile :: (Monad m, Failure ObjectExtractError m)
|
parseProfile :: (Monad m, Failure ObjectExtractError m)
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
name: authenticate
|
name: authenticate
|
||||||
version: 0.6.3.2
|
version: 0.6.4
|
||||||
license: BSD3
|
license: BSD3
|
||||||
license-file: LICENSE
|
license-file: LICENSE
|
||||||
author: Michael Snoyman <michael@snoyman.com>
|
author: Michael Snoyman <michael@snoyman.com>
|
||||||
@ -17,7 +17,7 @@ library
|
|||||||
build-depends: base >= 4 && < 5,
|
build-depends: base >= 4 && < 5,
|
||||||
data-object >= 0.3.1 && < 0.4,
|
data-object >= 0.3.1 && < 0.4,
|
||||||
data-object-json >= 0.3.1 && < 0.4,
|
data-object-json >= 0.3.1 && < 0.4,
|
||||||
http-wget >= 0.6 && < 0.7,
|
http-enumerator >= 0.1.1 && < 0.2,
|
||||||
tagsoup >= 0.6 && < 0.12,
|
tagsoup >= 0.6 && < 0.12,
|
||||||
failure >= 0.0.0 && < 0.2,
|
failure >= 0.0.0 && < 0.2,
|
||||||
transformers >= 0.1 && < 0.3,
|
transformers >= 0.1 && < 0.3,
|
||||||
|
|||||||
@ -3,6 +3,7 @@ import Yesod
|
|||||||
import Web.Authenticate.Facebook
|
import Web.Authenticate.Facebook
|
||||||
import Data.Object
|
import Data.Object
|
||||||
import Data.Maybe (fromMaybe)
|
import Data.Maybe (fromMaybe)
|
||||||
|
import Network.HTTP.Enumerator
|
||||||
|
|
||||||
data FB = FB Facebook
|
data FB = FB Facebook
|
||||||
fb :: FB
|
fb :: FB
|
||||||
@ -22,9 +23,9 @@ getRootR = do
|
|||||||
|
|
||||||
getFacebookR = do
|
getFacebookR = do
|
||||||
FB f <- getYesod
|
FB f <- getYesod
|
||||||
code <- runFormGet $ required $ input "code"
|
code <- runFormGet' $ stringInput "code"
|
||||||
at <- liftIO $ getAccessToken f code
|
at <- liftIO $ getAccessToken f code
|
||||||
mreq <-runFormGet $ optional $ input "req"
|
mreq <- runFormGet' $ maybeStringInput "req"
|
||||||
let req = fromMaybe "me" mreq
|
let req = fromMaybe "me" mreq
|
||||||
so <- liftIO $ getGraphData at req
|
so <- liftIO $ getGraphData at req
|
||||||
let so' = objToHamlet so
|
let so' = objToHamlet so
|
||||||
@ -39,7 +40,7 @@ getFacebookR = do
|
|||||||
^so'^
|
^so'^
|
||||||
|]
|
|]
|
||||||
|
|
||||||
main = toWaiApp fb >>= basicHandler 3000
|
main = withHttpEnumerator $ basicHandler 3000 fb
|
||||||
|
|
||||||
objToHamlet :: StringObject -> Hamlet url
|
objToHamlet :: StringObject -> Hamlet url
|
||||||
objToHamlet (Scalar s) = [$hamlet|$string.s$|]
|
objToHamlet (Scalar s) = [$hamlet|$string.s$|]
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user