diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index fb55c4b..285b745 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -13,6 +13,7 @@ jobs: matrix: stack-yaml: - stack.yaml + - stack-hoauth2-2.0.yaml - stack-lts-17.4.yaml - stack-lts-16.10.yaml - stack-lts-13.2.yaml diff --git a/README.md b/README.md index dba48a8..48e0541 100644 --- a/README.md +++ b/README.md @@ -91,11 +91,11 @@ oauth2MySite clientId clientSecret = } 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 } ``` diff --git a/src/Network/OAuth/OAuth2/Compat.hs b/src/Network/OAuth/OAuth2/Compat.hs new file mode 100644 index 0000000..36e3f74 --- /dev/null +++ b/src/Network/OAuth/OAuth2/Compat.hs @@ -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 diff --git a/src/Yesod/Auth/OAuth2.hs b/src/Yesod/Auth/OAuth2.hs index 92e5951..5bed58a 100644 --- a/src/Yesod/Auth/OAuth2.hs +++ b/src/Yesod/Auth/OAuth2.hs @@ -26,8 +26,7 @@ module Yesod.Auth.OAuth2 , getRefreshToken , getUserResponse , getUserResponseJSON - ) -where + ) where import Control.Error.Util (note) import Control.Monad ((<=<)) @@ -36,7 +35,7 @@ import Data.ByteString.Lazy (ByteString, fromStrict) 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 diff --git a/src/Yesod/Auth/OAuth2/AzureAD.hs b/src/Yesod/Auth/OAuth2/AzureAD.hs index 24334f7..cc9b27e 100644 --- a/src/Yesod/Auth/OAuth2/AzureAD.hs +++ b/src/Yesod/Auth/OAuth2/AzureAD.hs @@ -45,14 +45,14 @@ oauth2AzureADScoped scopes clientId clientSecret = } where oauth2 = OAuth2 - { oauthClientId = clientId - , oauthClientSecret = Just clientSecret - , oauthOAuthorizeEndpoint = + { oauth2ClientId = clientId + , oauth2ClientSecret = Just clientSecret + , oauth2AuthorizeEndpoint = "https://login.windows.net/common/oauth2/authorize" `withQuery` [ scopeParam "," scopes , ("resource", "https://graph.microsoft.com") ] - , oauthAccessTokenEndpoint = + , oauth2TokenEndpoint = "https://login.windows.net/common/oauth2/token" - , oauthCallback = Nothing + , oauth2RedirectUri = Nothing } diff --git a/src/Yesod/Auth/OAuth2/BattleNet.hs b/src/Yesod/Auth/OAuth2/BattleNet.hs index 1141808..fd89b95 100644 --- a/src/Yesod/Auth/OAuth2/BattleNet.hs +++ b/src/Yesod/Auth/OAuth2/BattleNet.hs @@ -51,11 +51,11 @@ oauth2BattleNet widget region clientId clientSecret = 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 + { oauth2ClientId = clientId + , oauth2ClientSecret = Just clientSecret + , oauth2AuthorizeEndpoint = fromRelative "https" host "/oauth/authorize" + , oauth2TokenEndpoint = fromRelative "https" host "/oauth/token" + , oauth2RedirectUri = Nothing } diff --git a/src/Yesod/Auth/OAuth2/Bitbucket.hs b/src/Yesod/Auth/OAuth2/Bitbucket.hs index 1f2738a..c485fee 100644 --- a/src/Yesod/Auth/OAuth2/Bitbucket.hs +++ b/src/Yesod/Auth/OAuth2/Bitbucket.hs @@ -52,12 +52,12 @@ oauth2BitbucketScoped scopes clientId clientSecret = } where oauth2 = OAuth2 - { oauthClientId = clientId - , oauthClientSecret = Just clientSecret - , oauthOAuthorizeEndpoint = + { oauth2ClientId = clientId + , oauth2ClientSecret = Just clientSecret + , oauth2AuthorizeEndpoint = "https://bitbucket.com/site/oauth2/authorize" `withQuery` [scopeParam "," scopes] - , oauthAccessTokenEndpoint = + , oauth2TokenEndpoint = "https://bitbucket.com/site/oauth2/access_token" - , oauthCallback = Nothing + , oauth2RedirectUri = Nothing } diff --git a/src/Yesod/Auth/OAuth2/ClassLink.hs b/src/Yesod/Auth/OAuth2/ClassLink.hs index 03c51ad..1127d2f 100644 --- a/src/Yesod/Auth/OAuth2/ClassLink.hs +++ b/src/Yesod/Auth/OAuth2/ClassLink.hs @@ -40,12 +40,12 @@ oauth2ClassLinkScoped scopes clientId clientSecret = } where oauth2 = OAuth2 - { oauthClientId = clientId - , oauthClientSecret = Just clientSecret - , oauthOAuthorizeEndpoint = + { oauth2ClientId = clientId + , oauth2ClientSecret = Just clientSecret + , oauth2AuthorizeEndpoint = "https://launchpad.classlink.com/oauth2/v2/auth" `withQuery` [scopeParam "," scopes] - , oauthAccessTokenEndpoint = + , oauth2TokenEndpoint = "https://launchpad.classlink.com/oauth2/v2/token" - , oauthCallback = Nothing + , oauth2RedirectUri = Nothing } diff --git a/src/Yesod/Auth/OAuth2/Dispatch.hs b/src/Yesod/Auth/OAuth2/Dispatch.hs index a524e2a..e470030 100644 --- a/src/Yesod/Auth/OAuth2/Dispatch.hs +++ b/src/Yesod/Auth/OAuth2/Dispatch.hs @@ -17,7 +17,7 @@ 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 @@ -104,9 +104,9 @@ 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 + { oauth2RedirectUri = Just callback + , oauth2AuthorizeEndpoint = + oauth2AuthorizeEndpoint oauth2 `withQuery` [("state", encodeUtf8 csrf)] } diff --git a/src/Yesod/Auth/OAuth2/EveOnline.hs b/src/Yesod/Auth/OAuth2/EveOnline.hs index e95c348..165a910 100644 --- a/src/Yesod/Auth/OAuth2/EveOnline.hs +++ b/src/Yesod/Auth/OAuth2/EveOnline.hs @@ -72,11 +72,11 @@ oauth2EveScoped scopes widgetType clientId clientSecret = } where oauth2 = OAuth2 - { oauthClientId = clientId - , oauthClientSecret = Just clientSecret - , oauthOAuthorizeEndpoint = + { oauth2ClientId = clientId + , oauth2ClientSecret = Just clientSecret + , oauth2AuthorizeEndpoint = "https://login.eveonline.com/oauth/authorize" `withQuery` [("response_type", "code"), scopeParam " " scopes] - , oauthAccessTokenEndpoint = "https://login.eveonline.com/oauth/token" - , oauthCallback = Nothing + , oauth2TokenEndpoint = "https://login.eveonline.com/oauth/token" + , oauth2RedirectUri = Nothing } diff --git a/src/Yesod/Auth/OAuth2/GitHub.hs b/src/Yesod/Auth/OAuth2/GitHub.hs index effeccc..d5bd7f0 100644 --- a/src/Yesod/Auth/OAuth2/GitHub.hs +++ b/src/Yesod/Auth/OAuth2/GitHub.hs @@ -46,12 +46,12 @@ oauth2GitHubScoped scopes clientId clientSecret = } where oauth2 = OAuth2 - { oauthClientId = clientId - , oauthClientSecret = Just clientSecret - , oauthOAuthorizeEndpoint = + { oauth2ClientId = clientId + , oauth2ClientSecret = Just clientSecret + , oauth2AuthorizeEndpoint = "https://github.com/login/oauth/authorize" `withQuery` [scopeParam "," scopes] - , oauthAccessTokenEndpoint = + , oauth2TokenEndpoint = "https://github.com/login/oauth/access_token" - , oauthCallback = Nothing + , oauth2RedirectUri = Nothing } diff --git a/src/Yesod/Auth/OAuth2/GitLab.hs b/src/Yesod/Auth/OAuth2/GitLab.hs index c0b136f..2910253 100644 --- a/src/Yesod/Auth/OAuth2/GitLab.hs +++ b/src/Yesod/Auth/OAuth2/GitLab.hs @@ -53,12 +53,12 @@ oauth2GitLabHostScopes host scopes clientId clientSecret = } where oauth2 = OAuth2 - { oauthClientId = clientId - , oauthClientSecret = Just clientSecret - , oauthOAuthorizeEndpoint = + { oauth2ClientId = clientId + , oauth2ClientSecret = Just clientSecret + , oauth2AuthorizeEndpoint = host `withPath` "/oauth/authorize" `withQuery` [scopeParam " " scopes] - , oauthAccessTokenEndpoint = host `withPath` "/oauth/token" - , oauthCallback = Nothing + , oauth2TokenEndpoint = host `withPath` "/oauth/token" + , oauth2RedirectUri = Nothing } diff --git a/src/Yesod/Auth/OAuth2/Google.hs b/src/Yesod/Auth/OAuth2/Google.hs index 4544d68..68baaff 100644 --- a/src/Yesod/Auth/OAuth2/Google.hs +++ b/src/Yesod/Auth/OAuth2/Google.hs @@ -74,12 +74,12 @@ oauth2GoogleScopedWidget widget scopes clientId clientSecret = } where oauth2 = OAuth2 - { oauthClientId = clientId - , oauthClientSecret = Just clientSecret - , oauthOAuthorizeEndpoint = + { oauth2ClientId = clientId + , oauth2ClientSecret = Just clientSecret + , oauth2AuthorizeEndpoint = "https://accounts.google.com/o/oauth2/auth" `withQuery` [scopeParam " " scopes] - , oauthAccessTokenEndpoint = + , oauth2TokenEndpoint = "https://www.googleapis.com/oauth2/v3/token" - , oauthCallback = Nothing + , oauth2RedirectUri = Nothing } diff --git a/src/Yesod/Auth/OAuth2/Nylas.hs b/src/Yesod/Auth/OAuth2/Nylas.hs index df2d8d1..edc729c 100644 --- a/src/Yesod/Auth/OAuth2/Nylas.hs +++ b/src/Yesod/Auth/OAuth2/Nylas.hs @@ -51,9 +51,9 @@ oauth2Nylas clientId clientSecret = $ eitherDecode userResponse where oauth = OAuth2 - { oauthClientId = clientId - , oauthClientSecret = Just clientSecret - , oauthOAuthorizeEndpoint = + { oauth2ClientId = clientId + , oauth2ClientSecret = Just clientSecret + , oauth2AuthorizeEndpoint = "https://api.nylas.com/oauth/authorize" `withQuery` [ ("response_type", "code") , ( "client_id" @@ -64,6 +64,6 @@ oauth2Nylas clientId clientSecret = -- its current state, it doesn't matter because it's only one scope. , scopeParam "," defaultScopes ] - , oauthAccessTokenEndpoint = "https://api.nylas.com/oauth/token" - , oauthCallback = Nothing + , oauth2TokenEndpoint = "https://api.nylas.com/oauth/token" + , oauth2RedirectUri = Nothing } diff --git a/src/Yesod/Auth/OAuth2/Prelude.hs b/src/Yesod/Auth/OAuth2/Prelude.hs index 3e190f5..5256da7 100644 --- a/src/Yesod/Auth/OAuth2/Prelude.hs +++ b/src/Yesod/Auth/OAuth2/Prelude.hs @@ -54,8 +54,7 @@ module Yesod.Auth.OAuth2.Prelude -- * Temporary, until I finish re-structuring modules , authOAuth2 , authOAuth2Widget - ) -where + ) where import Control.Exception.Safe import Data.Aeson @@ -65,7 +64,7 @@ import Data.Text (Text) 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 diff --git a/src/Yesod/Auth/OAuth2/Salesforce.hs b/src/Yesod/Auth/OAuth2/Salesforce.hs index ced442c..5543eba 100644 --- a/src/Yesod/Auth/OAuth2/Salesforce.hs +++ b/src/Yesod/Auth/OAuth2/Salesforce.hs @@ -73,10 +73,10 @@ salesforceHelper name profileUri authorizeUri tokenUri scopes clientId clientSec } where oauth2 = OAuth2 - { oauthClientId = clientId - , oauthClientSecret = Just clientSecret - , oauthOAuthorizeEndpoint = + { oauth2ClientId = clientId + , oauth2ClientSecret = Just clientSecret + , oauth2AuthorizeEndpoint = authorizeUri `withQuery` [scopeParam " " scopes] - , oauthAccessTokenEndpoint = tokenUri - , oauthCallback = Nothing + , oauth2TokenEndpoint = tokenUri + , oauth2RedirectUri = Nothing } diff --git a/src/Yesod/Auth/OAuth2/Slack.hs b/src/Yesod/Auth/OAuth2/Slack.hs index f555961..65f211a 100644 --- a/src/Yesod/Auth/OAuth2/Slack.hs +++ b/src/Yesod/Auth/OAuth2/Slack.hs @@ -65,11 +65,11 @@ oauth2SlackScoped scopes clientId clientSecret = $ eitherDecode userResponse where oauth2 = OAuth2 - { oauthClientId = clientId - , oauthClientSecret = Just clientSecret - , oauthOAuthorizeEndpoint = + { oauth2ClientId = clientId + , oauth2ClientSecret = Just clientSecret + , oauth2AuthorizeEndpoint = "https://slack.com/oauth/authorize" `withQuery` [scopeParam "," $ map scopeText scopes] - , oauthAccessTokenEndpoint = "https://slack.com/api/oauth.access" - , oauthCallback = Nothing + , oauth2TokenEndpoint = "https://slack.com/api/oauth.access" + , oauth2RedirectUri = Nothing } diff --git a/src/Yesod/Auth/OAuth2/Spotify.hs b/src/Yesod/Auth/OAuth2/Spotify.hs index f178b47..498aa47 100644 --- a/src/Yesod/Auth/OAuth2/Spotify.hs +++ b/src/Yesod/Auth/OAuth2/Spotify.hs @@ -34,11 +34,11 @@ oauth2Spotify scopes clientId clientSecret = } where oauth2 = OAuth2 - { oauthClientId = clientId - , oauthClientSecret = Just clientSecret - , oauthOAuthorizeEndpoint = + { oauth2ClientId = clientId + , oauth2ClientSecret = Just clientSecret + , oauth2AuthorizeEndpoint = "https://accounts.spotify.com/authorize" `withQuery` [scopeParam " " scopes] - , oauthAccessTokenEndpoint = "https://accounts.spotify.com/api/token" - , oauthCallback = Nothing + , oauth2TokenEndpoint = "https://accounts.spotify.com/api/token" + , oauth2RedirectUri = Nothing } diff --git a/src/Yesod/Auth/OAuth2/Upcase.hs b/src/Yesod/Auth/OAuth2/Upcase.hs index f1b17c2..8da9e25 100644 --- a/src/Yesod/Auth/OAuth2/Upcase.hs +++ b/src/Yesod/Auth/OAuth2/Upcase.hs @@ -41,9 +41,9 @@ oauth2Upcase clientId clientSecret = } where oauth2 = OAuth2 - { oauthClientId = clientId - , oauthClientSecret = Just clientSecret - , oauthOAuthorizeEndpoint = "http://upcase.com/oauth/authorize" - , oauthAccessTokenEndpoint = "http://upcase.com/oauth/token" - , oauthCallback = Nothing + { oauth2ClientId = clientId + , oauth2ClientSecret = Just clientSecret + , oauth2AuthorizeEndpoint = "http://upcase.com/oauth/authorize" + , oauth2TokenEndpoint = "http://upcase.com/oauth/token" + , oauth2RedirectUri = Nothing } diff --git a/src/Yesod/Auth/OAuth2/WordPressDotCom.hs b/src/Yesod/Auth/OAuth2/WordPressDotCom.hs index 7dd8dc8..adf825a 100644 --- a/src/Yesod/Auth/OAuth2/WordPressDotCom.hs +++ b/src/Yesod/Auth/OAuth2/WordPressDotCom.hs @@ -37,12 +37,12 @@ oauth2WordPressDotCom clientId clientSecret = where oauth2 = OAuth2 - { oauthClientId = clientId - , oauthClientSecret = Just clientSecret - , oauthOAuthorizeEndpoint = + { oauth2ClientId = clientId + , oauth2ClientSecret = Just clientSecret + , oauth2AuthorizeEndpoint = "https://public-api.wordpress.com/oauth2/authorize" `withQuery` [scopeParam "," ["auth"]] - , oauthAccessTokenEndpoint = + , oauth2TokenEndpoint = "https://public-api.wordpress.com/oauth2/token" - , oauthCallback = Nothing + , oauth2RedirectUri = Nothing } diff --git a/stack-hoauth2-2.0.yaml b/stack-hoauth2-2.0.yaml new file mode 100644 index 0000000..44cc6cb --- /dev/null +++ b/stack-hoauth2-2.0.yaml @@ -0,0 +1,3 @@ +resolver: lts-18.23 +extra-deps: + - hoauth2-2.0.0@sha256:4686d776272d4c57d3c8dbeb9e58b04afe4d2b410382011bd78a3d2bfb08a3fe,5662 diff --git a/stack-hoauth2-2.0.yaml.lock b/stack-hoauth2-2.0.yaml.lock new file mode 100644 index 0000000..2bb99b0 --- /dev/null +++ b/stack-hoauth2-2.0.yaml.lock @@ -0,0 +1,19 @@ +# This file was autogenerated by Stack. +# You should not edit this file by hand. +# For more information, please see the documentation at: +# https://docs.haskellstack.org/en/stable/lock_files + +packages: +- completed: + hackage: hoauth2-2.0.0@sha256:4686d776272d4c57d3c8dbeb9e58b04afe4d2b410382011bd78a3d2bfb08a3fe,5662 + pantry-tree: + size: 2171 + sha256: 291b3dd90854ef44f270519ec17e34b6778f8430f6d6517bd67b0128bd549553 + original: + hackage: hoauth2-2.0.0@sha256:4686d776272d4c57d3c8dbeb9e58b04afe4d2b410382011bd78a3d2bfb08a3fe,5662 +snapshots: +- completed: + size: 587819 + url: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/lts/18/23.yaml + sha256: 7f69bb29a57495586e7e3ed31ecc59c0d2c959cb23bd52b71ca676f254c9beb1 + original: lts-18.23 diff --git a/stack.yaml b/stack.yaml index 95ed52c..a5e4e03 100644 --- a/stack.yaml +++ b/stack.yaml @@ -1 +1 @@ -resolver: lts-17.4 +resolver: lts-18.23 diff --git a/stack.yaml.lock b/stack.yaml.lock index 108ab08..678fbff 100644 --- a/stack.yaml.lock +++ b/stack.yaml.lock @@ -6,7 +6,7 @@ packages: [] snapshots: - completed: - size: 563103 - url: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/lts/17/4.yaml - sha256: f11e2153044f5f71ea7b1c9398f4721f517c9bd37642ed769647b896564021f3 - original: lts-17.4 + size: 587819 + url: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/lts/18/23.yaml + sha256: 7f69bb29a57495586e7e3ed31ecc59c0d2c959cb23bd52b71ca676f254c9beb1 + original: lts-18.23 diff --git a/yesod-auth-oauth2.cabal b/yesod-auth-oauth2.cabal index 2b2b5bc..d1b53c3 100644 --- a/yesod-auth-oauth2.cabal +++ b/yesod-auth-oauth2.cabal @@ -1,10 +1,10 @@ cabal-version: 1.12 --- This file has been generated from package.yaml by hpack version 0.33.0. +-- This file has been generated from package.yaml by hpack version 0.34.4. -- -- see: https://github.com/sol/hpack -- --- hash: 1c0ae94778ce803bde4726d2be1e60cd5dcb94f8e34b7cefbbae7dafb30d1dea +-- hash: 5f7443ec90d4a2884d1d8816ec553f50fe303c51a6d8ee956fc8d62b49333e60 name: yesod-auth-oauth2 version: 0.6.3.4 @@ -35,6 +35,7 @@ flag example library exposed-modules: + Network.OAuth.OAuth2.Compat UnliftIO.Except URI.ByteString.Extension Yesod.Auth.OAuth2