packages feed

yesod-auth-oauth2 0.1.1 → 0.1.2

raw patch · 2 files changed

+144/−1 lines, 2 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

+ Yesod.Auth.OAuth2.Google: emailUid :: GoogleUser -> AccessToken -> Creds m
+ Yesod.Auth.OAuth2.Google: googleUid :: GoogleUser -> AccessToken -> Creds m
+ Yesod.Auth.OAuth2.Google: instance FromJSON GoogleUser
+ Yesod.Auth.OAuth2.Google: oauth2Google :: YesodAuth m => Text -> Text -> AuthPlugin m
+ Yesod.Auth.OAuth2.Google: oauth2GoogleScoped :: YesodAuth m => [Text] -> Text -> Text -> AuthPlugin m
+ Yesod.Auth.OAuth2.Google: oauth2GoogleScopedWithCustomId :: YesodAuth m => (GoogleUser -> AccessToken -> Creds m) -> [Text] -> Text -> Text -> AuthPlugin m

Files

+ Yesod/Auth/OAuth2/Google.hs view
@@ -0,0 +1,142 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE OverloadedStrings #-}+-- |+--+-- OAuth2 plugin for http://www.google.com+--+-- * Authenticates against Google+-- * Uses Google user id or email as credentials identifier+-- * Returns given_name, family_name, email, and avatar_url as extras+--+-- Note: This may eventually replace Yesod.Auth.GoogleEmail2. Currently it+-- provides the same functionality except that GoogleEmail2 returns more profile+-- information.+--+module Yesod.Auth.OAuth2.Google+    ( oauth2Google+    , oauth2GoogleScoped+    , oauth2GoogleScopedWithCustomId+    , googleUid+    , emailUid+    , module Yesod.Auth.OAuth2+    ) where++#if __GLASGOW_HASKELL__ < 710+import Control.Applicative ((<$>), (<*>))+#endif++import Control.Exception.Lifted+import Control.Monad (mzero)+import Data.Aeson+import Data.Monoid ((<>))+import Data.Maybe (maybeToList)+import Data.Text (Text)+import Data.Text.Encoding (encodeUtf8, decodeUtf8)+import Network.HTTP.Conduit (Manager)+import Yesod.Auth+import Yesod.Auth.OAuth2++import qualified Data.Text as T++-- | Auth with Google+--+-- Requests @openid@ and @email@ scopes and uses email as the @'Creds'@+-- identifier.+--+oauth2Google :: YesodAuth m+             => Text -- ^ Client ID+             -> Text -- ^ Client Secret+             -> AuthPlugin m+oauth2Google = oauth2GoogleScoped ["openid", "email"]++-- | Auth with Google+--+-- Requests custom scopes and uses email as the @'Creds'@ identifier.+--+oauth2GoogleScoped :: YesodAuth m+                   => [Text] -- ^ List of scopes to request+                   -> Text -- ^ Client ID+                   -> Text -- ^ Client Secret+                   -> AuthPlugin m+oauth2GoogleScoped = oauth2GoogleScopedWithCustomId emailUid++-- | Auth with Google+--+-- Requests custom scopes and uses the given function to create credentials+-- which allows for using any attribute as the identifier.+--+-- See @'emailUid'@ and @'googleUid'@.+--+oauth2GoogleScopedWithCustomId :: YesodAuth m+                               => (GoogleUser -> AccessToken -> Creds m)+                               -- ^ A function to generate the credentials+                               -> [Text] -- ^ List of scopes to request+                               -> Text -- ^ Client ID+                               -> Text -- ^ Client secret+                               -> AuthPlugin m+oauth2GoogleScopedWithCustomId toCreds scopes clientId clientSecret =+    authOAuth2 "google" oauth $ fetchGoogleProfile toCreds++  where+    oauth = OAuth2+        { oauthClientId = encodeUtf8 clientId+        , oauthClientSecret = encodeUtf8 clientSecret+        , oauthOAuthorizeEndpoint = encodeUtf8+            $ "https://accounts.google.com/o/oauth2/auth?scope=" <> T.intercalate "+" scopes+        , oauthAccessTokenEndpoint = "https://www.googleapis.com/oauth2/v3/token"+        , oauthCallback = Nothing+        }++fetchGoogleProfile :: (GoogleUser -> AccessToken -> Creds m) -> Manager -> AccessToken -> IO (Creds m)+fetchGoogleProfile toCreds manager token = do+    userInfo <- authGetJSON manager token "https://www.googleapis.com/oauth2/v3/userinfo"+    case userInfo of+      Right user -> return $ toCreds user token+      Left err -> throwIO $ InvalidProfileResponse "google" err++data GoogleUser = GoogleUser+    { googleUserId :: Text+    , googleUserName :: Text+    , googleUserEmail :: Text+    , googleUserPicture :: Text+    , googleUserGivenName :: Text+    , googleUserFamilyName :: Text+    , googleUserHostedDomain :: Maybe Text+    }++instance FromJSON GoogleUser where+    parseJSON (Object o) = GoogleUser+        <$> o .: "sub"+        <*> o .: "name"+        <*> o .: "email"+        <*> o .: "picture"+        <*> o .: "given_name"+        <*> o .: "family_name"+        <*> o .:? "hd"++    parseJSON _ = mzero++-- | Build a @'Creds'@ using the user's google-uid as the identifier+googleUid :: GoogleUser -> AccessToken -> Creds m+googleUid = uidBuilder $ ("google-uid:" <>) . googleUserId++-- | Build a @'Creds'@ using the user's email as the identifier+emailUid :: GoogleUser -> AccessToken -> Creds m+emailUid = uidBuilder googleUserEmail++uidBuilder :: (GoogleUser -> Text) -> GoogleUser -> AccessToken -> Creds m+uidBuilder f user token = Creds+    { credsPlugin = "google"+    , credsIdent = f user+    , credsExtra =+        [ ("email", googleUserEmail user)+        , ("name", googleUserName user)+        , ("given_name", googleUserGivenName user)+        , ("family_name", googleUserFamilyName user)+        , ("avatar_url", googleUserPicture user)+        , ("access_token", decodeUtf8 $ accessToken token)+        ] ++ maybeHostedDomain+    }++  where+    maybeHostedDomain = maybeToList $ (,) "hosted_domain" <$> googleUserHostedDomain user
yesod-auth-oauth2.cabal view
@@ -1,5 +1,5 @@ name:            yesod-auth-oauth2-version:         0.1.1+version:         0.1.2 license:         BSD3 license-file:    LICENSE author:          Tom Streller@@ -39,6 +39,7 @@      exposed-modules: Yesod.Auth.OAuth2                      Yesod.Auth.OAuth2.Github+                     Yesod.Auth.OAuth2.Google                      Yesod.Auth.OAuth2.Spotify                      Yesod.Auth.OAuth2.Twitter                      Yesod.Auth.OAuth2.Upcase