hoauth2-0.3.0: example/Google/test.hs
{-# LANGUAGE OverloadedStrings, TemplateHaskell #-}
{-
This is basically very manual test. Check following link for details.
Google web oauth: https://developers.google.com/accounts/docs/OAuth2WebServer
Google OAuth 2.0 playround: https://developers.google.com/oauthplayground/
-}
module Main where
import Network.OAuth.OAuth2.HttpClient
import Network.OAuth.OAuth2
import Keys (googleKey)
import Control.Applicative ((<$>), (<*>))
import Control.Monad (mzero)
import Data.Aeson (FromJSON, Value(Object), parseJSON, (.:), (.:?))
import Data.Aeson.TH (deriveJSON)
import qualified Data.ByteString.Char8 as BS
import qualified Data.ByteString.Lazy.Internal as BL
import Data.Text (Text)
import Prelude hiding (id)
import qualified Prelude as P (id)
import System.Environment (getArgs)
--------------------------------------------------
data Token = Token { issued_to :: Text
, audience :: Text
, user_id :: Maybe Text
, scope :: Text
, expires_in :: Integer
, email :: Maybe Text
, verified_email :: Maybe Bool
, access_type :: Text
} deriving (Show)
instance FromJSON Token where
parseJSON (Object o) = Token
<$> o .: "issued_to"
<*> o .: "audience"
<*> o .:? "user_id"
<*> o .: "scope"
<*> o .: "expires_in"
<*> o .:? "email"
<*> o .:? "verified_email"
<*> o .: "access_type"
parseJSON _ = mzero
data User = User { id :: Text
, name :: Text
, given_name :: Text
, family_name :: Text
, link :: Text
, picture :: Text
, gender :: Text
, birthday :: Text
, locale :: Text
} deriving (Show)
$(deriveJSON P.id ''User)
--------------------------------------------------
main :: IO ()
main = do
xs <- getArgs
case xs of
["offline"] -> offlineCase
_ -> normalCase
offlineCase :: IO ()
offlineCase = do
print $ authorizationUrl googleKey `appendQueryParam'` googleScopeEmail `appendQueryParam'` googleAccessOffline
putStrLn "visit the url and paste code here: "
code <- fmap BS.pack getLine
(Just (AccessToken accessToken refreshToken)) <- requestAccessToken googleKey code
print (accessToken, refreshToken)
validateToken accessToken >>= print
(validateToken' accessToken :: IO (Maybe Token)) >>= print
--
-- obtain a new access token with refresh token, which turns out only in response at first time.
-- Revoke Access https://www.google.com/settings/security
--
case refreshToken of
Nothing -> print "Failed to fetch refresh token"
Just tk -> do
(Just (AccessToken accessToken refreshToken)) <- refreshAccessToken googleKey tk
print (accessToken, refreshToken)
validateToken accessToken >>= print
(validateToken' accessToken :: IO (Maybe Token)) >>= print
normalCase :: IO ()
normalCase = do
print $ authorizationUrl googleKey `appendQueryParam'` googleScopeUserInfo
putStrLn "visit the url and paste code here: "
code <- fmap BS.pack getLine
(Just (AccessToken accessToken Nothing)) <- requestAccessToken googleKey code
putStr "AccessToken: " >> print accessToken
validateToken accessToken >>= print
(validateToken' accessToken :: IO (Maybe Token)) >>= print
userinfo accessToken >>= print
(userinfo' accessToken :: IO (Maybe User)) >>= print
--------------------------------------------------
-- Google API
-- | This is special for google Gain read-only access to the user's email address.
googleScopeEmail :: QueryParams
googleScopeEmail = [("scope", "https://www.googleapis.com/auth/userinfo.email")]
-- | Gain read-only access to basic profile information, including a
googleScopeUserInfo :: QueryParams
googleScopeUserInfo = [("scope", "https://www.googleapis.com/auth/userinfo.profile")]
-- | Access offline
googleAccessOffline :: QueryParams
googleAccessOffline = [("access_type", "offline")
,("approval_prompt", "force")]
-- | Token Validation
validateToken :: BS.ByteString -> IO BL.ByteString
validateToken accessToken = doSimpleGetRequest ("https://www.googleapis.com/oauth2/v1/tokeninfo" `appendQueryParam` (accessTokenToParam accessToken))
validateToken' :: FromJSON a => BS.ByteString -> IO (Maybe a)
validateToken' accessToken = doJSONGetRequest ("https://www.googleapis.com/oauth2/v1/tokeninfo" `appendQueryParam` (accessTokenToParam accessToken))
-- | fetch user email.
-- for more information, please check the playround site.
--
userinfo :: BS.ByteString -> IO BL.ByteString
userinfo accessToken = doSimpleGetRequest ("https://www.googleapis.com/oauth2/v2/userinfo" `appendQueryParam` (accessTokenToParam accessToken))
userinfo' :: FromJSON a => BS.ByteString -> IO (Maybe a)
userinfo' accessToken = doJSONGetRequest ("https://www.googleapis.com/oauth2/v2/userinfo" `appendQueryParam` (accessTokenToParam accessToken))