yesod-auth-oauth2 0.6.3.4 → 0.7.0.0
raw patch · 21 files changed
+647/−623 lines, 21 filesdep ~aeson-prettydep ~containersdep ~hspecPVP ok
version bump matches the API change (PVP)
Dependency ranges changed: aeson-pretty, containers, hspec, microlens, safe-exceptions, unliftio, uri-bytestring, warp, yesod
API changes (from Hackage documentation)
- Yesod.Auth.OAuth2: [oauthAccessTokenEndpoint] :: OAuth2 -> URI
- Yesod.Auth.OAuth2: [oauthCallback] :: OAuth2 -> Maybe URI
- Yesod.Auth.OAuth2: [oauthClientId] :: OAuth2 -> Text
- Yesod.Auth.OAuth2: [oauthClientSecret] :: OAuth2 -> Maybe Text
- Yesod.Auth.OAuth2: [oauthOAuthorizeEndpoint] :: OAuth2 -> URI
- Yesod.Auth.OAuth2.Prelude: [oauthAccessTokenEndpoint] :: OAuth2 -> URI
- Yesod.Auth.OAuth2.Prelude: [oauthCallback] :: OAuth2 -> Maybe URI
- Yesod.Auth.OAuth2.Prelude: [oauthClientId] :: OAuth2 -> Text
- Yesod.Auth.OAuth2.Prelude: [oauthClientSecret] :: OAuth2 -> Maybe Text
- Yesod.Auth.OAuth2.Prelude: [oauthOAuthorizeEndpoint] :: OAuth2 -> URI
+ Network.OAuth.OAuth2.Compat: AccessToken :: Text -> AccessToken
+ Network.OAuth.OAuth2.Compat: ExchangeToken :: Text -> ExchangeToken
+ Network.OAuth.OAuth2.Compat: IdToken :: Text -> IdToken
+ Network.OAuth.OAuth2.Compat: OAuth2 :: Text -> Maybe Text -> URIRef Absolute -> URIRef Absolute -> Maybe (URIRef Absolute) -> OAuth2
+ Network.OAuth.OAuth2.Compat: OAuth2Error :: Either Text a -> Maybe Text -> Maybe (URIRef Absolute) -> OAuth2Error a
+ Network.OAuth.OAuth2.Compat: OAuth2Token :: AccessToken -> Maybe RefreshToken -> Maybe Int -> Maybe Text -> Maybe IdToken -> OAuth2Token
+ Network.OAuth.OAuth2.Compat: RefreshToken :: Text -> RefreshToken
+ Network.OAuth.OAuth2.Compat: [accessToken] :: OAuth2Token -> AccessToken
+ Network.OAuth.OAuth2.Compat: [atoken] :: AccessToken -> Text
+ Network.OAuth.OAuth2.Compat: [errorDescription] :: OAuth2Error a -> Maybe Text
+ Network.OAuth.OAuth2.Compat: [errorUri] :: OAuth2Error a -> Maybe (URIRef Absolute)
+ Network.OAuth.OAuth2.Compat: [error] :: OAuth2Error a -> Either Text a
+ Network.OAuth.OAuth2.Compat: [expiresIn] :: OAuth2Token -> Maybe Int
+ Network.OAuth.OAuth2.Compat: [extoken] :: ExchangeToken -> Text
+ Network.OAuth.OAuth2.Compat: [idToken] :: OAuth2Token -> Maybe IdToken
+ Network.OAuth.OAuth2.Compat: [idtoken] :: IdToken -> Text
+ Network.OAuth.OAuth2.Compat: [oauth2AuthorizeEndpoint] :: OAuth2 -> URIRef Absolute
+ Network.OAuth.OAuth2.Compat: [oauth2ClientId] :: OAuth2 -> Text
+ Network.OAuth.OAuth2.Compat: [oauth2ClientSecret] :: OAuth2 -> Maybe Text
+ Network.OAuth.OAuth2.Compat: [oauth2RedirectUri] :: OAuth2 -> Maybe (URIRef Absolute)
+ Network.OAuth.OAuth2.Compat: [oauth2TokenEndpoint] :: OAuth2 -> URIRef Absolute
+ Network.OAuth.OAuth2.Compat: [refreshToken] :: OAuth2Token -> Maybe RefreshToken
+ Network.OAuth.OAuth2.Compat: [rtoken] :: RefreshToken -> Text
+ Network.OAuth.OAuth2.Compat: [tokenType] :: OAuth2Token -> Maybe Text
+ Network.OAuth.OAuth2.Compat: accessTokenToParam :: AccessToken -> [(ByteString, ByteString)]
+ Network.OAuth.OAuth2.Compat: accessTokenUrl :: OAuth2 -> ExchangeToken -> (URI, PostBody)
+ Network.OAuth.OAuth2.Compat: accessTokenUrl' :: OAuth2 -> ExchangeToken -> Maybe Text -> (URI, PostBody)
+ Network.OAuth.OAuth2.Compat: appendAccessToken :: URIRef a -> AccessToken -> URIRef a
+ Network.OAuth.OAuth2.Compat: appendQueryParams :: [(ByteString, ByteString)] -> URIRef a -> URIRef a
+ Network.OAuth.OAuth2.Compat: authGetBS :: Manager -> AccessToken -> URI -> IO (Either ByteString ByteString)
+ Network.OAuth.OAuth2.Compat: authGetBS2 :: Manager -> AccessToken -> URI -> IO (Either ByteString ByteString)
+ Network.OAuth.OAuth2.Compat: authGetJSON :: FromJSON b => Manager -> AccessToken -> URI -> IO (Either ByteString b)
+ Network.OAuth.OAuth2.Compat: authPostBS :: Manager -> AccessToken -> URI -> PostBody -> IO (Either ByteString ByteString)
+ Network.OAuth.OAuth2.Compat: authPostBS2 :: Manager -> AccessToken -> URI -> PostBody -> IO (Either ByteString ByteString)
+ Network.OAuth.OAuth2.Compat: authPostBS3 :: Manager -> AccessToken -> URI -> IO (Either ByteString ByteString)
+ Network.OAuth.OAuth2.Compat: authPostJSON :: FromJSON b => Manager -> AccessToken -> URI -> PostBody -> IO (Either ByteString b)
+ Network.OAuth.OAuth2.Compat: authRequest :: Request -> (Request -> Request) -> Manager -> IO (Either ByteString ByteString)
+ Network.OAuth.OAuth2.Compat: authorizationUrl :: OAuth2 -> URI
+ Network.OAuth.OAuth2.Compat: data OAuth2
+ Network.OAuth.OAuth2.Compat: data OAuth2Error a
+ Network.OAuth.OAuth2.Compat: data OAuth2Token
+ Network.OAuth.OAuth2.Compat: doSimplePostRequest :: FromJSON err => Manager -> OAuth2 -> URI -> PostBody -> IO (OAuth2Result err ByteString)
+ Network.OAuth.OAuth2.Compat: fetchAccessToken :: Manager -> OAuth2 -> ExchangeToken -> IO (OAuth2Result Errors OAuth2Token)
+ Network.OAuth.OAuth2.Compat: fetchAccessToken2 :: Manager -> OAuth2 -> ExchangeToken -> IO (OAuth2Result Errors OAuth2Token)
+ Network.OAuth.OAuth2.Compat: hostLens :: Lens' Request ByteString
+ Network.OAuth.OAuth2.Compat: mkDecodeOAuth2Error :: ByteString -> String -> OAuth2Error err
+ Network.OAuth.OAuth2.Compat: newtype AccessToken
+ Network.OAuth.OAuth2.Compat: newtype ExchangeToken
+ Network.OAuth.OAuth2.Compat: newtype IdToken
+ Network.OAuth.OAuth2.Compat: newtype RefreshToken
+ Network.OAuth.OAuth2.Compat: parseIntFlexible :: Value -> Parser Int
+ Network.OAuth.OAuth2.Compat: parseOAuth2Error :: FromJSON err => ByteString -> OAuth2Error err
+ Network.OAuth.OAuth2.Compat: portLens :: Lens' Request Int
+ Network.OAuth.OAuth2.Compat: refreshAccessToken :: Manager -> OAuth2 -> RefreshToken -> IO (OAuth2Result Errors OAuth2Token)
+ Network.OAuth.OAuth2.Compat: refreshAccessToken2 :: Manager -> OAuth2 -> RefreshToken -> IO (OAuth2Result Errors OAuth2Token)
+ Network.OAuth.OAuth2.Compat: refreshAccessTokenUrl :: OAuth2 -> RefreshToken -> (URI, PostBody)
+ Network.OAuth.OAuth2.Compat: requestToUri :: Request -> URI
+ Network.OAuth.OAuth2.Compat: type OAuth2Result err a = Either OAuth2Error err a
+ Network.OAuth.OAuth2.Compat: type PostBody = [(ByteString, ByteString)]
+ Network.OAuth.OAuth2.Compat: type QueryParams = [(ByteString, ByteString)]
+ Network.OAuth.OAuth2.Compat: uriToRequest :: MonadThrow m => URI -> m Request
+ Yesod.Auth.OAuth2: [oauth2AuthorizeEndpoint] :: OAuth2 -> URIRef Absolute
+ Yesod.Auth.OAuth2: [oauth2ClientId] :: OAuth2 -> Text
+ Yesod.Auth.OAuth2: [oauth2ClientSecret] :: OAuth2 -> Maybe Text
+ Yesod.Auth.OAuth2: [oauth2RedirectUri] :: OAuth2 -> Maybe (URIRef Absolute)
+ Yesod.Auth.OAuth2: [oauth2TokenEndpoint] :: OAuth2 -> URIRef Absolute
+ Yesod.Auth.OAuth2.Prelude: [oauth2AuthorizeEndpoint] :: OAuth2 -> URIRef Absolute
+ Yesod.Auth.OAuth2.Prelude: [oauth2ClientId] :: OAuth2 -> Text
+ Yesod.Auth.OAuth2.Prelude: [oauth2ClientSecret] :: OAuth2 -> Maybe Text
+ Yesod.Auth.OAuth2.Prelude: [oauth2RedirectUri] :: OAuth2 -> Maybe (URIRef Absolute)
+ Yesod.Auth.OAuth2.Prelude: [oauth2TokenEndpoint] :: OAuth2 -> URIRef Absolute
- Yesod.Auth.OAuth2: OAuth2 :: Text -> Maybe Text -> URI -> URI -> Maybe URI -> OAuth2
+ Yesod.Auth.OAuth2: OAuth2 :: Text -> Maybe Text -> URIRef Absolute -> URIRef Absolute -> Maybe (URIRef Absolute) -> OAuth2
- Yesod.Auth.OAuth2.Prelude: OAuth2 :: Text -> Maybe Text -> URI -> URI -> Maybe URI -> OAuth2
+ Yesod.Auth.OAuth2.Prelude: OAuth2 :: Text -> Maybe Text -> URIRef Absolute -> URIRef Absolute -> Maybe (URIRef Absolute) -> OAuth2
Files
- CHANGELOG.md +12/−1
- README.md +5/−5
- src/Network/OAuth/OAuth2/Compat.hs +61/−0
- src/Yesod/Auth/OAuth2.hs +41/−42
- src/Yesod/Auth/OAuth2/AzureAD.hs +26/−29
- src/Yesod/Auth/OAuth2/BattleNet.hs +30/−35
- src/Yesod/Auth/OAuth2/Bitbucket.hs +29/−33
- src/Yesod/Auth/OAuth2/ClassLink.hs +23/−27
- src/Yesod/Auth/OAuth2/Dispatch.hs +65/−67
- src/Yesod/Auth/OAuth2/EveOnline.hs +33/−34
- src/Yesod/Auth/OAuth2/GitHub.hs +23/−27
- src/Yesod/Auth/OAuth2/GitLab.hs +24/−29
- src/Yesod/Auth/OAuth2/Google.hs +34/−35
- src/Yesod/Auth/OAuth2/Nylas.hs +40/−43
- src/Yesod/Auth/OAuth2/Prelude.hs +43/−44
- src/Yesod/Auth/OAuth2/Salesforce.hs +38/−45
- src/Yesod/Auth/OAuth2/Slack.hs +36/−36
- src/Yesod/Auth/OAuth2/Spotify.hs +22/−25
- src/Yesod/Auth/OAuth2/Upcase.hs +23/−25
- src/Yesod/Auth/OAuth2/WordPressDotCom.hs +27/−30
- yesod-auth-oauth2.cabal +12/−11
CHANGELOG.md view
@@ -1,6 +1,17 @@-## [_Unreleased_](https://github.com/thoughtbot/yesod-auth-oauth2/compare/v0.6.3.4...main)+## [_Unreleased_](https://github.com/thoughtbot/yesod-auth-oauth2/compare/v0.7.0.0...main) None++## [v0.7.0.0](https://github.com/thoughtbot/yesod-auth-oauth2/compare/v0.6.3.4...v0.7.0.0)++- Support `hoauth2-2.0`++ The `OAuth2` type's fields have changed. If you are not defining your own+ Local Providers (i.e. you're not constructing any `OAuth2` values) you should+ not be affected by this change. If you are, you should update to the [new+ field names][oauth2].++ [oauth2]: https://hackage.haskell.org/package/hoauth2-2.0.0/docs/Network-OAuth-OAuth2-Internal.html#t:OAuth2 ## [v0.6.3.4](https://github.com/thoughtbot/yesod-auth-oauth2/compare/v0.6.3.1...v0.6.3.4)
README.md view
@@ -91,11 +91,11 @@ } where oauth2 = OAuth2- { oauthClientId = clientId- , oauthClientSecret = Just clientSecret- , oauthOAuthorizeEndpoint = "https://mysite.com/oauth/authorize"- , oauthAccessTokenEndpoint = "https://mysite.com/oauth/token"- , oauthCallback = Nothing+ { oauth2ClientId = clientId+ , oauth2ClientSecret = Just clientSecret+ , oauth2AuthorizeEndpoint = "https://mysite.com/oauth/authorize"+ , oauth2TokenEndpoint = "https://mysite.com/oauth/token"+ , oauth2RedirectUri = Nothing } ```
+ src/Network/OAuth/OAuth2/Compat.hs view
@@ -0,0 +1,61 @@+{-# LANGUAGE CPP #-}++module Network.OAuth.OAuth2.Compat+ ( OAuth2(..)+ , authorizationUrl+ , fetchAccessToken+ , fetchAccessToken2+ , module Network.OAuth.OAuth2+ ) where++import Network.HTTP.Conduit (Manager)+import Network.OAuth.OAuth2 hiding+ (OAuth2(..), authorizationUrl, fetchAccessToken, fetchAccessToken2)+import qualified Network.OAuth.OAuth2 as OAuth2+import Network.OAuth.OAuth2.TokenRequest (Errors)+import URI.ByteString++#if MIN_VERSION_hoauth2(2,0,0)+import Network.OAuth.OAuth2 (OAuth2(..))++getOAuth2 :: OAuth2 -> OAuth2+getOAuth2 = id++#else+import Data.Text (Text)++data OAuth2 = OAuth2+ { oauth2ClientId :: Text+ , oauth2ClientSecret :: Maybe Text+ , oauth2AuthorizeEndpoint :: URIRef Absolute+ , oauth2TokenEndpoint :: URIRef Absolute+ , oauth2RedirectUri :: Maybe (URIRef Absolute)+ }++getOAuth2 :: OAuth2 -> OAuth2.OAuth2+getOAuth2 o = OAuth2.OAuth2+ { OAuth2.oauthClientId = oauth2ClientId o+ , OAuth2.oauthClientSecret = oauth2ClientSecret o+ , OAuth2.oauthOAuthorizeEndpoint = oauth2AuthorizeEndpoint o+ , OAuth2.oauthAccessTokenEndpoint = oauth2TokenEndpoint o+ , OAuth2.oauthCallback = oauth2RedirectUri o+ }++#endif++authorizationUrl :: OAuth2 -> URI+authorizationUrl = OAuth2.authorizationUrl . getOAuth2++fetchAccessToken+ :: Manager+ -> OAuth2+ -> ExchangeToken+ -> IO (OAuth2Result Errors OAuth2Token)+fetchAccessToken m = OAuth2.fetchAccessToken m . getOAuth2++fetchAccessToken2+ :: Manager+ -> OAuth2+ -> ExchangeToken+ -> IO (OAuth2Result Errors OAuth2Token)+fetchAccessToken2 m = OAuth2.fetchAccessToken2 m . getOAuth2
src/Yesod/Auth/OAuth2.hs view
@@ -8,26 +8,25 @@ -- See @"Yesod.Auth.OAuth2.GitHub"@ for example usage. -- module Yesod.Auth.OAuth2- ( OAuth2(..)- , FetchCreds- , Manager- , OAuth2Token(..)- , Creds(..)- , oauth2Url- , authOAuth2- , authOAuth2Widget+ ( OAuth2(..)+ , FetchCreds+ , Manager+ , OAuth2Token(..)+ , Creds(..)+ , oauth2Url+ , authOAuth2+ , authOAuth2Widget -- * Alternatives that use 'fetchAccessToken2'- , authOAuth2'- , authOAuth2Widget'+ , authOAuth2'+ , authOAuth2Widget' -- * Reading our @'credsExtra'@ keys- , getAccessToken- , getRefreshToken- , getUserResponse- , getUserResponseJSON- )-where+ , getAccessToken+ , getRefreshToken+ , getUserResponse+ , getUserResponseJSON+ ) where import Control.Error.Util (note) import Control.Monad ((<=<))@@ -36,7 +35,7 @@ import Data.Text (Text) import Data.Text.Encoding (encodeUtf8) import Network.HTTP.Conduit (Manager)-import Network.OAuth.OAuth2+import Network.OAuth.OAuth2.Compat import Yesod.Auth import Yesod.Auth.OAuth2.Dispatch import Yesod.Core.Widget@@ -64,12 +63,12 @@ -- example. -- authOAuth2Widget- :: YesodAuth m- => WidgetFor m ()- -> Text- -> OAuth2- -> FetchCreds m- -> AuthPlugin m+ :: YesodAuth m+ => WidgetFor m ()+ -> Text+ -> OAuth2+ -> FetchCreds m+ -> AuthPlugin m authOAuth2Widget = buildPlugin fetchAccessToken -- | A version of 'authOAuth2Widget' that uses 'fetchAccessToken2'@@ -77,27 +76,27 @@ -- See <https://github.com/thoughtbot/yesod-auth-oauth2/pull/129> -- authOAuth2Widget'- :: YesodAuth m- => WidgetFor m ()- -> Text- -> OAuth2- -> FetchCreds m- -> AuthPlugin m+ :: YesodAuth m+ => WidgetFor m ()+ -> Text+ -> OAuth2+ -> FetchCreds m+ -> AuthPlugin m authOAuth2Widget' = buildPlugin fetchAccessToken2 buildPlugin- :: YesodAuth m- => FetchToken- -> WidgetFor m ()- -> Text- -> OAuth2- -> FetchCreds m- -> AuthPlugin m+ :: YesodAuth m+ => FetchToken+ -> WidgetFor m ()+ -> Text+ -> OAuth2+ -> FetchCreds m+ -> AuthPlugin m buildPlugin getToken widget name oauth getCreds = AuthPlugin- name- (dispatchAuthRequest name oauth getToken getCreds)- login- where login tm = [whamlet|<a href=@{tm $ oauth2Url name}>^{widget}|]+ name+ (dispatchAuthRequest name oauth getToken getCreds)+ login+ where login tm = [whamlet|<a href=@{tm $ oauth2Url name}>^{widget}|] -- | Read the @'AccessToken'@ from the values set via @'setExtra'@ getAccessToken :: Creds m -> Maybe AccessToken@@ -113,9 +112,9 @@ -- | Read the original profile response from the values set via @'setExtra'@ getUserResponse :: Creds m -> Maybe ByteString getUserResponse =- (fromStrict . encodeUtf8 <$>) . lookup "userResponse" . credsExtra+ (fromStrict . encodeUtf8 <$>) . lookup "userResponse" . credsExtra -- | @'getUserResponse'@, and decode as JSON getUserResponseJSON :: FromJSON a => Creds m -> Either String a getUserResponseJSON =- eitherDecode <=< note "userResponse key not present" . getUserResponse+ eitherDecode <=< note "userResponse key not present" . getUserResponse
src/Yesod/Auth/OAuth2/AzureAD.hs view
@@ -7,10 +7,9 @@ -- * Uses email as credentials identifier -- module Yesod.Auth.OAuth2.AzureAD- ( oauth2AzureAD- , oauth2AzureADScoped- )-where+ ( oauth2AzureAD+ , oauth2AzureADScoped+ ) where import Prelude import Yesod.Auth.OAuth2.Prelude@@ -18,7 +17,7 @@ newtype User = User Text instance FromJSON User where- parseJSON = withObject "User" $ \o -> User <$> o .: "mail"+ parseJSON = withObject "User" $ \o -> User <$> o .: "mail" pluginName :: Text pluginName = "azuread"@@ -31,28 +30,26 @@ oauth2AzureADScoped :: YesodAuth m => [Text] -> Text -> Text -> AuthPlugin m oauth2AzureADScoped scopes clientId clientSecret =- authOAuth2 pluginName oauth2 $ \manager token -> do- (User userId, userResponse) <- authGetProfile- pluginName- manager- token- "https://graph.microsoft.com/v1.0/me"+ authOAuth2 pluginName oauth2 $ \manager token -> do+ (User userId, userResponse) <- authGetProfile+ pluginName+ manager+ token+ "https://graph.microsoft.com/v1.0/me" - pure Creds- { credsPlugin = pluginName- , credsIdent = userId- , credsExtra = setExtra token userResponse- }- where- oauth2 = OAuth2- { oauthClientId = clientId- , oauthClientSecret = Just clientSecret- , oauthOAuthorizeEndpoint =- "https://login.windows.net/common/oauth2/authorize"- `withQuery` [ scopeParam "," scopes- , ("resource", "https://graph.microsoft.com")- ]- , oauthAccessTokenEndpoint =- "https://login.windows.net/common/oauth2/token"- , oauthCallback = Nothing- }+ pure Creds { credsPlugin = pluginName+ , credsIdent = userId+ , credsExtra = setExtra token userResponse+ }+ where+ oauth2 = OAuth2+ { oauth2ClientId = clientId+ , oauth2ClientSecret = Just clientSecret+ , oauth2AuthorizeEndpoint =+ "https://login.windows.net/common/oauth2/authorize"+ `withQuery` [ scopeParam "," scopes+ , ("resource", "https://graph.microsoft.com")+ ]+ , oauth2TokenEndpoint = "https://login.windows.net/common/oauth2/token"+ , oauth2RedirectUri = Nothing+ }
src/Yesod/Auth/OAuth2/BattleNet.hs view
@@ -9,10 +9,9 @@ -- * Returns user's battletag in extras. -- module Yesod.Auth.OAuth2.BattleNet- ( oauth2BattleNet- , oAuth2BattleNet- )-where+ ( oauth2BattleNet+ , oAuth2BattleNet+ ) where import Yesod.Auth.OAuth2.Prelude @@ -22,52 +21,48 @@ newtype User = User Int instance FromJSON User where- parseJSON = withObject "User" $ \o -> User <$> o .: "id"+ parseJSON = withObject "User" $ \o -> User <$> o .: "id" pluginName :: Text pluginName = "battle.net" oauth2BattleNet- :: YesodAuth m- => WidgetFor m () -- ^ Login widget- -> Text -- ^ User region (e.g. "eu", "cn", "us")- -> Text -- ^ Client ID- -> Text -- ^ Client Secret- -> AuthPlugin m+ :: YesodAuth m+ => WidgetFor m () -- ^ Login widget+ -> Text -- ^ User region (e.g. "eu", "cn", "us")+ -> Text -- ^ Client ID+ -> Text -- ^ Client Secret+ -> AuthPlugin m oauth2BattleNet widget region clientId clientSecret =- authOAuth2Widget widget pluginName oauth2 $ \manager token -> do- (User userId, userResponse) <-- authGetProfile pluginName manager token- $ fromRelative- "https"- (apiHost $ T.toLower region)- "/account/user"+ authOAuth2Widget widget pluginName oauth2 $ \manager token -> do+ (User userId, userResponse) <-+ authGetProfile pluginName manager token+ $ fromRelative "https" (apiHost $ T.toLower region) "/account/user" - pure Creds- { credsPlugin = pluginName- , credsIdent = T.pack $ show userId- , credsExtra = setExtra token userResponse- }- where- host = wwwHost $ T.toLower region- oauth2 = OAuth2- { oauthClientId = clientId- , oauthClientSecret = Just clientSecret- , oauthOAuthorizeEndpoint = fromRelative "https" host "/oauth/authorize"- , oauthAccessTokenEndpoint = fromRelative "https" host "/oauth/token"- , oauthCallback = Nothing- }+ pure Creds { credsPlugin = pluginName+ , credsIdent = T.pack $ show userId+ , credsExtra = setExtra token userResponse+ }+ where+ host = wwwHost $ T.toLower region+ oauth2 = OAuth2+ { oauth2ClientId = clientId+ , oauth2ClientSecret = Just clientSecret+ , oauth2AuthorizeEndpoint = fromRelative "https" host "/oauth/authorize"+ , oauth2TokenEndpoint = fromRelative "https" host "/oauth/token"+ , oauth2RedirectUri = Nothing+ } apiHost :: Text -> Host-apiHost "cn" = "api.battlenet.com.cn"+apiHost "cn" = "api.battlenet.com.cn" apiHost region = Host $ encodeUtf8 $ region <> ".api.battle.net" wwwHost :: Text -> Host-wwwHost "cn" = "www.battlenet.com.cn"+wwwHost "cn" = "www.battlenet.com.cn" wwwHost region = Host $ encodeUtf8 $ region <> ".battle.net" oAuth2BattleNet- :: YesodAuth m => Text -> Text -> Text -> WidgetFor m () -> AuthPlugin m+ :: YesodAuth m => Text -> Text -> Text -> WidgetFor m () -> AuthPlugin m oAuth2BattleNet i s r w = oauth2BattleNet w r i s {-# DEPRECATED oAuth2BattleNet "Use oauth2BattleNet" #-}
src/Yesod/Auth/OAuth2/Bitbucket.hs view
@@ -7,10 +7,9 @@ -- * Uses bitbucket uuid as credentials identifier -- module Yesod.Auth.OAuth2.Bitbucket- ( oauth2Bitbucket- , oauth2BitbucketScoped- )-where+ ( oauth2Bitbucket+ , oauth2BitbucketScoped+ ) where import Yesod.Auth.OAuth2.Prelude @@ -19,7 +18,7 @@ newtype User = User Text instance FromJSON User where- parseJSON = withObject "User" $ \o -> User <$> o .: "uuid"+ parseJSON = withObject "User" $ \o -> User <$> o .: "uuid" pluginName :: Text pluginName = "bitbucket"@@ -32,32 +31,29 @@ oauth2BitbucketScoped :: YesodAuth m => [Text] -> Text -> Text -> AuthPlugin m oauth2BitbucketScoped scopes clientId clientSecret =- authOAuth2 pluginName oauth2 $ \manager token -> do- (User userId, userResponse) <- authGetProfile- pluginName- manager- token- "https://api.bitbucket.com/2.0/user"+ authOAuth2 pluginName oauth2 $ \manager token -> do+ (User userId, userResponse) <- authGetProfile+ pluginName+ manager+ token+ "https://api.bitbucket.com/2.0/user" - pure Creds- { credsPlugin = pluginName- -- FIXME: Preserved bug. This should just be userId (it's already- -- a Text), but because this code was shipped, folks likely have- -- Idents in their database like @"\"...\""@, and if we fixed this- -- they would need migrating. We're keeping it for now as it's a- -- minor wart. Breaking typed APIs is one thing, causing data to go- -- invalid is another.- , credsIdent = T.pack $ show userId- , credsExtra = setExtra token userResponse- }- where- oauth2 = OAuth2- { oauthClientId = clientId- , oauthClientSecret = Just clientSecret- , oauthOAuthorizeEndpoint =- "https://bitbucket.com/site/oauth2/authorize"- `withQuery` [scopeParam "," scopes]- , oauthAccessTokenEndpoint =- "https://bitbucket.com/site/oauth2/access_token"- , oauthCallback = Nothing- }+ pure Creds { credsPlugin = pluginName+ -- FIXME: Preserved bug. This should just be userId (it's already+ -- a Text), but because this code was shipped, folks likely have+ -- Idents in their database like @"\"...\""@, and if we fixed this+ -- they would need migrating. We're keeping it for now as it's a+ -- minor wart. Breaking typed APIs is one thing, causing data to go+ -- invalid is another.+ , credsIdent = T.pack $ show userId+ , credsExtra = setExtra token userResponse+ }+ where+ oauth2 = OAuth2+ { oauth2ClientId = clientId+ , oauth2ClientSecret = Just clientSecret+ , oauth2AuthorizeEndpoint = "https://bitbucket.com/site/oauth2/authorize"+ `withQuery` [scopeParam "," scopes]+ , oauth2TokenEndpoint = "https://bitbucket.com/site/oauth2/access_token"+ , oauth2RedirectUri = Nothing+ }
src/Yesod/Auth/OAuth2/ClassLink.hs view
@@ -1,10 +1,9 @@ {-# LANGUAGE OverloadedStrings #-} module Yesod.Auth.OAuth2.ClassLink- ( oauth2ClassLink- , oauth2ClassLinkScoped- )-where+ ( oauth2ClassLink+ , oauth2ClassLinkScoped+ ) where import Yesod.Auth.OAuth2.Prelude @@ -13,7 +12,7 @@ newtype User = User Int instance FromJSON User where- parseJSON = withObject "User" $ \o -> User <$> o .: "UserId"+ parseJSON = withObject "User" $ \o -> User <$> o .: "UserId" pluginName :: Text pluginName = "classlink"@@ -26,26 +25,23 @@ oauth2ClassLinkScoped :: YesodAuth m => [Text] -> Text -> Text -> AuthPlugin m oauth2ClassLinkScoped scopes clientId clientSecret =- authOAuth2 pluginName oauth2 $ \manager token -> do- (User userId, userResponse) <- authGetProfile- pluginName- manager- token- "https://nodeapi.classlink.com/v2/my/info"+ authOAuth2 pluginName oauth2 $ \manager token -> do+ (User userId, userResponse) <- authGetProfile+ pluginName+ manager+ token+ "https://nodeapi.classlink.com/v2/my/info" - pure Creds- { credsPlugin = pluginName- , credsIdent = T.pack $ show userId- , credsExtra = setExtra token userResponse- }- where- oauth2 = OAuth2- { oauthClientId = clientId- , oauthClientSecret = Just clientSecret- , oauthOAuthorizeEndpoint =- "https://launchpad.classlink.com/oauth2/v2/auth"- `withQuery` [scopeParam "," scopes]- , oauthAccessTokenEndpoint =- "https://launchpad.classlink.com/oauth2/v2/token"- , oauthCallback = Nothing- }+ pure Creds { credsPlugin = pluginName+ , credsIdent = T.pack $ show userId+ , credsExtra = setExtra token userResponse+ }+ where+ oauth2 = OAuth2+ { oauth2ClientId = clientId+ , oauth2ClientSecret = Just clientSecret+ , oauth2AuthorizeEndpoint = "https://launchpad.classlink.com/oauth2/v2/auth"+ `withQuery` [scopeParam "," scopes]+ , oauth2TokenEndpoint = "https://launchpad.classlink.com/oauth2/v2/token"+ , oauth2RedirectUri = Nothing+ }
src/Yesod/Auth/OAuth2/Dispatch.hs view
@@ -5,19 +5,19 @@ {-# LANGUAGE TypeFamilies #-} module Yesod.Auth.OAuth2.Dispatch- ( FetchToken- , fetchAccessToken- , fetchAccessToken2- , FetchCreds- , dispatchAuthRequest- ) where+ ( FetchToken+ , fetchAccessToken+ , fetchAccessToken2+ , FetchCreds+ , dispatchAuthRequest+ ) where import Control.Monad.Except import Data.Text (Text) import qualified Data.Text as T import Data.Text.Encoding (encodeUtf8) import Network.HTTP.Conduit (Manager)-import Network.OAuth.OAuth2+import Network.OAuth.OAuth2.Compat import Network.OAuth.OAuth2.TokenRequest (Errors) import URI.ByteString.Extension import UnliftIO.Exception@@ -32,24 +32,24 @@ -- This will be 'fetchAccessToken' or 'fetchAccessToken2' -- type FetchToken- = Manager -> OAuth2 -> ExchangeToken -> IO (OAuth2Result Errors OAuth2Token)+ = Manager -> OAuth2 -> ExchangeToken -> IO (OAuth2Result Errors OAuth2Token) -- | How to take an @'OAuth2Token'@ and retrieve user credentials type FetchCreds m = Manager -> OAuth2Token -> IO (Creds m) -- | Dispatch the various OAuth2 handshake routes dispatchAuthRequest- :: Text -- ^ Name- -> OAuth2 -- ^ Service details- -> FetchToken -- ^ How to get a token- -> FetchCreds m -- ^ How to get credentials- -> Text -- ^ Method- -> [Text] -- ^ Path pieces- -> AuthHandler m TypedContent+ :: Text -- ^ Name+ -> OAuth2 -- ^ Service details+ -> FetchToken -- ^ How to get a token+ -> FetchCreds m -- ^ How to get credentials+ -> Text -- ^ Method+ -> [Text] -- ^ Path pieces+ -> AuthHandler m TypedContent dispatchAuthRequest name oauth2 _ _ "GET" ["forward"] =- handleDispatchError $ dispatchForward name oauth2+ handleDispatchError $ dispatchForward name oauth2 dispatchAuthRequest name oauth2 getToken getCreds "GET" ["callback"] =- handleDispatchError $ dispatchCallback name oauth2 getToken getCreds+ handleDispatchError $ dispatchCallback name oauth2 getToken getCreds dispatchAuthRequest _ _ _ _ _ _ = notFound -- | Handle @GET \/forward@@@ -58,14 +58,14 @@ -- 2. Redirect to the Provider's authorization URL -- dispatchForward- :: (MonadError DispatchError m, MonadAuthHandler site m)- => Text- -> OAuth2- -> m TypedContent+ :: (MonadError DispatchError m, MonadAuthHandler site m)+ => Text+ -> OAuth2+ -> m TypedContent dispatchForward name oauth2 = do- csrf <- setSessionCSRF $ tokenSessionKey name- oauth2' <- withCallbackAndState name oauth2 csrf- redirect $ toText $ authorizationUrl oauth2'+ csrf <- setSessionCSRF $ tokenSessionKey name+ oauth2' <- withCallbackAndState name oauth2 csrf+ redirect $ toText $ authorizationUrl oauth2' -- | Handle @GET \/callback@ --@@ -74,41 +74,40 @@ -- 3. Use the AccessToken to construct a @'Creds'@ value for the Provider -- dispatchCallback- :: (MonadError DispatchError m, MonadAuthHandler site m)- => Text- -> OAuth2- -> FetchToken- -> FetchCreds site- -> m TypedContent+ :: (MonadError DispatchError m, MonadAuthHandler site m)+ => Text+ -> OAuth2+ -> FetchToken+ -> FetchCreds site+ -> m TypedContent dispatchCallback name oauth2 getToken getCreds = do- onErrorResponse $ throwError . OAuth2HandshakeError- csrf <- verifySessionCSRF $ tokenSessionKey name- code <- requireGetParam "code"- manager <- authHttpManager- oauth2' <- withCallbackAndState name oauth2 csrf- token <- either (throwError . OAuth2ResultError) pure- =<< liftIO (getToken manager oauth2' $ ExchangeToken code)- creds <-- liftIO (getCreds manager token)- `catch` (throwError . FetchCredsIOException)- `catch` (throwError . FetchCredsYesodOAuth2Exception)- setCredsRedirect creds+ onErrorResponse $ throwError . OAuth2HandshakeError+ csrf <- verifySessionCSRF $ tokenSessionKey name+ code <- requireGetParam "code"+ manager <- authHttpManager+ oauth2' <- withCallbackAndState name oauth2 csrf+ token <- either (throwError . OAuth2ResultError) pure+ =<< liftIO (getToken manager oauth2' $ ExchangeToken code)+ creds <-+ liftIO (getCreds manager token)+ `catch` (throwError . FetchCredsIOException)+ `catch` (throwError . FetchCredsYesodOAuth2Exception)+ setCredsRedirect creds withCallbackAndState- :: (MonadError DispatchError m, MonadAuthHandler site m)- => Text- -> OAuth2- -> Text- -> m OAuth2+ :: (MonadError DispatchError m, MonadAuthHandler site m)+ => Text+ -> OAuth2+ -> Text+ -> m OAuth2 withCallbackAndState name oauth2 csrf = do- uri <- ($ PluginR name ["callback"]) <$> getParentUrlRender- callback <- maybe (throwError $ InvalidCallbackUri uri) pure $ fromText uri- pure oauth2- { oauthCallback = Just callback- , oauthOAuthorizeEndpoint =- oauthOAuthorizeEndpoint oauth2- `withQuery` [("state", encodeUtf8 csrf)]- }+ uri <- ($ PluginR name ["callback"]) <$> getParentUrlRender+ callback <- maybe (throwError $ InvalidCallbackUri uri) pure $ fromText uri+ pure oauth2+ { oauth2RedirectUri = Just callback+ , oauth2AuthorizeEndpoint = oauth2AuthorizeEndpoint oauth2+ `withQuery` [("state", encodeUtf8 csrf)]+ } getParentUrlRender :: MonadHandler m => m (Route (SubHandlerSite m) -> Text) getParentUrlRender = (.) <$> getUrlRender <*> getRouteToParent@@ -124,25 +123,24 @@ -- setSessionCSRF :: MonadHandler m => Text -> m Text setSessionCSRF sessionKey = do- csrfToken <- liftIO randomToken- csrfToken <$ setSession sessionKey csrfToken- where randomToken = T.filter (/= '+') <$> randomText 64+ csrfToken <- liftIO randomToken+ csrfToken <$ setSession sessionKey csrfToken+ where randomToken = T.filter (/= '+') <$> randomText 64 -- | Verify the callback provided the same CSRF token as in our session verifySessionCSRF- :: (MonadError DispatchError m, MonadHandler m) => Text -> m Text+ :: (MonadError DispatchError m, MonadHandler m) => Text -> m Text verifySessionCSRF sessionKey = do- token <- requireGetParam "state"- sessionToken <- lookupSession sessionKey- deleteSession sessionKey- token <$ unless- (sessionToken == Just token)- (throwError $ InvalidStateToken sessionToken token)+ token <- requireGetParam "state"+ sessionToken <- lookupSession sessionKey+ deleteSession sessionKey+ token <$ unless (sessionToken == Just token)+ (throwError $ InvalidStateToken sessionToken token) requireGetParam- :: (MonadError DispatchError m, MonadHandler m) => Text -> m Text+ :: (MonadError DispatchError m, MonadHandler m) => Text -> m Text requireGetParam key =- maybe (throwError $ MissingParameter key) pure =<< lookupGetParam key+ maybe (throwError $ MissingParameter key) pure =<< lookupGetParam key tokenSessionKey :: Text -> Text tokenSessionKey name = "_yesod_oauth2_" <> name
src/Yesod/Auth/OAuth2/EveOnline.hs view
@@ -8,11 +8,10 @@ -- * Uses EVEs unique account-user-char-hash as credentials identifier -- module Yesod.Auth.OAuth2.EveOnline- ( oauth2Eve- , oauth2EveScoped- , WidgetType(..)- )-where+ ( oauth2Eve+ , oauth2EveScoped+ , WidgetType(..)+ ) where import Yesod.Auth.OAuth2.Prelude @@ -22,7 +21,7 @@ newtype User = User Text instance FromJSON User where- parseJSON = withObject "User" $ \o -> User <$> o .: "CharacterOwnerHash"+ parseJSON = withObject "User" $ \o -> User <$> o .: "CharacterOwnerHash" data WidgetType m = Plain -- ^ Simple "Login via eveonline" text@@ -35,13 +34,13 @@ asWidget :: YesodAuth m => WidgetType m -> WidgetFor m () asWidget Plain = [whamlet|Login via eveonline|] asWidget BigWhite =- [whamlet|<img src="https://images.contentful.com/idjq7aai9ylm/4PTzeiAshqiM8osU2giO0Y/5cc4cb60bac52422da2e45db87b6819c/EVE_SSO_Login_Buttons_Large_White.png?w=270&h=45">|]+ [whamlet|<img src="https://images.contentful.com/idjq7aai9ylm/4PTzeiAshqiM8osU2giO0Y/5cc4cb60bac52422da2e45db87b6819c/EVE_SSO_Login_Buttons_Large_White.png?w=270&h=45">|] asWidget BigBlack- = [whamlet|<img src="https://images.contentful.com/idjq7aai9ylm/4fSjj56uD6CYwYyus4KmES/4f6385c91e6de56274d99496e6adebab/EVE_SSO_Login_Buttons_Large_Black.png?w=270&h=45">|]+ = [whamlet|<img src="https://images.contentful.com/idjq7aai9ylm/4fSjj56uD6CYwYyus4KmES/4f6385c91e6de56274d99496e6adebab/EVE_SSO_Login_Buttons_Large_Black.png?w=270&h=45">|] asWidget SmallWhite- = [whamlet|<img src="https://images.contentful.com/idjq7aai9ylm/18BxKSXCymyqY4QKo8KwKe/c2bdded6118472dd587c8107f24104d7/EVE_SSO_Login_Buttons_Small_White.png?w=195&h=30">|]+ = [whamlet|<img src="https://images.contentful.com/idjq7aai9ylm/18BxKSXCymyqY4QKo8KwKe/c2bdded6118472dd587c8107f24104d7/EVE_SSO_Login_Buttons_Small_White.png?w=195&h=30">|] asWidget SmallBlack- = [whamlet|<img src="https://images.contentful.com/idjq7aai9ylm/12vrPsIMBQi28QwCGOAqGk/33234da7672c6b0cdca394fc8e0b1c2b/EVE_SSO_Login_Buttons_Small_Black.png?w=195&h=30">|]+ = [whamlet|<img src="https://images.contentful.com/idjq7aai9ylm/12vrPsIMBQi28QwCGOAqGk/33234da7672c6b0cdca394fc8e0b1c2b/EVE_SSO_Login_Buttons_Small_Black.png?w=195&h=30">|] asWidget (Custom a) = a pluginName :: Text@@ -54,29 +53,29 @@ oauth2Eve = oauth2EveScoped defaultScopes oauth2EveScoped- :: YesodAuth m => [Text] -> WidgetType m -> Text -> Text -> AuthPlugin m+ :: YesodAuth m => [Text] -> WidgetType m -> Text -> Text -> AuthPlugin m oauth2EveScoped scopes widgetType clientId clientSecret =- authOAuth2Widget (asWidget widgetType) pluginName oauth2- $ \manager token -> do- (User userId, userResponse) <- authGetProfile- pluginName- manager- token- "https://login.eveonline.com/oauth/verify"+ authOAuth2Widget (asWidget widgetType) pluginName oauth2 $ \manager token ->+ do+ (User userId, userResponse) <- authGetProfile+ pluginName+ manager+ token+ "https://login.eveonline.com/oauth/verify" - pure Creds- { credsPlugin = "eveonline"- -- FIXME: Preserved bug. See similar comment in Bitbucket provider.- , credsIdent = T.pack $ show userId- , credsExtra = setExtra token userResponse- }- where- oauth2 = OAuth2- { oauthClientId = clientId- , oauthClientSecret = Just clientSecret- , oauthOAuthorizeEndpoint =- "https://login.eveonline.com/oauth/authorize"- `withQuery` [("response_type", "code"), scopeParam " " scopes]- , oauthAccessTokenEndpoint = "https://login.eveonline.com/oauth/token"- , oauthCallback = Nothing- }+ pure Creds { credsPlugin = "eveonline"+ -- FIXME: Preserved bug. See similar comment in Bitbucket provider.+ , credsIdent = T.pack $ show userId+ , credsExtra = setExtra token userResponse+ }+ where+ oauth2 = OAuth2+ { oauth2ClientId = clientId+ , oauth2ClientSecret = Just clientSecret+ , oauth2AuthorizeEndpoint = "https://login.eveonline.com/oauth/authorize"+ `withQuery` [ ("response_type", "code")+ , scopeParam " " scopes+ ]+ , oauth2TokenEndpoint = "https://login.eveonline.com/oauth/token"+ , oauth2RedirectUri = Nothing+ }
src/Yesod/Auth/OAuth2/GitHub.hs view
@@ -7,10 +7,9 @@ -- * Uses github user id as credentials identifier -- module Yesod.Auth.OAuth2.GitHub- ( oauth2GitHub- , oauth2GitHubScoped- )-where+ ( oauth2GitHub+ , oauth2GitHubScoped+ ) where import Yesod.Auth.OAuth2.Prelude @@ -19,7 +18,7 @@ newtype User = User Int instance FromJSON User where- parseJSON = withObject "User" $ \o -> User <$> o .: "id"+ parseJSON = withObject "User" $ \o -> User <$> o .: "id" pluginName :: Text pluginName = "github"@@ -32,26 +31,23 @@ oauth2GitHubScoped :: YesodAuth m => [Text] -> Text -> Text -> AuthPlugin m oauth2GitHubScoped scopes clientId clientSecret =- authOAuth2 pluginName oauth2 $ \manager token -> do- (User userId, userResponse) <- authGetProfile- pluginName- manager- token- "https://api.github.com/user"+ authOAuth2 pluginName oauth2 $ \manager token -> do+ (User userId, userResponse) <- authGetProfile+ pluginName+ manager+ token+ "https://api.github.com/user" - pure Creds- { credsPlugin = pluginName- , credsIdent = T.pack $ show userId- , credsExtra = setExtra token userResponse- }- where- oauth2 = OAuth2- { oauthClientId = clientId- , oauthClientSecret = Just clientSecret- , oauthOAuthorizeEndpoint =- "https://github.com/login/oauth/authorize"- `withQuery` [scopeParam "," scopes]- , oauthAccessTokenEndpoint =- "https://github.com/login/oauth/access_token"- , oauthCallback = Nothing- }+ pure Creds { credsPlugin = pluginName+ , credsIdent = T.pack $ show userId+ , credsExtra = setExtra token userResponse+ }+ where+ oauth2 = OAuth2+ { oauth2ClientId = clientId+ , oauth2ClientSecret = Just clientSecret+ , oauth2AuthorizeEndpoint = "https://github.com/login/oauth/authorize"+ `withQuery` [scopeParam "," scopes]+ , oauth2TokenEndpoint = "https://github.com/login/oauth/access_token"+ , oauth2RedirectUri = Nothing+ }
src/Yesod/Auth/OAuth2/GitLab.hs view
@@ -1,11 +1,10 @@ {-# LANGUAGE OverloadedStrings #-} module Yesod.Auth.OAuth2.GitLab- ( oauth2GitLab- , oauth2GitLabHostScopes- , defaultHost- , defaultScopes- )-where+ ( oauth2GitLab+ , oauth2GitLabHostScopes+ , defaultHost+ , defaultScopes+ ) where import Yesod.Auth.OAuth2.Prelude @@ -14,7 +13,7 @@ newtype User = User Int instance FromJSON User where- parseJSON = withObject "User" $ \o -> User <$> o .: "id"+ parseJSON = withObject "User" $ \o -> User <$> o .: "id" pluginName :: Text pluginName = "gitlab"@@ -38,27 +37,23 @@ oauth2GitLab = oauth2GitLabHostScopes defaultHost defaultScopes oauth2GitLabHostScopes- :: YesodAuth m => URI -> [Text] -> Text -> Text -> AuthPlugin m+ :: YesodAuth m => URI -> [Text] -> Text -> Text -> AuthPlugin m oauth2GitLabHostScopes host scopes clientId clientSecret =- authOAuth2 pluginName oauth2 $ \manager token -> do- (User userId, userResponse) <-- authGetProfile pluginName manager token- $ host- `withPath` "/api/v4/user"+ authOAuth2 pluginName oauth2 $ \manager token -> do+ (User userId, userResponse) <-+ authGetProfile pluginName manager token $ host `withPath` "/api/v4/user" - pure Creds- { credsPlugin = pluginName- , credsIdent = T.pack $ show userId- , credsExtra = setExtra token userResponse- }- where- oauth2 = OAuth2- { oauthClientId = clientId- , oauthClientSecret = Just clientSecret- , oauthOAuthorizeEndpoint =- host- `withPath` "/oauth/authorize"- `withQuery` [scopeParam " " scopes]- , oauthAccessTokenEndpoint = host `withPath` "/oauth/token"- , oauthCallback = Nothing- }+ pure Creds { credsPlugin = pluginName+ , credsIdent = T.pack $ show userId+ , credsExtra = setExtra token userResponse+ }+ where+ oauth2 = OAuth2+ { oauth2ClientId = clientId+ , oauth2ClientSecret = Just clientSecret+ , oauth2AuthorizeEndpoint = host+ `withPath` "/oauth/authorize"+ `withQuery` [scopeParam " " scopes]+ , oauth2TokenEndpoint = host `withPath` "/oauth/token"+ , oauth2RedirectUri = Nothing+ }
src/Yesod/Auth/OAuth2/Google.hs view
@@ -25,12 +25,11 @@ -- > -- continue normally with updatedCreds -- module Yesod.Auth.OAuth2.Google- ( oauth2Google- , oauth2GoogleWidget- , oauth2GoogleScoped- , oauth2GoogleScopedWidget- )-where+ ( oauth2Google+ , oauth2GoogleWidget+ , oauth2GoogleScoped+ , oauth2GoogleScopedWidget+ ) where import Yesod.Auth.OAuth2.Prelude import Yesod.Core (WidgetFor, whamlet)@@ -38,10 +37,10 @@ newtype User = User Text instance FromJSON User where- parseJSON =- withObject "User" $ \o -> User- -- Required for data backwards-compatibility- <$> (("google-uid:" <>) <$> o .: "sub")+ parseJSON =+ withObject "User" $ \o -> User+ -- Required for data backwards-compatibility+ <$> (("google-uid:" <>) <$> o .: "sub") pluginName :: Text pluginName = "google"@@ -52,34 +51,34 @@ oauth2Google :: YesodAuth m => Text -> Text -> AuthPlugin m oauth2Google = oauth2GoogleScoped defaultScopes -oauth2GoogleWidget :: YesodAuth m => WidgetFor m () -> Text -> Text -> AuthPlugin m+oauth2GoogleWidget+ :: YesodAuth m => WidgetFor m () -> Text -> Text -> AuthPlugin m oauth2GoogleWidget widget = oauth2GoogleScopedWidget widget defaultScopes oauth2GoogleScoped :: YesodAuth m => [Text] -> Text -> Text -> AuthPlugin m-oauth2GoogleScoped = oauth2GoogleScopedWidget [whamlet|Login via #{pluginName}|]+oauth2GoogleScoped =+ oauth2GoogleScopedWidget [whamlet|Login via #{pluginName}|] -oauth2GoogleScopedWidget :: YesodAuth m => WidgetFor m () -> [Text] -> Text -> Text -> AuthPlugin m+oauth2GoogleScopedWidget+ :: YesodAuth m => WidgetFor m () -> [Text] -> Text -> Text -> AuthPlugin m oauth2GoogleScopedWidget widget scopes clientId clientSecret =- authOAuth2Widget widget pluginName oauth2 $ \manager token -> do- (User userId, userResponse) <- authGetProfile- pluginName- manager- token- "https://www.googleapis.com/oauth2/v3/userinfo"+ authOAuth2Widget widget pluginName oauth2 $ \manager token -> do+ (User userId, userResponse) <- authGetProfile+ pluginName+ manager+ token+ "https://www.googleapis.com/oauth2/v3/userinfo" - pure Creds- { credsPlugin = pluginName- , credsIdent = userId- , credsExtra = setExtra token userResponse- }- where- oauth2 = OAuth2- { oauthClientId = clientId- , oauthClientSecret = Just clientSecret- , oauthOAuthorizeEndpoint =- "https://accounts.google.com/o/oauth2/auth"- `withQuery` [scopeParam " " scopes]- , oauthAccessTokenEndpoint =- "https://www.googleapis.com/oauth2/v3/token"- , oauthCallback = Nothing- }+ pure Creds { credsPlugin = pluginName+ , credsIdent = userId+ , credsExtra = setExtra token userResponse+ }+ where+ oauth2 = OAuth2+ { oauth2ClientId = clientId+ , oauth2ClientSecret = Just clientSecret+ , oauth2AuthorizeEndpoint = "https://accounts.google.com/o/oauth2/auth"+ `withQuery` [scopeParam " " scopes]+ , oauth2TokenEndpoint = "https://www.googleapis.com/oauth2/v3/token"+ , oauth2RedirectUri = Nothing+ }
src/Yesod/Auth/OAuth2/Nylas.hs view
@@ -1,9 +1,8 @@ {-# LANGUAGE OverloadedStrings #-} module Yesod.Auth.OAuth2.Nylas- ( oauth2Nylas- )-where+ ( oauth2Nylas+ ) where import Yesod.Auth.OAuth2.Prelude @@ -16,7 +15,7 @@ newtype User = User Text instance FromJSON User where- parseJSON = withObject "User" $ \o -> User <$> o .: "id"+ parseJSON = withObject "User" $ \o -> User <$> o .: "id" pluginName :: Text pluginName = "nylas"@@ -26,44 +25,42 @@ oauth2Nylas :: YesodAuth m => Text -> Text -> AuthPlugin m oauth2Nylas clientId clientSecret =- authOAuth2 pluginName oauth $ \manager token -> do- req <- applyBasicAuth (encodeUtf8 $ atoken $ accessToken token) ""- <$> parseRequest "https://api.nylas.com/account"- resp <- httpLbs req manager- let userResponse = responseBody resp+ authOAuth2 pluginName oauth $ \manager token -> do+ req <- applyBasicAuth (encodeUtf8 $ atoken $ accessToken token) ""+ <$> parseRequest "https://api.nylas.com/account"+ resp <- httpLbs req manager+ let userResponse = responseBody resp - -- FIXME: was this working? I'm 95% sure that the client will throw its- -- own exception on unsuccessful status codes.- unless (HT.statusIsSuccessful $ responseStatus resp)- $ throwIO- $ YesodOAuth2Exception.GenericError pluginName- $ "Unsuccessful HTTP response: "- <> BL8.unpack userResponse+ -- FIXME: was this working? I'm 95% sure that the client will throw its+ -- own exception on unsuccessful status codes.+ unless (HT.statusIsSuccessful $ responseStatus resp)+ $ throwIO+ $ YesodOAuth2Exception.GenericError pluginName+ $ "Unsuccessful HTTP response: "+ <> BL8.unpack userResponse - either- (throwIO . YesodOAuth2Exception.JSONDecodingError pluginName)- (\(User userId) -> pure Creds- { credsPlugin = pluginName- , credsIdent = userId- , credsExtra = setExtra token userResponse- }- )- $ eitherDecode userResponse- where- oauth = OAuth2- { oauthClientId = clientId- , oauthClientSecret = Just clientSecret- , oauthOAuthorizeEndpoint =- "https://api.nylas.com/oauth/authorize"- `withQuery` [ ("response_type", "code")- , ( "client_id"- , encodeUtf8 clientId- )- -- N.B. The scopes delimeter is unknown/untested. Verify that before- -- extracting this to an argument and offering a Scoped function. In- -- its current state, it doesn't matter because it's only one scope.- , scopeParam "," defaultScopes- ]- , oauthAccessTokenEndpoint = "https://api.nylas.com/oauth/token"- , oauthCallback = Nothing- }+ either+ (throwIO . YesodOAuth2Exception.JSONDecodingError pluginName)+ (\(User userId) -> pure Creds { credsPlugin = pluginName+ , credsIdent = userId+ , credsExtra = setExtra token userResponse+ }+ )+ $ eitherDecode userResponse+ where+ oauth = OAuth2+ { oauth2ClientId = clientId+ , oauth2ClientSecret = Just clientSecret+ , oauth2AuthorizeEndpoint = "https://api.nylas.com/oauth/authorize"+ `withQuery` [ ("response_type", "code")+ , ( "client_id"+ , encodeUtf8 clientId+ )+ -- N.B. The scopes delimeter is unknown/untested. Verify that before+ -- extracting this to an argument and offering a Scoped function. In+ -- its current state, it doesn't matter because it's only one scope.+ , scopeParam "," defaultScopes+ ]+ , oauth2TokenEndpoint = "https://api.nylas.com/oauth/token"+ , oauth2RedirectUri = Nothing+ }
src/Yesod/Auth/OAuth2/Prelude.hs view
@@ -6,56 +6,55 @@ -- implementations. May also be useful for writing local providers. -- module Yesod.Auth.OAuth2.Prelude- (+ ( -- * Provider helpers- authGetProfile- , scopeParam- , setExtra+ authGetProfile+ , scopeParam+ , setExtra -- * Text- , Text- , decodeUtf8- , encodeUtf8+ , Text+ , decodeUtf8+ , encodeUtf8 -- * JSON- , (.:)- , (.:?)- , (.=)- , (<>)- , FromJSON(..)- , ToJSON(..)- , eitherDecode- , withObject+ , (.:)+ , (.:?)+ , (.=)+ , (<>)+ , FromJSON(..)+ , ToJSON(..)+ , eitherDecode+ , withObject -- * Exceptions- , throwIO+ , throwIO -- * OAuth2- , OAuth2(..)- , OAuth2Token(..)- , AccessToken(..)- , RefreshToken(..)+ , OAuth2(..)+ , OAuth2Token(..)+ , AccessToken(..)+ , RefreshToken(..) -- * HTTP- , Manager+ , Manager -- * Yesod- , YesodAuth(..)- , AuthPlugin(..)- , Creds(..)+ , YesodAuth(..)+ , AuthPlugin(..)+ , Creds(..) -- * Bytestring URI types- , URI- , Host(..)+ , URI+ , Host(..) -- * Bytestring URI extensions- , module URI.ByteString.Extension+ , module URI.ByteString.Extension -- * Temporary, until I finish re-structuring modules- , authOAuth2- , authOAuth2Widget- )-where+ , authOAuth2+ , authOAuth2Widget+ ) where import Control.Exception.Safe import Data.Aeson@@ -65,7 +64,7 @@ import qualified Data.Text as T import Data.Text.Encoding import Network.HTTP.Conduit-import Network.OAuth.OAuth2+import Network.OAuth.OAuth2.Compat import URI.ByteString import URI.ByteString.Extension import Yesod.Auth@@ -79,28 +78,28 @@ -- fetched via additional requests by consumers. -- authGetProfile- :: FromJSON a- => Text- -> Manager- -> OAuth2Token- -> URI- -> IO (a, BL.ByteString)+ :: FromJSON a+ => Text+ -> Manager+ -> OAuth2Token+ -> URI+ -> IO (a, BL.ByteString) authGetProfile name manager token url = do- resp <- fromAuthGet name =<< authGetBS manager (accessToken token) url- decoded <- fromAuthJSON name resp- pure (decoded, resp)+ resp <- fromAuthGet name =<< authGetBS manager (accessToken token) url+ decoded <- fromAuthJSON name resp+ pure (decoded, resp) -- | Throws a @Left@ result as an @'YesodOAuth2Exception'@ fromAuthGet :: Text -> Either BL.ByteString BL.ByteString -> IO BL.ByteString fromAuthGet _ (Right bs) = pure bs -- nice fromAuthGet name (Left err) =- throwIO $ YesodOAuth2Exception.OAuth2Error name err+ throwIO $ YesodOAuth2Exception.OAuth2Error name err -- | Throws a decoding error as an @'YesodOAuth2Exception'@ fromAuthJSON :: FromJSON a => Text -> BL.ByteString -> IO a fromAuthJSON name =- either (throwIO . YesodOAuth2Exception.JSONDecodingError name) pure- . eitherDecode+ either (throwIO . YesodOAuth2Exception.JSONDecodingError name) pure+ . eitherDecode -- | A tuple of @\"scope\"@ and the given scopes separated by a delimiter scopeParam :: Text -> [Text] -> (ByteString, ByteString)
src/Yesod/Auth/OAuth2/Salesforce.hs view
@@ -7,19 +7,18 @@ -- * Uses Salesforce user id as credentials identifier -- module Yesod.Auth.OAuth2.Salesforce- ( oauth2Salesforce- , oauth2SalesforceScoped- , oauth2SalesforceSandbox- , oauth2SalesforceSandboxScoped- )-where+ ( oauth2Salesforce+ , oauth2SalesforceScoped+ , oauth2SalesforceSandbox+ , oauth2SalesforceSandboxScoped+ ) where import Yesod.Auth.OAuth2.Prelude newtype User = User Text instance FromJSON User where- parseJSON = withObject "User" $ \o -> User <$> o .: "user_id"+ parseJSON = withObject "User" $ \o -> User <$> o .: "user_id" pluginName :: Text pluginName = "salesforce"@@ -32,51 +31,45 @@ oauth2SalesforceScoped :: YesodAuth m => [Text] -> Text -> Text -> AuthPlugin m oauth2SalesforceScoped = salesforceHelper- pluginName- "https://login.salesforce.com/services/oauth2/userinfo"- "https://login.salesforce.com/services/oauth2/authorize"- "https://login.salesforce.com/services/oauth2/token"+ pluginName+ "https://login.salesforce.com/services/oauth2/userinfo"+ "https://login.salesforce.com/services/oauth2/authorize"+ "https://login.salesforce.com/services/oauth2/token" oauth2SalesforceSandbox :: YesodAuth m => Text -> Text -> AuthPlugin m oauth2SalesforceSandbox = oauth2SalesforceSandboxScoped defaultScopes oauth2SalesforceSandboxScoped- :: YesodAuth m => [Text] -> Text -> Text -> AuthPlugin m+ :: YesodAuth m => [Text] -> Text -> Text -> AuthPlugin m oauth2SalesforceSandboxScoped = salesforceHelper- (pluginName <> "-sandbox")- "https://test.salesforce.com/services/oauth2/userinfo"- "https://test.salesforce.com/services/oauth2/authorize"- "https://test.salesforce.com/services/oauth2/token"+ (pluginName <> "-sandbox")+ "https://test.salesforce.com/services/oauth2/userinfo"+ "https://test.salesforce.com/services/oauth2/authorize"+ "https://test.salesforce.com/services/oauth2/token" salesforceHelper- :: YesodAuth m- => Text- -> URI -- ^ User profile- -> URI -- ^ Authorize- -> URI -- ^ Token- -> [Text]- -> Text- -> Text- -> AuthPlugin m+ :: YesodAuth m+ => Text+ -> URI -- ^ User profile+ -> URI -- ^ Authorize+ -> URI -- ^ Token+ -> [Text]+ -> Text+ -> Text+ -> AuthPlugin m salesforceHelper name profileUri authorizeUri tokenUri scopes clientId clientSecret- = authOAuth2 name oauth2 $ \manager token -> do- (User userId, userResponse) <- authGetProfile- name- manager- token- profileUri+ = authOAuth2 name oauth2 $ \manager token -> do+ (User userId, userResponse) <- authGetProfile name manager token profileUri - pure Creds- { credsPlugin = pluginName- , credsIdent = userId- , credsExtra = setExtra token userResponse- }- where- oauth2 = OAuth2- { oauthClientId = clientId- , oauthClientSecret = Just clientSecret- , oauthOAuthorizeEndpoint =- authorizeUri `withQuery` [scopeParam " " scopes]- , oauthAccessTokenEndpoint = tokenUri- , oauthCallback = Nothing- }+ pure Creds { credsPlugin = pluginName+ , credsIdent = userId+ , credsExtra = setExtra token userResponse+ }+ where+ oauth2 = OAuth2+ { oauth2ClientId = clientId+ , oauth2ClientSecret = Just clientSecret+ , oauth2AuthorizeEndpoint = authorizeUri `withQuery` [scopeParam " " scopes]+ , oauth2TokenEndpoint = tokenUri+ , oauth2RedirectUri = Nothing+ }
src/Yesod/Auth/OAuth2/Slack.hs view
@@ -6,11 +6,10 @@ -- * Uses slack user id as credentials identifier -- module Yesod.Auth.OAuth2.Slack- ( SlackScope(..)- , oauth2Slack- , oauth2SlackScoped- )-where+ ( SlackScope(..)+ , oauth2Slack+ , oauth2SlackScoped+ ) where import Yesod.Auth.OAuth2.Prelude @@ -25,17 +24,17 @@ | SlackAvatarScope scopeText :: SlackScope -> Text-scopeText SlackBasicScope = "identity.basic"-scopeText SlackEmailScope = "identity.email"-scopeText SlackTeamScope = "identity.team"+scopeText SlackBasicScope = "identity.basic"+scopeText SlackEmailScope = "identity.email"+scopeText SlackTeamScope = "identity.team" scopeText SlackAvatarScope = "identity.avatar" newtype User = User Text instance FromJSON User where- parseJSON = withObject "User" $ \root -> do- o <- root .: "user"- User <$> o .: "id"+ parseJSON = withObject "User" $ \root -> do+ o <- root .: "user"+ User <$> o .: "id" pluginName :: Text pluginName = "slack"@@ -46,30 +45,31 @@ oauth2Slack :: YesodAuth m => Text -> Text -> AuthPlugin m oauth2Slack = oauth2SlackScoped defaultScopes -oauth2SlackScoped :: YesodAuth m => [SlackScope] -> Text -> Text -> AuthPlugin m+oauth2SlackScoped+ :: YesodAuth m => [SlackScope] -> Text -> Text -> AuthPlugin m oauth2SlackScoped scopes clientId clientSecret =- authOAuth2 pluginName oauth2 $ \manager token -> do- let param = encodeUtf8 $ atoken $ accessToken token- req <- setQueryString [("token", Just param)]- <$> parseUrlThrow "https://slack.com/api/users.identity"- userResponse <- responseBody <$> httpLbs req manager+ authOAuth2 pluginName oauth2 $ \manager token -> do+ let param = encodeUtf8 $ atoken $ accessToken token+ req <- setQueryString [("token", Just param)]+ <$> parseUrlThrow "https://slack.com/api/users.identity"+ userResponse <- responseBody <$> httpLbs req manager - either- (throwIO . YesodOAuth2Exception.JSONDecodingError pluginName)- (\(User userId) -> pure Creds- { credsPlugin = pluginName- , credsIdent = userId- , credsExtra = setExtra token userResponse- }- )- $ eitherDecode userResponse- where- oauth2 = OAuth2- { oauthClientId = clientId- , oauthClientSecret = Just clientSecret- , oauthOAuthorizeEndpoint =- "https://slack.com/oauth/authorize"- `withQuery` [scopeParam "," $ map scopeText scopes]- , oauthAccessTokenEndpoint = "https://slack.com/api/oauth.access"- , oauthCallback = Nothing- }+ either+ (throwIO . YesodOAuth2Exception.JSONDecodingError pluginName)+ (\(User userId) -> pure Creds { credsPlugin = pluginName+ , credsIdent = userId+ , credsExtra = setExtra token userResponse+ }+ )+ $ eitherDecode userResponse+ where+ oauth2 = OAuth2+ { oauth2ClientId = clientId+ , oauth2ClientSecret = Just clientSecret+ , oauth2AuthorizeEndpoint = "https://slack.com/oauth/authorize"+ `withQuery` [ scopeParam ","+ $ map scopeText scopes+ ]+ , oauth2TokenEndpoint = "https://slack.com/api/oauth.access"+ , oauth2RedirectUri = Nothing+ }
src/Yesod/Auth/OAuth2/Spotify.hs view
@@ -4,41 +4,38 @@ -- OAuth2 plugin for http://spotify.com -- module Yesod.Auth.OAuth2.Spotify- ( oauth2Spotify- )-where+ ( oauth2Spotify+ ) where import Yesod.Auth.OAuth2.Prelude newtype User = User Text instance FromJSON User where- parseJSON = withObject "User" $ \o -> User <$> o .: "id"+ parseJSON = withObject "User" $ \o -> User <$> o .: "id" pluginName :: Text pluginName = "spotify" oauth2Spotify :: YesodAuth m => [Text] -> Text -> Text -> AuthPlugin m oauth2Spotify scopes clientId clientSecret =- authOAuth2 pluginName oauth2 $ \manager token -> do- (User userId, userResponse) <- authGetProfile- pluginName- manager- token- "https://api.spotify.com/v1/me"+ authOAuth2 pluginName oauth2 $ \manager token -> do+ (User userId, userResponse) <- authGetProfile+ pluginName+ manager+ token+ "https://api.spotify.com/v1/me" - pure Creds- { credsPlugin = pluginName- , credsIdent = userId- , credsExtra = setExtra token userResponse- }- where- oauth2 = OAuth2- { oauthClientId = clientId- , oauthClientSecret = Just clientSecret- , oauthOAuthorizeEndpoint =- "https://accounts.spotify.com/authorize"- `withQuery` [scopeParam " " scopes]- , oauthAccessTokenEndpoint = "https://accounts.spotify.com/api/token"- , oauthCallback = Nothing- }+ pure Creds { credsPlugin = pluginName+ , credsIdent = userId+ , credsExtra = setExtra token userResponse+ }+ where+ oauth2 = OAuth2+ { oauth2ClientId = clientId+ , oauth2ClientSecret = Just clientSecret+ , oauth2AuthorizeEndpoint = "https://accounts.spotify.com/authorize"+ `withQuery` [scopeParam " " scopes]+ , oauth2TokenEndpoint = "https://accounts.spotify.com/api/token"+ , oauth2RedirectUri = Nothing+ }
src/Yesod/Auth/OAuth2/Upcase.hs view
@@ -7,9 +7,8 @@ -- * Uses upcase user id as credentials identifier -- module Yesod.Auth.OAuth2.Upcase- ( oauth2Upcase- )-where+ ( oauth2Upcase+ ) where import Yesod.Auth.OAuth2.Prelude @@ -18,32 +17,31 @@ newtype User = User Int instance FromJSON User where- parseJSON = withObject "User" $ \root -> do- o <- root .: "user"- User <$> o .: "id"+ parseJSON = withObject "User" $ \root -> do+ o <- root .: "user"+ User <$> o .: "id" pluginName :: Text pluginName = "upcase" oauth2Upcase :: YesodAuth m => Text -> Text -> AuthPlugin m oauth2Upcase clientId clientSecret =- authOAuth2 pluginName oauth2 $ \manager token -> do- (User userId, userResponse) <- authGetProfile- pluginName- manager- token- "http://upcase.com/api/v1/me.json"+ authOAuth2 pluginName oauth2 $ \manager token -> do+ (User userId, userResponse) <- authGetProfile+ pluginName+ manager+ token+ "http://upcase.com/api/v1/me.json" - pure Creds- { credsPlugin = pluginName- , credsIdent = T.pack $ show userId- , credsExtra = setExtra token userResponse- }- where- oauth2 = OAuth2- { oauthClientId = clientId- , oauthClientSecret = Just clientSecret- , oauthOAuthorizeEndpoint = "http://upcase.com/oauth/authorize"- , oauthAccessTokenEndpoint = "http://upcase.com/oauth/token"- , oauthCallback = Nothing- }+ pure Creds { credsPlugin = pluginName+ , credsIdent = T.pack $ show userId+ , credsExtra = setExtra token userResponse+ }+ where+ oauth2 = OAuth2+ { oauth2ClientId = clientId+ , oauth2ClientSecret = Just clientSecret+ , oauth2AuthorizeEndpoint = "http://upcase.com/oauth/authorize"+ , oauth2TokenEndpoint = "http://upcase.com/oauth/token"+ , oauth2RedirectUri = Nothing+ }
src/Yesod/Auth/OAuth2/WordPressDotCom.hs view
@@ -1,9 +1,8 @@ {-# LANGUAGE OverloadedStrings #-} module Yesod.Auth.OAuth2.WordPressDotCom- ( oauth2WordPressDotCom- )-where+ ( oauth2WordPressDotCom+ ) where import qualified Data.Text as T import Yesod.Auth.OAuth2.Prelude@@ -14,35 +13,33 @@ newtype WpUser = WpUser Int instance FromJSON WpUser where- parseJSON = withObject "WpUser" $ \o -> WpUser <$> o .: "ID"+ parseJSON = withObject "WpUser" $ \o -> WpUser <$> o .: "ID" oauth2WordPressDotCom- :: (YesodAuth m)- => Text -- ^ Client Id- -> Text -- ^ Client Secret- -> AuthPlugin m+ :: (YesodAuth m)+ => Text -- ^ Client Id+ -> Text -- ^ Client Secret+ -> AuthPlugin m oauth2WordPressDotCom clientId clientSecret =- authOAuth2 pluginName oauth2 $ \manager token -> do- (WpUser userId, userResponse) <- authGetProfile- pluginName- manager- token- "https://public-api.wordpress.com/rest/v1/me/"+ authOAuth2 pluginName oauth2 $ \manager token -> do+ (WpUser userId, userResponse) <- authGetProfile+ pluginName+ manager+ token+ "https://public-api.wordpress.com/rest/v1/me/" - pure Creds- { credsPlugin = pluginName- , credsIdent = T.pack $ show userId- , credsExtra = setExtra token userResponse- }+ pure Creds { credsPlugin = pluginName+ , credsIdent = T.pack $ show userId+ , credsExtra = setExtra token userResponse+ } - where- oauth2 = OAuth2- { oauthClientId = clientId- , oauthClientSecret = Just clientSecret- , oauthOAuthorizeEndpoint =- "https://public-api.wordpress.com/oauth2/authorize"- `withQuery` [scopeParam "," ["auth"]]- , oauthAccessTokenEndpoint =- "https://public-api.wordpress.com/oauth2/token"- , oauthCallback = Nothing- }+ where+ oauth2 = OAuth2+ { oauth2ClientId = clientId+ , oauth2ClientSecret = Just clientSecret+ , oauth2AuthorizeEndpoint =+ "https://public-api.wordpress.com/oauth2/authorize"+ `withQuery` [scopeParam "," ["auth"]]+ , oauth2TokenEndpoint = "https://public-api.wordpress.com/oauth2/token"+ , oauth2RedirectUri = Nothing+ }
yesod-auth-oauth2.cabal view
@@ -1,6 +1,6 @@ cabal-version: 1.12 name: yesod-auth-oauth2-version: 0.6.3.4+version: 0.7.0.0 license: MIT license-file: LICENSE maintainer: engineering@freckle.com@@ -31,6 +31,7 @@ library exposed-modules:+ Network.OAuth.OAuth2.Compat UnliftIO.Except URI.ByteString.Extension Yesod.Auth.OAuth2@@ -70,12 +71,12 @@ http-conduit >=2.0, http-types >=0.8, memory >=0.15.0,- microlens >=0.4.11.2,+ microlens >=0.4.12.0, mtl >=2.2.2,- safe-exceptions >=0.1.7.1,+ safe-exceptions >=0.1.7.2, text >=0.7,- unliftio >=0.2.14,- uri-bytestring >=0.3.3.0,+ unliftio >=0.2.20,+ uri-bytestring >=0.3.3.1, yesod-auth >=1.6.0, yesod-core >=1.6.0 @@ -87,15 +88,15 @@ ghc-options: -Wall -threaded -rtsopts -with-rtsopts=-N build-depends: aeson >=0.6,- aeson-pretty >=0.8.8,+ aeson-pretty >=0.8.9, base >=4.9.0.0 && <5, bytestring >=0.9.1.4,- containers >=0.6.2.1,+ containers >=0.6.5.1, http-conduit >=2.0, load-env >=0.2.1.0, text >=0.7,- warp >=3.3.14,- yesod >=1.6.1.0,+ warp >=3.3.18,+ yesod >=1.6.1.2, yesod-auth >=1.6.0, yesod-auth-oauth2 -any @@ -114,6 +115,6 @@ ghc-options: -Wall build-depends: base >=4.9.0.0 && <5,- hspec >=2.7.8,- uri-bytestring >=0.3.3.0,+ hspec >=2.7.10,+ uri-bytestring >=0.3.3.1, yesod-auth-oauth2 -any