{-# LANGUAGE CPP #-} {-# LANGUAGE OverloadedStrings #-} -- | -- -- OAuth2 plugin for Battle.Net -- -- * Authenticates against battle.net. -- * Uses user's id as credentials identifier. -- * Returns user's battletag in extras. -- module Yesod.Auth.OAuth2.BattleNet ( oAuth2BattleNet ) where #if __GLASGOW_HASKELL__ < 710 import Control.Applicative ((<$>), (<*>)) #endif import Control.Exception (throwIO) import Control.Monad (mzero) import Yesod.Auth import Yesod.Auth.OAuth2 import Data.Monoid ((<>)) import Network.HTTP.Conduit (Manager) import Data.Aeson import Data.Text (Text) import qualified Data.Text as T (pack, toLower) import qualified Data.Text.Encoding as E (encodeUtf8) import Prelude import Yesod.Core.Widget data BattleNetUser = BattleNetUser { userId :: Int , battleTag :: Text } instance FromJSON BattleNetUser where parseJSON (Object o) = BattleNetUser <$> o .: "id" <*> o .: "battletag" parseJSON _ = mzero oAuth2BattleNet :: YesodAuth m => Text -- ^ Client ID -> Text -- ^ Client Secret -> Text -- ^ User region (e.g. "eu", "cn", "us") -> WidgetT m IO () -- ^ Login widget -> AuthPlugin m oAuth2BattleNet clientId clientSecret region widget = authOAuth2Widget widget "battle.net" oAuthData $ makeCredentials region where oAuthData = OAuth2 { oauthClientId = clientId , oauthClientSecret = clientSecret , oauthOAuthorizeEndpoint = fromRelative "https" host "/oauth/authorize" , oauthAccessTokenEndpoint = fromRelative "https" host "/oauth/token" , oauthCallback = Nothing } host = wwwHost $ T.toLower region makeCredentials :: Text -> Manager -> OAuth2Token -> IO (Creds m) makeCredentials region manager token = do userResult <- authGetJSON manager (accessToken token) $ fromRelative "https" (apiHost $ T.toLower region) "/account/user" case userResult of Left err -> throwIO $ invalidProfileResponse "battle.net" err Right user -> return Creds { credsPlugin = "battle.net" , credsIdent = T.pack $ show $ userId user , credsExtra = [("battletag", battleTag user)] } apiHost :: Text -> Host apiHost "cn" = "api.battlenet.com.cn" apiHost region = Host $ E.encodeUtf8 $ region <> ".api.battle.net" wwwHost :: Text -> Host wwwHost "cn" = "www.battlenet.com.cn" wwwHost region = Host $ E.encodeUtf8 $ region <> ".battle.net"