hoauth2 1.7.2 → 1.8.0
raw patch · 16 files changed
+63/−83 lines, 16 filesdep ~aesondep ~binarydep ~exceptionsPVP ok
version bump matches the API change (PVP)
Dependency ranges changed: aeson, binary, exceptions, mustache, scotty, unordered-containers, wai-extra, wai-middleware-static
API changes (from Hackage documentation)
Files
- README.md +10/−1
- example/IDP/Douban.hs +0/−1
- example/IDP/Dropbox.hs +0/−1
- example/IDP/Facebook.hs +0/−1
- example/IDP/Github.hs +0/−1
- example/IDP/Google.hs +0/−1
- example/IDP/Okta.hs +0/−1
- example/IDP/StackExchange.hs +0/−1
- example/IDP/Weibo.hs +0/−1
- example/Keys.hs +35/−57
- example/README.md +2/−1
- example/Types.hs +3/−1
- hoauth2.cabal +10/−10
- src/Network/OAuth/OAuth2/AuthorizationRequest.hs +0/−1
- src/Network/OAuth/OAuth2/Internal.hs +3/−3
- src/Network/OAuth/OAuth2/TokenRequest.hs +0/−1
README.md view
@@ -1,8 +1,17 @@ [](http://travis-ci.org/freizl/hoauth2) [](https://hackage.haskell.org/package/hoauth2)+ # Introduction -A lightweight oauth2 haskell binding. See examples in `example/` folder.+A lightweight oauth2 haskell binding.++# Build example app++- `make create-keys`+- check the `example/Keys.hs` to make sure it's config correctly for the IdP you're going to test. (client id, client secret, oauth Urls etc)+- `make build`+- `make demo`+- open <http://localhost:9988> # Contribute
example/IDP/Douban.hs view
@@ -4,7 +4,6 @@ module IDP.Douban where import Data.Aeson-import Data.Aeson.Types import Data.Bifunctor import Data.Hashable import Data.Text.Lazy (Text)
example/IDP/Dropbox.hs view
@@ -4,7 +4,6 @@ module IDP.Dropbox where import Data.Aeson-import Data.Aeson.Types import Data.Bifunctor import Data.Hashable import Data.Text.Lazy (Text)
example/IDP/Facebook.hs view
@@ -4,7 +4,6 @@ module IDP.Facebook where import Data.Aeson-import Data.Aeson.Types import Data.Bifunctor import Data.Hashable import Data.Text.Lazy (Text)
example/IDP/Github.hs view
@@ -4,7 +4,6 @@ module IDP.Github where import Data.Aeson-import Data.Aeson.Types import Data.Bifunctor import Data.Hashable import Data.Text.Lazy (Text)
example/IDP/Google.hs view
@@ -4,7 +4,6 @@ module IDP.Google where import Data.Aeson-import Data.Aeson.Types import Data.Bifunctor import Data.Hashable import Data.Text.Lazy (Text)
example/IDP/Okta.hs view
@@ -4,7 +4,6 @@ module IDP.Okta where import Data.Aeson-import Data.Aeson.Types import Data.Bifunctor import Data.Hashable import Data.Text.Lazy (Text)
example/IDP/StackExchange.hs view
@@ -8,7 +8,6 @@ -} module IDP.StackExchange where import Data.Aeson-import Data.Aeson.Types import Data.Bifunctor import Data.ByteString (ByteString) import Data.Hashable
example/IDP/Weibo.hs view
@@ -4,7 +4,6 @@ module IDP.Weibo where import Data.Aeson-import Data.Aeson.Types import Data.Bifunctor import Data.Hashable import Data.Text.Lazy (Text)
example/Keys.hs view
@@ -8,101 +8,79 @@ import URI.ByteString.QQ weiboKey :: OAuth2-weiboKey = OAuth2 { oauthClientId = "1962132691"- , oauthClientSecret = "a2ad30383bdff9bcb12be6a3d30deeb1"- , oauthCallback = Just [uri|http://127.0.0.1:9988/oauth2/callback|]- , oauthOAuthorizeEndpoint = [uri|https://api.weibo.com/oauth2/authorize|]- , oauthAccessTokenEndpoint = [uri|https://api.weibo.com/oauth2/access_token|]- }+weiboKey = OAuth2 { oauthClientId = "xxxxxxxxxxxxxxx"+ , oauthClientSecret = "xxxxxxxxxxxxxxxxxxxxxx"+ , oauthCallback = Just [uri|http://127.0.0.1:9988/oauthCallback|]+ , oauthOAuthorizeEndpoint = [uri|https://api.weibo.com/oauth2/authorize|]+ , oauthAccessTokenEndpoint = [uri|https://api.weibo.com/oauth2/access_token|]+ } -- | http://developer.github.com/v3/oauth/ githubKey :: OAuth2-githubKey = OAuth2 { oauthClientId = "bf86d338485a96a93c88"- , oauthClientSecret = "a1c00dada665dc00aa6fafe0495c7c885f82d1ce"- , oauthCallback = Just [uri|http://127.0.0.1:9988/oauth2/callback|]- , oauthOAuthorizeEndpoint = [uri|https://github.com/login/oauth/authorize|]- , oauthAccessTokenEndpoint = [uri|https://github.com/login/oauth/access_token|]- }+githubKey = OAuth2 { oauthClientId = "xxxxxxxxxxxxxxx"+ , oauthClientSecret = "xxxxxxxxxxxxxxxxxxxxxx"+ , oauthCallback = Just [uri|http://127.0.0.1:9988/githubCallback|]+ , oauthOAuthorizeEndpoint = [uri|https://github.com/login/oauth/authorize|]+ , oauthAccessTokenEndpoint = [uri|https://github.com/login/oauth/access_token|]+ } -- | oauthCallback = Just "https://developers.google.com/oauthplayground" googleKey :: OAuth2-googleKey = OAuth2 { oauthClientId = "886894027376.apps.googleusercontent.com"- , oauthClientSecret = "27w98gwGB1h8N5a6JQ2bT_nm"- , oauthCallback = Just [uri|http://127.0.0.1:9988/oauth2/callback|]+googleKey = OAuth2 { oauthClientId = "xxxxxxxxxxxxxxx.apps.googleusercontent.com"+ , oauthClientSecret = "xxxxxxxxxxxxxxxxxxxxxx"+ , oauthCallback = Just [uri|http://127.0.0.1:9988/googleCallback|] , oauthOAuthorizeEndpoint = [uri|https://accounts.google.com/o/oauth2/auth|] , oauthAccessTokenEndpoint = [uri|https://www.googleapis.com/oauth2/v3/token|] } -{--googleServiceAccount :: GoogleServiceAccount-googleServiceAccount = GoogleServiceAccount- { saPrivateKey = "-----BEGIN PRIVATE KEY-----\nMIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDfu/z7ASRGrQus\ngWABWNX/EKgE8NlEUoHUeDWCTpXVj6PmiEDGyRaBNqR+6fQmwBMD/ItpISTGT31/\nfdqhKAdJOaYGNvWNYxx1uWYm0HP1YU7OkfFt8YgROu8gGz7+mdseXs/3bMhjlbk9\nPKmBiU46VRFWn7QaAp9YiVGghZp/LcawC+urmWdYnpkl+P4C4u+YtszmCMql842M\nT4nK8jlraxvUT/XM+97UXKwiGL8sPiPKGEthAFiXHNRVgnDibnJ2Etw7zPbZ6FB+\nvHL1SkuSnE7C358RTkuz56Tvf6ETgOGDIJ9HpZlgT6hrsWcAOh8UZ34Q5QzinhtP\n5BdgQxnjAgMBAAECggEBAJqfxFYA0v5ZZ+D/xMcJi1PtQgGwJqf2Ua3yqiB1iU4A\nKKkRb5syrG/+wK7Jp6gEROATcJHmixDXLQeohimsjWSJB/nxj8D4R1oBGN0oYYur\nhZhz+qQeMgieb1cEHYQ99tbFdfss3k0c09nDi+5vY3YjBomUdBcpytCYjqZez4im\nYoZjA6ijb5BduCQO2YOJpjiHbSrTV05Zr/xfHgafkbRx04jHA7OdJM6x5giRcMBn\n5BYNGPUkM6mGpeTeCZjTsOqvXcckuyR8P4wzoG3J8grnXgGR17d829t0bi5X/Jym\nwj5707lvIqu+WcfUfXDDYkZNhe5S9PWpT1uqaOGWElECgYEA738wclTGRNboYLsx\noT6HCOEKNFiY/4DMV65nugSnHBIl4amLwm4+0v669F8F28U2xhihp+RfPC4Fjd62\nfJ9hlYg6NiEqReJfXhs5OcvMBjmBFUR046/kOGyEj6D2yn3LTXoiWI8tHaS0Ucmu\nwF4Lp0/Rk/ofQrFB7q1a0OBeTakCgYEA7ya+IMo0t4lRYl+x8A7ouuJwnK1VjkkC\nkloCAEsnVznb2BsHJCsF0fPPU3f+kqhYqD0qQCfbwhYGragt603a/BqXnnQyE9T/\nnLqSGgctY/Xr06HbOr+aZ4QLKsTfD6IkTC82WAJD3J8hptLaqqDMORluI6xchKEL\nNUV8uvX7qqsCgYEAtKo/w5+LyZZMydusfrSKbPpGFmLXV7azb1lTShIEdbqC9Q5P\nLaa4obYjFgEwjC7jOOCP4fT2mpElA3aENtKMbJ7NOtQd7YXs5zKmIqFIEVIDvCVd\n//xJrv69qROF2A649IMzsZagNAJxPFlmCBtpsxcVRAmk10ycLg57uaHnwbECgYEA\nrtqn1rehVbQ74e5P3lI4TTP03ElLra2qCLFwlyBb0kXGfLo+PW6LYdeedcvdQQN/\nVvrpomDCJ6UNGvlFIa8Z9ovG4Z7ZYnCwt7odypQG1vhehazo6ope7WK4+3tYEEkf\nuugmFrEJRwy+gQfXwzuwNetnAQQr3PkWhcuZh+UELeMCgYAPoQK1LETBLFsUBWhh\nHc5VrnQBykn9GMRPXKR4pq5MK8p8o2QwfL5hNlZNeTKPWdP0QtMuIH9gxRuqvbrF\nXEO8RmZmoNtznh/Ax7+S62g72iLzF1/C8j3g8hWJUeGlU8LAJsZVTSma3t/vEQZM\nQqydJfwXJMTkh4nslALJZ9S4bw==\n-----END PRIVATE KEY-----\n"- , saEmail = "testoauth2sa@api-project-886894027376.iam.gserviceaccount.com"- , saScope = [ "https://www.googleapis.com/auth/prediction"- , "https://www.googleapis.com/auth/drive"- ]- , saAuthEndpoint = "https://www.googleapis.com/oauth2/v4/token"- , saExpireTime = Nothing- , saDelegateEmail = Nothing- }--}- facebookKey :: OAuth2-facebookKey = OAuth2 { oauthClientId = "414630782030965"- , oauthClientSecret = "0e648eae100da4d03f16594f231fc1d0"- , oauthCallback = Just [uri|http://localhost:9988/oauth2/callback|]+facebookKey = OAuth2 { oauthClientId = "xxxxxxxxxxxxxxx"+ , oauthClientSecret = "xxxxxxxxxxxxxxxxxxxxxx"+ , oauthCallback = Just [uri|http://t.haskellcn.org/cb|] , oauthOAuthorizeEndpoint = [uri|https://www.facebook.com/dialog/oauth|]- , oauthAccessTokenEndpoint = [uri|https://graph.facebook.com/v2.12/oauth/access_token|]+ , oauthAccessTokenEndpoint = [uri|https://graph.facebook.com/v2.3/oauth/access_token|] } doubanKey :: OAuth2-doubanKey = OAuth2 { oauthClientId = "02a914cf299ca31607fb3e6d7cd5e942"- , oauthClientSecret = "3c0fdef13b0dd271"- , oauthCallback = Just [uri|http://localhost:9988/oauth2/callback|]+doubanKey = OAuth2 { oauthClientId = "xxxxxxxxxxxxxxx"+ , oauthClientSecret = "xxxxxxxxxxxxxxxxxxxxxx"+ , oauthCallback = Just [uri|http://localhost:9999/oauthCallback|] , oauthOAuthorizeEndpoint = [uri|https://www.douban.com/service/auth2/auth|] , oauthAccessTokenEndpoint = [uri|https://www.douban.com/service/auth2/token|] } fitbitKey :: OAuth2-fitbitKey = OAuth2 { oauthClientId = "229LN9"- , oauthClientSecret = "2f4aa9a275c2d4bb9eb616efbd2c1311"+fitbitKey = OAuth2 { oauthClientId = "xxxxxx"+ , oauthClientSecret = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" , oauthCallback = Just [uri|http://localhost:9988/oauth2/callback|] , oauthOAuthorizeEndpoint = [uri|https://www.fitbit.com/oauth2/authorize|] , oauthAccessTokenEndpoint = [uri|https://api.fitbit.com/oauth2/token|] } +-- fix key from your application edit page+-- https://stackapps.com/apps/oauth stackexchangeAppKey :: ByteString-stackexchangeAppKey = "LZvAveRFYw8lgNluEU2pDQ(("+stackexchangeAppKey = "xxxxxx" stackexchangeKey :: OAuth2-stackexchangeKey = OAuth2 { oauthClientId = "7185"- , oauthClientSecret = "K5hK)ET*dbFGFmNFVtqIyA(("- , oauthCallback = Just [uri|http://localhost:9988/oauth2/callback|]+stackexchangeKey = OAuth2 { oauthClientId = "xx"+ , oauthClientSecret = "xxxxxxxxxxxxxxx"+ , oauthCallback = Just [uri|http://c.haskellcn.org/cb|] , oauthOAuthorizeEndpoint = [uri|https://stackexchange.com/oauth|]- , oauthAccessTokenEndpoint = [uri|https://stackexchange.com/oauth/access_token/json|]+ , oauthAccessTokenEndpoint = [uri|https://stackexchange.com/oauth/access_token|] }- dropboxKey :: OAuth2-dropboxKey = OAuth2 { oauthClientId = "zbyxxox19gz6dgg"- , oauthClientSecret = "ihhui0ysp85oi8s"+dropboxKey = OAuth2 { oauthClientId = "xxx"+ , oauthClientSecret = "xxx" , oauthCallback = Just [uri|http://localhost:9988/oauth2/callback|] , oauthOAuthorizeEndpoint = [uri|https://www.dropbox.com/1/oauth2/authorize|] , oauthAccessTokenEndpoint = [uri|https://api.dropboxapi.com/oauth2/token|] } oktaKey :: OAuth2-oktaKey = OAuth2 { oauthClientId = "0oad3popatwUIhWV40h7"- , oauthClientSecret = "YFqXRjtsy7IYRbueiG2tcgHzhaawLccxqq5ruPfN"+oktaKey = OAuth2 { oauthClientId = "xxx"+ , oauthClientSecret = "xxx" , oauthCallback = Just [uri|http://localhost:9988/oauth2/callback|] , oauthOAuthorizeEndpoint = [uri|https://dev-148986.oktapreview.com/oauth2/v1/authorize|] , oauthAccessTokenEndpoint = [uri|https://dev-148986.oktapreview.com/oauth2/v1/token|] }--linkedinKey :: OAuth2-linkedinKey = OAuth2 { oauthClientId = "86r7dx3b0piy56"- , oauthClientSecret = "lBb5kA5lpggHT0Ne"- , oauthCallback = Just [uri|http://localhost:9988/oauth2/callback|]- , oauthOAuthorizeEndpoint = [uri|https://www.linkedin.com/oauth/v2/authorization|]- , oauthAccessTokenEndpoint = [uri|https://www.linkedin.com/oauth/v2/accessToken|]- }-
example/README.md view
@@ -1,3 +1,4 @@+ * IDPs - douban: http://developers.douban.com/wiki/?title=oauth2 - Google: <https://developers.google.com/accounts/docs/OAuth2WebServer>@@ -9,5 +10,5 @@ - DropBox: <https://www.dropbox.com/developers/reference/oauth-guide> - Weibo: <http://open.weibo.com/wiki/Oauth2> -** Linkedin+* WIP: Linkedin - <https://developer.linkedin.com>
example/Types.hs view
@@ -9,7 +9,6 @@ import Control.Concurrent.MVar import Data.Aeson-import Data.Aeson.Types import Data.Hashable import qualified Data.HashMap.Strict as Map import Data.Maybe@@ -45,6 +44,9 @@ class (IDP a) => HasUserReq a where userReq :: FromJSON b => a -> Manager -> AccessToken -> IO (OAuth2Result b LoginUser) +-- Heterogenous collections+-- https://wiki.haskell.org/Heterogenous_collections+-- data IDPApp = forall a. (IDP a, HasTokenReq a, HasUserReq a, HasLabel a, HasAuthUri a) => IDPApp a -- dummy oauth2 request error
hoauth2.cabal view
@@ -1,6 +1,6 @@ Name: hoauth2 -- http://wiki.haskell.org/Package_versioning_policy-Version: 1.7.2+Version: 1.8.0 Synopsis: Haskell OAuth2 authentication client @@ -77,12 +77,12 @@ bytestring >= 0.9 && < 0.11, http-conduit >= 2.1 && < 2.4, http-types >= 0.11 && < 0.13,- aeson >= 0.11 && < 1.4,+ aeson >= 1.0.0.0 && < 1.4, unordered-containers >= 0.2.5, uri-bytestring >= 0.2.3.1 && < 0.4, uri-bytestring-aeson >= 0.1 && < 0.2, microlens >= 0.4.0 && < 0.5,- exceptions >= 0.8.3 && < 0.10+ exceptions >= 0.8.3 && < 0.11 if impl(ghc >= 6.12.0) ghc-options: -Wall -fwarn-tabs -funbox-strict-fields@@ -125,15 +125,15 @@ wai >= 3.2 && < 3.3, warp >= 3.2 && < 3.3, containers >= 0.4 && < 0.6,- aeson >= 0.11 && < 1.4,+ aeson >= 1.0.0.0 && < 1.4, microlens >= 0.4.0 && < 0.5,- unordered-containers >= 0.2.8 && < 0.2.9,- wai-extra >= 3.0.21.0 && < 3.0.22.0,- wai-middleware-static == 0.8.1,- mustache >= 2.2.3 && < 2.3.0,+ unordered-containers >= 0.2.8 && < 0.2.10,+ wai-extra >= 3.0.21.0 && < 3.0.25.0,+ wai-middleware-static >= 0.8.1 && < 0.8.3,+ mustache >= 2.2.3 && < 2.4.0, mtl >= 2.2.1 && < 2.3,- scotty == 0.10.0,- binary >= 0.8.3.0 && < 0.8.5,+ scotty >= 0.10.0 && < 0.12,+ binary >= 0.8.3.0 && < 0.8.6, parsec >= 3.1.11 && < 3.2.0 , hashable >= 1.2.6 && < 1.3.0, hoauth2
src/Network/OAuth/OAuth2/AuthorizationRequest.hs view
@@ -3,7 +3,6 @@ module Network.OAuth.OAuth2.AuthorizationRequest where import Data.Aeson-import Data.Aeson.Types import GHC.Generics instance FromJSON Errors where
src/Network/OAuth/OAuth2/Internal.hs view
@@ -14,11 +14,9 @@ import Control.Arrow (second) import Control.Monad.Catch import Data.Aeson-import Data.Aeson.Types import qualified Data.ByteString as BS import qualified Data.ByteString.Lazy as BSL import Data.Maybe-import Data.Monoid import Data.Text (Text, pack) import Data.Text.Encoding import GHC.Generics@@ -64,6 +62,7 @@ instance FromJSON OAuth2Token where parseJSON = genericParseJSON defaultOptions { fieldLabelModifier = camelTo2 '_' } instance ToJSON OAuth2Token where+ toJSON = genericToJSON defaultOptions { fieldLabelModifier = camelTo2 '_' } toEncoding = genericToEncoding defaultOptions { fieldLabelModifier = camelTo2 '_' } data OAuth2Error a =@@ -83,6 +82,7 @@ parseJSON _ = fail "Expected an object" instance ToJSON err => ToJSON (OAuth2Error err) where+ toJSON = genericToJSON defaultOptions { constructorTagModifier = camelTo2 '_', allNullaryToStringTag = True } toEncoding = genericToEncoding defaultOptions { constructorTagModifier = camelTo2 '_', allNullaryToStringTag = True } parseOAuth2Error :: FromJSON err => BSL.ByteString -> OAuth2Error err@@ -135,7 +135,7 @@ accessTokenUrl' oa code gt = (uri, body) where uri = oauthAccessTokenEndpoint oa body = catMaybes [ Just ("code", encodeUtf8 $ extoken code)- , (("redirect_uri",) . serializeURIRef') <$> oauthCallback oa+ , ("redirect_uri",) . serializeURIRef' <$> oauthCallback oa , fmap (("grant_type",) . encodeUtf8) gt ]
src/Network/OAuth/OAuth2/TokenRequest.hs view
@@ -3,7 +3,6 @@ module Network.OAuth.OAuth2.TokenRequest where import Data.Aeson-import Data.Aeson.Types import GHC.Generics instance FromJSON Errors where