Slimmed down code
This commit is contained in:
parent
17b5406fce
commit
0da51855ec
@ -34,15 +34,14 @@ import Control.Failure (Failure (failure))
|
|||||||
|
|
||||||
-- | Attempt to resolve an OpenID endpoint, and user identifier.
|
-- | Attempt to resolve an OpenID endpoint, and user identifier.
|
||||||
discover :: (MonadIO m, Failure OpenIdException m)
|
discover :: (MonadIO m, Failure OpenIdException m)
|
||||||
=> Resolver IO
|
=> Identifier
|
||||||
-> Identifier
|
|
||||||
-> m (Provider, Identifier)
|
-> m (Provider, Identifier)
|
||||||
discover resolve ident@(Identifier i) = do
|
discover ident@(Identifier i) = do
|
||||||
res1 <- liftIO $ discoverYADIS resolve ident Nothing
|
res1 <- liftIO $ discoverYADIS ident Nothing
|
||||||
case res1 of
|
case res1 of
|
||||||
Just x -> return x
|
Just x -> return x
|
||||||
Nothing -> do
|
Nothing -> do
|
||||||
res2 <- liftIO $ discoverHTML resolve ident
|
res2 <- liftIO $ discoverHTML ident
|
||||||
case res2 of
|
case res2 of
|
||||||
Just x -> return x
|
Just x -> return x
|
||||||
Nothing -> failure $ DiscoveryException i
|
Nothing -> failure $ DiscoveryException i
|
||||||
@ -51,11 +50,10 @@ discover resolve ident@(Identifier i) = do
|
|||||||
|
|
||||||
-- | Attempt a YADIS based discovery, given a valid identifier. The result is
|
-- | Attempt a YADIS based discovery, given a valid identifier. The result is
|
||||||
-- an OpenID endpoint, and the actual identifier for the user.
|
-- an OpenID endpoint, and the actual identifier for the user.
|
||||||
discoverYADIS :: Resolver IO
|
discoverYADIS :: Identifier
|
||||||
-> Identifier
|
|
||||||
-> Maybe String
|
-> Maybe String
|
||||||
-> IO (Maybe (Provider,Identifier))
|
-> IO (Maybe (Provider,Identifier))
|
||||||
discoverYADIS resolve ident mb_loc = do
|
discoverYADIS ident mb_loc = do
|
||||||
let uri = fromMaybe (getIdentifier ident) mb_loc
|
let uri = fromMaybe (getIdentifier ident) mb_loc
|
||||||
req <- parseUrl uri
|
req <- parseUrl uri
|
||||||
res <- httpLbs req
|
res <- httpLbs req
|
||||||
@ -65,7 +63,7 @@ discoverYADIS resolve ident mb_loc = do
|
|||||||
case statusCode res of
|
case statusCode res of
|
||||||
200 ->
|
200 ->
|
||||||
case mloc of
|
case mloc of
|
||||||
Just loc -> discoverYADIS resolve ident (Just $ S8.unpack loc)
|
Just loc -> discoverYADIS ident (Just $ S8.unpack loc)
|
||||||
Nothing -> do
|
Nothing -> do
|
||||||
let mdoc = parseXRDS $ BSLU.toString $ responseBody res
|
let mdoc = parseXRDS $ BSLU.toString $ responseBody res
|
||||||
case mdoc of
|
case mdoc of
|
||||||
@ -91,16 +89,16 @@ parseYADIS ident = listToMaybe . mapMaybe isOpenId . concat
|
|||||||
, ("http://openid.net/signon/1.0" , localId)
|
, ("http://openid.net/signon/1.0" , localId)
|
||||||
, ("http://openid.net/signon/1.1" , localId)
|
, ("http://openid.net/signon/1.1" , localId)
|
||||||
]
|
]
|
||||||
uri <- parseProvider =<< listToMaybe (serviceURIs svc)
|
uri <- listToMaybe $ serviceURIs svc
|
||||||
return (uri,lid)
|
return (Provider uri, lid)
|
||||||
|
|
||||||
|
|
||||||
-- HTML-Based Discovery --------------------------------------------------------
|
-- HTML-Based Discovery --------------------------------------------------------
|
||||||
|
|
||||||
-- | Attempt to discover an OpenID endpoint, from an HTML document. The result
|
-- | Attempt to discover an OpenID endpoint, from an HTML document. The result
|
||||||
-- will be an endpoint on success, and the actual identifier of the user.
|
-- will be an endpoint on success, and the actual identifier of the user.
|
||||||
discoverHTML :: Resolver IO -> Identifier -> IO (Maybe (Provider,Identifier))
|
discoverHTML :: Identifier -> IO (Maybe (Provider,Identifier))
|
||||||
discoverHTML resolve ident'@(Identifier ident) =
|
discoverHTML ident'@(Identifier ident) =
|
||||||
parseHTML ident' . BSLU.toString <$> simpleHttp ident
|
parseHTML ident' . BSLU.toString <$> simpleHttp ident
|
||||||
|
|
||||||
-- | Parse out an OpenID endpoint and an actual identifier from an HTML
|
-- | Parse out an OpenID endpoint and an actual identifier from an HTML
|
||||||
@ -113,9 +111,9 @@ parseHTML ident = resolve
|
|||||||
where
|
where
|
||||||
isOpenId (rel,_) = "openid" `isPrefixOf` rel
|
isOpenId (rel,_) = "openid" `isPrefixOf` rel
|
||||||
resolve ls = do
|
resolve ls = do
|
||||||
prov <- parseProvider =<< lookup "openid2.provider" ls
|
prov <- lookup "openid2.provider" ls
|
||||||
let lid = maybe ident Identifier $ lookup "openid2.local_id" ls
|
let lid = maybe ident Identifier $ lookup "openid2.local_id" ls
|
||||||
return (prov,lid)
|
return (Provider prov,lid)
|
||||||
|
|
||||||
|
|
||||||
-- | Filter out link tags from a list of html tags.
|
-- | Filter out link tags from a list of html tags.
|
||||||
|
|||||||
@ -1,94 +0,0 @@
|
|||||||
|
|
||||||
--------------------------------------------------------------------------------
|
|
||||||
-- |
|
|
||||||
-- Module : Network.OpenID.HTTP
|
|
||||||
-- Copyright : (c) Trevor Elliott, 2008
|
|
||||||
-- License : BSD3
|
|
||||||
--
|
|
||||||
-- Maintainer : Trevor Elliott <trevor@geekgateway.com>
|
|
||||||
-- Stability :
|
|
||||||
-- Portability :
|
|
||||||
--
|
|
||||||
|
|
||||||
module OpenId2.HTTP (
|
|
||||||
-- * Request Interface
|
|
||||||
makeRequest
|
|
||||||
|
|
||||||
-- * Request/Response Parsing and Formatting
|
|
||||||
, parseDirectResponse
|
|
||||||
, formatParams
|
|
||||||
, formatDirectParams
|
|
||||||
, escapeParam
|
|
||||||
, addParams
|
|
||||||
, parseParams
|
|
||||||
) where
|
|
||||||
|
|
||||||
-- friends
|
|
||||||
import OpenId2.Types
|
|
||||||
--import Network.OpenID.Utils
|
|
||||||
|
|
||||||
-- libraries
|
|
||||||
import Data.List
|
|
||||||
import Network.BSD
|
|
||||||
import Network.Socket
|
|
||||||
import Network.URI hiding (query)
|
|
||||||
import Network.HTTP.Enumerator
|
|
||||||
|
|
||||||
|
|
||||||
-- | Perform an http request.
|
|
||||||
-- If the Bool parameter is set to True, redirects from the server will be
|
|
||||||
-- followed.
|
|
||||||
makeRequest :: Bool -> Resolver IO
|
|
||||||
makeRequest follow = if follow then httpLbsRedirect else httpLbs
|
|
||||||
|
|
||||||
-- Parsing and Formatting ------------------------------------------------------
|
|
||||||
|
|
||||||
-- | Turn a response body into a list of parameters.
|
|
||||||
parseDirectResponse :: String -> Params
|
|
||||||
parseDirectResponse = unfoldr step
|
|
||||||
where
|
|
||||||
step [] = Nothing
|
|
||||||
step str = case split (== '\n') str of
|
|
||||||
(ps,rest) -> Just (split (== ':') ps,rest)
|
|
||||||
|
|
||||||
|
|
||||||
-- | Format OpenID parameters as a query string
|
|
||||||
formatParams :: Params -> String
|
|
||||||
formatParams = intercalate "&" . map f
|
|
||||||
where f (x,y) = x ++ "=" ++ escapeParam y
|
|
||||||
|
|
||||||
|
|
||||||
-- | Format OpenID parameters as a direct response
|
|
||||||
formatDirectParams :: Params -> String
|
|
||||||
formatDirectParams = concatMap f
|
|
||||||
where f (x,y) = x ++ ":" ++ y ++ "\n"
|
|
||||||
|
|
||||||
|
|
||||||
-- | Escape for the query string of a URI
|
|
||||||
escapeParam :: String -> String
|
|
||||||
escapeParam = escapeURIString isUnreserved
|
|
||||||
|
|
||||||
|
|
||||||
-- | Add Parameters to a URI
|
|
||||||
addParams :: Params -> URI -> URI
|
|
||||||
addParams ps uri = uri { uriQuery = query }
|
|
||||||
where
|
|
||||||
f (k,v) = (k,v)
|
|
||||||
ps' = map f ps
|
|
||||||
query = '?' : formatParams (parseParams (uriQuery uri) ++ ps')
|
|
||||||
|
|
||||||
|
|
||||||
-- | Parse OpenID parameters out of a url string
|
|
||||||
parseParams :: String -> Params
|
|
||||||
parseParams xs = case split (== '?') xs of
|
|
||||||
(_,bs) -> unfoldr step bs
|
|
||||||
where
|
|
||||||
step [] = Nothing
|
|
||||||
step bs = case split (== '&') bs of
|
|
||||||
(as,rest) -> case split (== '=') as of
|
|
||||||
(k,v) -> Just ((k, unEscapeString v),rest)
|
|
||||||
|
|
||||||
split :: (a -> Bool) -> [a] -> ([a],[a])
|
|
||||||
split p as = case break p as of
|
|
||||||
(xs,_:ys) -> (xs,ys)
|
|
||||||
pair -> pair
|
|
||||||
@ -21,8 +21,8 @@ import OpenId2.Types
|
|||||||
import Control.Applicative
|
import Control.Applicative
|
||||||
import Control.Monad
|
import Control.Monad
|
||||||
import Data.List
|
import Data.List
|
||||||
import Network.URI hiding (scheme,path)
|
|
||||||
import Control.Failure (Failure (..))
|
import Control.Failure (Failure (..))
|
||||||
|
import Network.URI
|
||||||
|
|
||||||
normalize :: Failure OpenIdException m => String -> m Identifier
|
normalize :: Failure OpenIdException m => String -> m Identifier
|
||||||
normalize ident =
|
normalize ident =
|
||||||
@ -49,11 +49,11 @@ normalizeIdentifier' xri (Identifier str)
|
|||||||
|
|
||||||
norm uri = validScheme >> return u
|
norm uri = validScheme >> return u
|
||||||
where
|
where
|
||||||
scheme = uriScheme uri
|
scheme' = uriScheme uri
|
||||||
validScheme = guard (scheme == "http:" || scheme == "https:")
|
validScheme = guard (scheme' == "http:" || scheme' == "https:")
|
||||||
u = uri { uriFragment = "", uriPath = path }
|
u = uri { uriFragment = "", uriPath = path' }
|
||||||
path | null (uriPath uri) = "/"
|
path' | null (uriPath uri) = "/"
|
||||||
| otherwise = uriPath uri
|
| otherwise = uriPath uri
|
||||||
|
|
||||||
fmt u = Identifier
|
fmt u = Identifier
|
||||||
$ normalizePathSegments
|
$ normalizePathSegments
|
||||||
|
|||||||
@ -11,28 +11,12 @@
|
|||||||
--
|
--
|
||||||
|
|
||||||
module OpenId2.Types (
|
module OpenId2.Types (
|
||||||
AssocType(..)
|
Provider (..)
|
||||||
, SessionType(..)
|
, Identifier (..)
|
||||||
, Association(..)
|
|
||||||
, Params
|
|
||||||
, ReturnTo
|
|
||||||
, Realm
|
|
||||||
, Resolver
|
|
||||||
, Provider (..)
|
|
||||||
, parseProvider
|
|
||||||
, showProvider
|
|
||||||
, modifyProvider
|
|
||||||
, Identifier(..)
|
|
||||||
, Error(..)
|
|
||||||
, assocString
|
|
||||||
, OpenIdException (..)
|
, OpenIdException (..)
|
||||||
) where
|
) where
|
||||||
|
|
||||||
-- Libraries
|
-- Libraries
|
||||||
import Data.List
|
|
||||||
import Data.Word
|
|
||||||
import Network.URI
|
|
||||||
import Network.HTTP.Enumerator (Request, Response)
|
|
||||||
import Control.Exception (Exception)
|
import Control.Exception (Exception)
|
||||||
import Data.Typeable (Typeable)
|
import Data.Typeable (Typeable)
|
||||||
|
|
||||||
@ -43,83 +27,9 @@ data OpenIdException =
|
|||||||
deriving (Show, Typeable)
|
deriving (Show, Typeable)
|
||||||
instance Exception OpenIdException
|
instance Exception OpenIdException
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
|
||||||
-- Types
|
|
||||||
|
|
||||||
-- | Supported association types
|
|
||||||
data AssocType = HmacSha1 | HmacSha256
|
|
||||||
deriving (Read,Show)
|
|
||||||
|
|
||||||
assocString :: AssocType -> String
|
|
||||||
assocString HmacSha1 = "HMAC-SHA1"
|
|
||||||
assocString HmacSha256 = "HMAC-SHA256"
|
|
||||||
|
|
||||||
{-
|
|
||||||
instance Show AssocType where
|
|
||||||
show HmacSha1 = "HMAC-SHA1"
|
|
||||||
show HmacSha256 = "HMAC-SHA256"
|
|
||||||
|
|
||||||
instance Read AssocType where
|
|
||||||
readsPrec _ str | "HMAC-SHA1" `isPrefixOf` str = [(HmacSha1 ,drop 9 str)]
|
|
||||||
| "HMAC-SHA256" `isPrefixOf` str = [(HmacSha256, drop 11 str)]
|
|
||||||
| otherwise = []
|
|
||||||
-}
|
|
||||||
|
|
||||||
-- | Session types for association establishment
|
|
||||||
data SessionType = NoEncryption | DhSha1 | DhSha256
|
|
||||||
|
|
||||||
instance Show SessionType where
|
|
||||||
show NoEncryption = "no-encryption"
|
|
||||||
show DhSha1 = "DH-SHA1"
|
|
||||||
show DhSha256 = "DH-SHA256"
|
|
||||||
|
|
||||||
instance Read SessionType where
|
|
||||||
readsPrec _ str
|
|
||||||
| "no-encryption" `isPrefixOf` str = [(NoEncryption, drop 13 str)]
|
|
||||||
| "DH-SHA1" `isPrefixOf` str = [(DhSha1, drop 7 str)]
|
|
||||||
| "DH-SHA256" `isPrefixOf` str = [(DhSha256, drop 9 str)]
|
|
||||||
| otherwise = []
|
|
||||||
|
|
||||||
|
|
||||||
-- | An association with a provider.
|
|
||||||
data Association = Association
|
|
||||||
{ assocExpiresIn :: Int
|
|
||||||
, assocHandle :: String
|
|
||||||
, assocMacKey :: [Word8]
|
|
||||||
, assocType :: AssocType
|
|
||||||
} deriving (Show,Read)
|
|
||||||
|
|
||||||
|
|
||||||
-- | Parameter lists for communication with the server
|
|
||||||
type Params = [(String,String)]
|
|
||||||
|
|
||||||
-- | A return to path
|
|
||||||
type ReturnTo = String
|
|
||||||
|
|
||||||
-- | A realm of uris for a provider to inform a user about
|
|
||||||
type Realm = String
|
|
||||||
|
|
||||||
-- | A way to resolve an HTTP request
|
|
||||||
type Resolver m = Request -> m Response
|
|
||||||
|
|
||||||
-- | An OpenID provider.
|
-- | An OpenID provider.
|
||||||
newtype Provider = Provider { providerURI :: URI } deriving (Eq,Show)
|
newtype Provider = Provider { providerURI :: String } deriving (Eq,Show)
|
||||||
|
|
||||||
-- | Parse a provider
|
|
||||||
parseProvider :: String -> Maybe Provider
|
|
||||||
parseProvider = fmap Provider . parseURI
|
|
||||||
|
|
||||||
-- | Show a provider
|
|
||||||
showProvider :: Provider -> String
|
|
||||||
showProvider (Provider uri) = uriToString (const "") uri []
|
|
||||||
|
|
||||||
-- | Modify the URI in a provider
|
|
||||||
modifyProvider :: (URI -> URI) -> Provider -> Provider
|
|
||||||
modifyProvider f (Provider uri) = Provider (f uri)
|
|
||||||
|
|
||||||
-- | A valid OpenID identifier.
|
-- | A valid OpenID identifier.
|
||||||
newtype Identifier = Identifier { getIdentifier :: String }
|
newtype Identifier = Identifier { getIdentifier :: String }
|
||||||
deriving (Eq,Show,Read)
|
deriving (Eq,Show,Read)
|
||||||
|
|
||||||
-- | Errors
|
|
||||||
newtype Error = Error String deriving Show
|
|
||||||
|
|||||||
@ -12,13 +12,9 @@
|
|||||||
|
|
||||||
module OpenId2.XRDS (
|
module OpenId2.XRDS (
|
||||||
-- * Types
|
-- * Types
|
||||||
XRDS, XRD
|
XRDS
|
||||||
, Service(..)
|
, Service(..)
|
||||||
|
|
||||||
-- * Utility Functions
|
|
||||||
, isUsable
|
|
||||||
, hasType
|
|
||||||
|
|
||||||
-- * Parsing
|
-- * Parsing
|
||||||
, parseXRDS
|
, parseXRDS
|
||||||
) where
|
) where
|
||||||
@ -48,11 +44,6 @@ data Service = Service
|
|||||||
|
|
||||||
-- Utilities -------------------------------------------------------------------
|
-- Utilities -------------------------------------------------------------------
|
||||||
|
|
||||||
-- | Check to see if an XRDS service description is usable.
|
|
||||||
isUsable :: XRDS -> Bool
|
|
||||||
isUsable = not . null . concat
|
|
||||||
|
|
||||||
|
|
||||||
-- | Generate a tag name predicate, that ignores prefix and namespace.
|
-- | Generate a tag name predicate, that ignores prefix and namespace.
|
||||||
tag :: String -> Element -> Bool
|
tag :: String -> Element -> Bool
|
||||||
tag n el = qName (elName el) == n
|
tag n el = qName (elName el) == n
|
||||||
@ -76,12 +67,6 @@ getText el = case elContent el of
|
|||||||
[Text cd] -> cdData cd
|
[Text cd] -> cdData cd
|
||||||
_ -> []
|
_ -> []
|
||||||
|
|
||||||
|
|
||||||
-- | Generate a predicate over Service Types.
|
|
||||||
hasType :: String -> Service -> Bool
|
|
||||||
hasType ty svc = ty `elem` serviceTypes svc
|
|
||||||
|
|
||||||
|
|
||||||
-- Parsing ---------------------------------------------------------------------
|
-- Parsing ---------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -8,7 +8,6 @@ module Web.Authenticate.OpenId2
|
|||||||
import Control.Monad.IO.Class
|
import Control.Monad.IO.Class
|
||||||
import OpenId2.Normalization (normalize)
|
import OpenId2.Normalization (normalize)
|
||||||
import OpenId2.Discovery (discover)
|
import OpenId2.Discovery (discover)
|
||||||
import OpenId2.HTTP (makeRequest, parseDirectResponse)
|
|
||||||
import Control.Failure (Failure (failure))
|
import Control.Failure (Failure (failure))
|
||||||
import OpenId2.Types (OpenIdException (..), Identifier (Identifier),
|
import OpenId2.Types (OpenIdException (..), Identifier (Identifier),
|
||||||
Provider (Provider))
|
Provider (Provider))
|
||||||
@ -16,17 +15,18 @@ import Web.Authenticate.Internal (qsUrl)
|
|||||||
import Control.Monad (unless)
|
import Control.Monad (unless)
|
||||||
import qualified Data.ByteString.UTF8 as BSU
|
import qualified Data.ByteString.UTF8 as BSU
|
||||||
import qualified Data.ByteString.Lazy.UTF8 as BSLU
|
import qualified Data.ByteString.Lazy.UTF8 as BSLU
|
||||||
import Network.HTTP.Enumerator (parseUrl, urlEncodedBody, responseBody)
|
import Network.HTTP.Enumerator
|
||||||
|
(parseUrl, urlEncodedBody, responseBody, httpLbsRedirect)
|
||||||
import Control.Arrow ((***))
|
import Control.Arrow ((***))
|
||||||
|
import Data.List (unfoldr)
|
||||||
|
|
||||||
getForwardUrl :: (MonadIO m, Failure OpenIdException m)
|
getForwardUrl :: (MonadIO m, Failure OpenIdException 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
|
||||||
let resolve = makeRequest True
|
(Provider p, Identifier i) <- normalize openid' >>= discover
|
||||||
(Provider p, Identifier i) <- normalize openid' >>= discover resolve
|
return $ qsUrl p
|
||||||
return $ qsUrl (show p)
|
|
||||||
[ ("openid.ns", "http://specs.openid.net/auth/2.0")
|
[ ("openid.ns", "http://specs.openid.net/auth/2.0")
|
||||||
, ("openid.mode", "checkid_setup")
|
, ("openid.mode", "checkid_setup")
|
||||||
, ("openid.claimed_id", i)
|
, ("openid.claimed_id", i)
|
||||||
@ -49,15 +49,29 @@ authenticate params = do
|
|||||||
Just e -> return e
|
Just e -> return e
|
||||||
Nothing ->
|
Nothing ->
|
||||||
failure $ AuthenticationException "Missing op_endpoint"
|
failure $ AuthenticationException "Missing op_endpoint"
|
||||||
|
(Provider p, Identifier i) <- normalize ident >>= discover
|
||||||
|
unless (endpoint == p) $
|
||||||
|
failure $ AuthenticationException "endpoint does not match discovery"
|
||||||
let params' = map (BSU.fromString *** BSU.fromString)
|
let params' = map (BSU.fromString *** BSU.fromString)
|
||||||
$ ("openid.mode", "check_authentication")
|
$ ("openid.mode", "check_authentication")
|
||||||
: filter (\(k, _) -> k /= "openid.mode") params
|
: filter (\(k, _) -> k /= "openid.mode") params
|
||||||
req' <- liftIO $ parseUrl endpoint
|
req' <- liftIO $ parseUrl endpoint
|
||||||
let req = urlEncodedBody params' req'
|
let req = urlEncodedBody params' req'
|
||||||
rsp <- liftIO $ makeRequest True req
|
rsp <- liftIO $ httpLbsRedirect req
|
||||||
let rps = parseDirectResponse $ BSLU.toString $ responseBody rsp
|
let rps = parseDirectResponse $ BSLU.toString $ responseBody rsp
|
||||||
case lookup "is_valid" rps of
|
case lookup "is_valid" rps of
|
||||||
Just "true" -> return ident
|
Just "true" -> return ident
|
||||||
Nothing ->
|
_ -> failure $ AuthenticationException "OpenID provider did not validate"
|
||||||
failure $ AuthenticationException "OpenID provider did not validate"
|
|
||||||
-- FIXME check if endpoint is valid for given identity
|
-- | Turn a response body into a list of parameters.
|
||||||
|
parseDirectResponse :: String -> [(String, String)]
|
||||||
|
parseDirectResponse = unfoldr step
|
||||||
|
where
|
||||||
|
step [] = Nothing
|
||||||
|
step str = case split (== '\n') str of
|
||||||
|
(ps,rest) -> Just (split (== ':') ps,rest)
|
||||||
|
|
||||||
|
split :: (a -> Bool) -> [a] -> ([a],[a])
|
||||||
|
split p as = case break p as of
|
||||||
|
(xs,_:ys) -> (xs,ys)
|
||||||
|
pair -> pair
|
||||||
|
|||||||
@ -31,7 +31,6 @@ library
|
|||||||
Web.Authenticate.Facebook
|
Web.Authenticate.Facebook
|
||||||
other-modules: Web.Authenticate.Internal,
|
other-modules: Web.Authenticate.Internal,
|
||||||
OpenId2.Discovery,
|
OpenId2.Discovery,
|
||||||
OpenId2.HTTP,
|
|
||||||
OpenId2.Normalization,
|
OpenId2.Normalization,
|
||||||
OpenId2.Types,
|
OpenId2.Types,
|
||||||
OpenId2.XRDS
|
OpenId2.XRDS
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user