yesod-auth-oauth2 (empty) → 0.0.1
raw patch · 6 files changed
+250/−0 lines, 6 filesdep +aesondep +basedep +bytestringsetup-changed
Dependencies added: aeson, base, bytestring, hoauth2, http-conduit, http-types, text, transformers, yesod-auth, yesod-core, yesod-form
Files
- LICENSE +25/−0
- Setup.lhs +7/−0
- Yesod/Auth/OAuth2.hs +69/−0
- Yesod/Auth/OAuth2/Google.hs +30/−0
- Yesod/Auth/OAuth2/Learn.hs +76/−0
- yesod-auth-oauth2.cabal +43/−0
+ LICENSE view
@@ -0,0 +1,25 @@+The following license covers this documentation, and the source code, except+where otherwise indicated.++Copyright 2008, Michael Snoyman. All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are met:++* Redistributions of source code must retain the above copyright notice, this+ list of conditions and the following disclaimer.++* Redistributions in binary form must reproduce the above copyright notice,+ this list of conditions and the following disclaimer in the documentation+ and/or other materials provided with the distribution.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS "AS IS" AND ANY EXPRESS OR+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO+EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT,+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,+OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ Setup.lhs view
@@ -0,0 +1,7 @@+#!/usr/bin/env runhaskell++> module Main where+> import Distribution.Simple++> main :: IO ()+> main = defaultMain
+ Yesod/Auth/OAuth2.hs view
@@ -0,0 +1,69 @@+{-# LANGUAGE OverloadedStrings, QuasiQuotes #-}+-- |+--+-- Generic OAuth2 plugin for Yesod+--+-- * See Yesod.Auth.OAuth2.Learn for example usage.+--+module Yesod.Auth.OAuth2+ ( authOAuth2+ , oauth2Url+ , module Network.OAuth.OAuth2+ ) where++import Control.Monad.IO.Class+import Data.ByteString (ByteString)+import Data.Text (Text)+import Data.Text.Encoding (decodeUtf8With, encodeUtf8)+import Data.Text.Encoding.Error (lenientDecode)+import Network.OAuth.OAuth2+import Yesod.Auth+import Yesod.Core+import Yesod.Form++oauth2Url :: Text -> AuthRoute+oauth2Url name = PluginR name ["forward"]++authOAuth2 :: YesodAuth m+ => Text -- ^ Service name+ -> OAuth2 -- ^ Service details++ -- | This function defines how to take an @'AccessToken'@ and+ -- retrieve additional information about the user, to be+ -- set in the session as @'Creds'@. Usually this means a+ -- second authorized request to @api/me.json@.+ -> (AccessToken -> IO (Creds m))+ -> AuthPlugin m+authOAuth2 name oauth getCreds = AuthPlugin name dispatch login++ where+ url = PluginR name ["callback"]++ withCallback = do+ tm <- getRouteToParent+ render <- lift $ getUrlRender+ return $ oauth { oauthCallback = Just $ encodeUtf8 $ render $ tm url }++ dispatch "GET" ["forward"] = do+ authUrl <- fmap (bsToText . authorizationUrl) withCallback+ lift $ redirect authUrl++ dispatch "GET" ["callback"] = do+ code <- lift $ runInputGet $ ireq textField "code"+ oauth' <- withCallback+ result <- liftIO $ fetchAccessToken oauth' (encodeUtf8 code)+ case result of+ Left _ -> permissionDenied "Unable to retreive OAuth2 token"+ Right token -> do+ creds <- liftIO $ getCreds token+ lift $ setCreds True creds++ dispatch _ _ = notFound++ login tm = do+ render <- getUrlRender+ let oaUrl = render $ tm $ oauth2Url name+ [whamlet| <a href=#{oaUrl}>Login via #{name} |]++bsToText :: ByteString -> Text+bsToText = decodeUtf8With lenientDecode
+ Yesod/Auth/OAuth2/Google.hs view
@@ -0,0 +1,30 @@+{-# LANGUAGE OverloadedStrings #-}+-- |+--+-- OAuth2 plugin for http://google.com+--+-- * Note: this module is unfinished, do not use.+--+module Yesod.Auth.OAuth2.Google+ ( oauth2Google+ , module Yesod.Auth.OAuth2+ ) where++import Data.Text (Text)+import Data.Text.Encoding (encodeUtf8)+import Yesod.Auth+import Yesod.Auth.OAuth2++oauth2Google :: YesodAuth m+ => Text -- ^ Client ID+ -> Text -- ^ Client Secret+ -> AuthPlugin m+oauth2Google clientId clientSecret = authOAuth2 "google"+ (OAuth2+ { oauthClientId = encodeUtf8 clientId+ , oauthClientSecret = encodeUtf8 clientSecret+ , oauthOAuthorizeEndpoint = "https://accounts.google.com/o/oauth2/auth"+ , oauthAccessTokenEndpoint = "https://accounts.google.com/o/oauth2/token"+ , oauthCallback = Nothing+ })+ undefined -- TODO
+ Yesod/Auth/OAuth2/Learn.hs view
@@ -0,0 +1,76 @@+{-# LANGUAGE OverloadedStrings #-}+-- |+--+-- OAuth2 plugin for http://learn.thoughtbot.com+--+-- * Authenticates against learn+-- * Uses learn user id as credentials identifier+-- * Returns first_name, last_name, and email as extras+--+module Yesod.Auth.OAuth2.Learn+ ( oauth2Learn+ , module Yesod.Auth.OAuth2+ ) where++import Control.Applicative ((<$>), (<*>))+import Control.Monad (mzero)+import Data.Aeson+import Data.Text (Text)+import Data.Text.Encoding (encodeUtf8)+import Yesod.Auth+import Yesod.Auth.OAuth2+import qualified Data.Text as T++data LearnUser = LearnUser+ { learnUserId :: Int+ , learnUserFirstName :: Text+ , learnUserLastName :: Text+ , learnUserEmail :: Text+ }++instance FromJSON LearnUser where+ parseJSON (Object o) =+ LearnUser <$> o .: "id"+ <*> o .: "first_name"+ <*> o .: "last_name"+ <*> o .: "email"++ parseJSON _ = mzero++data LearnResponse = LearnResponse LearnUser++instance FromJSON LearnResponse where+ parseJSON (Object o) =+ LearnResponse <$> o .: "user"++ parseJSON _ = mzero++oauth2Learn :: YesodAuth m+ => Text -- ^ Client ID+ -> Text -- ^ Client Secret+ -> AuthPlugin m+oauth2Learn clientId clientSecret = authOAuth2 "learn"+ (OAuth2+ { oauthClientId = encodeUtf8 clientId+ , oauthClientSecret = encodeUtf8 clientSecret+ , oauthOAuthorizeEndpoint = "http://learn.thoughtbot.com/oauth/authorize"+ , oauthAccessTokenEndpoint = "http://learn.thoughtbot.com/oauth/token"+ , oauthCallback = Nothing+ })+ fetchLearnProfile++fetchLearnProfile :: AccessToken -> IO (Creds m)+fetchLearnProfile token = do+ result <- authGetJSON token "http://learn.thoughtbot.com/api/v1/me.json"++ case result of+ Right (LearnResponse user) -> return $ toCreds user+ _ -> error "Invalid response for learn profile data"++toCreds :: LearnUser -> Creds m+toCreds user = Creds "learn"+ (T.pack $ show $ learnUserId user)+ [ ("first_name", learnUserFirstName user)+ , ("last_name" , learnUserLastName user)+ , ("email" , learnUserEmail user)+ ]
+ yesod-auth-oauth2.cabal view
@@ -0,0 +1,43 @@+name: yesod-auth-oauth2+version: 0.0.1+license: BSD3+license-file: LICENSE+author: Tom Streller+maintainer: Tom Streller+synopsis: Library to authenticate with OAuth 2.0 for Yesod web applications.+description: OAuth 2.0 authentication+category: Web+stability: Experimental+cabal-version: >= 1.6+build-type: Simple+homepage: http://github.com/scan/yesod-auth-oauth2++flag ghc7++library+ if flag(ghc7)+ build-depends: base >= 4.3 && < 5+ cpp-options: -DGHC7+ else+ build-depends: base >= 4 && < 4.3++ build-depends: bytestring >= 0.9.1.4+ , http-conduit >= 2.0 && < 3.0+ , http-types >= 0.8 && < 0.9+ , aeson >= 0.6 && < 0.8+ , yesod-core >= 1.2 && < 1.3+ , yesod-auth >= 1.2 && < 1.3+ , text >= 0.7 && < 0.12+ , yesod-form >= 1.3 && < 1.4+ , transformers >= 0.2.2 && < 0.4+ , hoauth2 >= 0.3.6 && < 0.4++ exposed-modules: Yesod.Auth.OAuth2+ Yesod.Auth.OAuth2.Google+ Yesod.Auth.OAuth2.Learn++ ghc-options: -Wall++source-repository head+ type: git+ location: git://github.com/scan/authenticate-oauth2.git