yesod-auth-oauth2 0.7.0.1 → 0.7.0.2
raw patch · 5 files changed
+183/−60 lines, 5 filesPVP: minor bump suggested
API additions: PVP suggests at least a minor version bump
API changes (from Hackage documentation)
+ Yesod.Auth.OAuth2.Auth0: defaultAuth0Scopes :: [Text]
+ Yesod.Auth.OAuth2.Auth0: instance Data.Aeson.Types.FromJSON.FromJSON Yesod.Auth.OAuth2.Auth0.User
+ Yesod.Auth.OAuth2.Auth0: oauth2Auth0Host :: YesodAuth m => URI -> Text -> Text -> AuthPlugin m
+ Yesod.Auth.OAuth2.Auth0: oauth2Auth0HostScopes :: YesodAuth m => URI -> [Text] -> Text -> Text -> AuthPlugin m
+ Yesod.Auth.OAuth2.Twitch: instance Data.Aeson.Types.FromJSON.FromJSON Yesod.Auth.OAuth2.Twitch.User
+ Yesod.Auth.OAuth2.Twitch: oauth2Twitch :: YesodAuth m => Text -> Text -> AuthPlugin m
+ Yesod.Auth.OAuth2.Twitch: oauth2TwitchScoped :: YesodAuth m => [Text] -> Text -> Text -> AuthPlugin m
Files
- CHANGELOG.md +4/−2
- example/Main.hs +53/−46
- src/Yesod/Auth/OAuth2/Auth0.hs +56/−0
- src/Yesod/Auth/OAuth2/Twitch.hs +56/−0
- yesod-auth-oauth2.cabal +14/−12
CHANGELOG.md view
@@ -1,6 +1,8 @@-## [_Unreleased_](https://github.com/thoughtbot/yesod-auth-oauth2/compare/v0.7.0.1...main)+## [_Unreleased_](https://github.com/thoughtbot/yesod-auth-oauth2/compare/v0.7.0.2...main) -None+## [v0.7.0.2](https://github.com/thoughtbot/yesod-auth-oauth2/compare/v0.7.0.1...v0.7.0.2)++- Add Auth0 provider ([@hw202207](https://github.com/freckle/yesod-auth-oauth2/pull/162)) ## [v0.7.0.1](https://github.com/thoughtbot/yesod-auth-oauth2/compare/v0.7.0.0...v0.7.0.1)
example/Main.hs view
@@ -26,6 +26,7 @@ import Data.ByteString.Lazy (fromStrict, toStrict) import qualified Data.Map as M import Data.Maybe (fromJust)+import Data.String (IsString(fromString)) import Data.Text (Text) import qualified Data.Text as T import Data.Text.Encoding (decodeUtf8)@@ -35,6 +36,7 @@ import System.Environment (getEnv) import Yesod import Yesod.Auth+import Yesod.Auth.OAuth2.Auth0 import Yesod.Auth.OAuth2.AzureAD import Yesod.Auth.OAuth2.BattleNet import Yesod.Auth.OAuth2.Bitbucket@@ -47,13 +49,14 @@ import Yesod.Auth.OAuth2.Salesforce import Yesod.Auth.OAuth2.Slack import Yesod.Auth.OAuth2.Spotify+import Yesod.Auth.OAuth2.Twitch import Yesod.Auth.OAuth2.Upcase import Yesod.Auth.OAuth2.WordPressDotCom data App = App- { appHttpManager :: Manager- , appAuthPlugins :: [AuthPlugin App]- }+ { appHttpManager :: Manager+ , appAuthPlugins :: [AuthPlugin App]+ } mkYesod "App" [parseRoutes| / RootR GET@@ -62,28 +65,28 @@ instance Yesod App where -- see https://github.com/thoughtbot/yesod-auth-oauth2/issues/87- approot = ApprootStatic "http://localhost:3000"+ approot = ApprootStatic "http://localhost:3000" instance YesodAuth App where- type AuthId App = Text- loginDest _ = RootR- logoutDest _ = RootR+ type AuthId App = Text+ loginDest _ = RootR+ logoutDest _ = RootR - -- Disable any attempt to read persisted authenticated state- maybeAuthId = return Nothing+ -- Disable any attempt to read persisted authenticated state+ maybeAuthId = return Nothing - -- Copy the Creds response into the session for viewing after- authenticate c = do- mapM_ (uncurry setSession)- $ [("credsIdent", credsIdent c), ("credsPlugin", credsPlugin c)]- ++ credsExtra c+ -- Copy the Creds response into the session for viewing after+ authenticate c = do+ mapM_ (uncurry setSession)+ $ [("credsIdent", credsIdent c), ("credsPlugin", credsPlugin c)]+ ++ credsExtra c - return $ Authenticated "1"+ return $ Authenticated "1" - authPlugins = appAuthPlugins+ authPlugins = appAuthPlugins instance RenderMessage App FormMessage where- renderMessage _ _ = defaultFormMessage+ renderMessage _ _ = defaultFormMessage -- brittany-disable-next-binding @@ -126,37 +129,41 @@ mkFoundation :: IO App mkFoundation = do- loadEnv+ loadEnv - appHttpManager <- newManager tlsManagerSettings- appAuthPlugins <- sequence- -- When Providers are added, add them here and update .env.example.- -- Nothing else should need changing.- --- -- FIXME: oauth2BattleNet is quite annoying!- --- [ loadPlugin oauth2AzureAD "AZURE_AD"- , loadPlugin (oauth2BattleNet [whamlet|TODO|] "en") "BATTLE_NET"- , loadPlugin oauth2Bitbucket "BITBUCKET"- , loadPlugin oauth2ClassLink "CLASSLINK"- , loadPlugin (oauth2Eve Plain) "EVE_ONLINE"- , loadPlugin oauth2GitHub "GITHUB"- , loadPlugin oauth2GitLab "GITLAB"- , loadPlugin oauth2Google "GOOGLE"- , loadPlugin oauth2Nylas "NYLAS"- , loadPlugin oauth2Salesforce "SALES_FORCE"- , loadPlugin oauth2Slack "SLACK"- , loadPlugin (oauth2Spotify []) "SPOTIFY"- , loadPlugin oauth2WordPressDotCom "WORDPRESS_DOT_COM"- , loadPlugin oauth2Upcase "UPCASE"- ]+ auth0Host <- getEnv "AUTH0_HOST" - return App { .. }- where- loadPlugin f prefix = do- clientId <- getEnv $ prefix <> "_CLIENT_ID"- clientSecret <- getEnv $ prefix <> "_CLIENT_SECRET"- pure $ f (T.pack clientId) (T.pack clientSecret)+ appHttpManager <- newManager tlsManagerSettings+ appAuthPlugins <- sequence+ -- When Providers are added, add them here and update .env.example.+ -- Nothing else should need changing.+ --+ -- FIXME: oauth2BattleNet is quite annoying!+ --+ [ loadPlugin oauth2AzureAD "AZURE_AD"+ , loadPlugin (oauth2Auth0Host $ fromString auth0Host) "AUTH0"+ , loadPlugin (oauth2BattleNet [whamlet|TODO|] "en") "BATTLE_NET"+ , loadPlugin oauth2Bitbucket "BITBUCKET"+ , loadPlugin oauth2ClassLink "CLASSLINK"+ , loadPlugin (oauth2Eve Plain) "EVE_ONLINE"+ , loadPlugin oauth2GitHub "GITHUB"+ , loadPlugin oauth2GitLab "GITLAB"+ , loadPlugin oauth2Google "GOOGLE"+ , loadPlugin oauth2Nylas "NYLAS"+ , loadPlugin oauth2Salesforce "SALES_FORCE"+ , loadPlugin oauth2Slack "SLACK"+ , loadPlugin (oauth2Spotify []) "SPOTIFY"+ , loadPlugin oauth2Twitch "TWITCH"+ , loadPlugin oauth2WordPressDotCom "WORDPRESS_DOT_COM"+ , loadPlugin oauth2Upcase "UPCASE"+ ]++ return App { .. }+ where+ loadPlugin f prefix = do+ clientId <- getEnv $ prefix <> "_CLIENT_ID"+ clientSecret <- getEnv $ prefix <> "_CLIENT_SECRET"+ pure $ f (T.pack clientId) (T.pack clientSecret) main :: IO () main = runEnv 3000 =<< toWaiApp =<< mkFoundation
+ src/Yesod/Auth/OAuth2/Auth0.hs view
@@ -0,0 +1,56 @@+{-# LANGUAGE OverloadedStrings #-}+-- |+-- OAuth2 plugin for <https://auth0.com>+--+-- * Authenticates against specific auth0 tenant+-- * Uses Auth0 user id (a.k.a [sub](https://auth0.com/docs/api/authentication#get-user-info)) as credentials identifier+--+module Yesod.Auth.OAuth2.Auth0+ ( oauth2Auth0HostScopes+ , oauth2Auth0Host+ , defaultAuth0Scopes+ ) where++import Data.Aeson as Aeson+import qualified Data.Text as T+import Prelude+import Yesod.Auth.OAuth2.Prelude++-- | https://auth0.com/docs/api/authentication#get-user-info+newtype User = User T.Text++instance FromJSON User where+ parseJSON = withObject "User" $ \o -> User <$> o .: "sub"++-- | https://auth0.com/docs/get-started/apis/scopes/openid-connect-scopes#standard-claims+defaultAuth0Scopes :: [Text]+defaultAuth0Scopes = ["openid"]++pluginName :: Text+pluginName = "auth0"++oauth2Auth0Host :: YesodAuth m => URI -> Text -> Text -> AuthPlugin m+oauth2Auth0Host host = oauth2Auth0HostScopes host defaultAuth0Scopes++oauth2Auth0HostScopes+ :: YesodAuth m => URI -> [Text] -> Text -> Text -> AuthPlugin m+oauth2Auth0HostScopes host scopes clientId clientSecret =+ authOAuth2 pluginName oauth2 $ \manager token -> do+ (User uid, userResponse) <- authGetProfile pluginName+ manager+ token+ (host `withPath` "/userinfo")+ pure Creds { credsPlugin = pluginName+ , credsIdent = uid+ , credsExtra = setExtra token userResponse+ }+ where+ oauth2 = OAuth2+ { oauth2ClientId = clientId+ , oauth2ClientSecret = Just clientSecret+ , oauth2AuthorizeEndpoint = host+ `withPath` "/authorize"+ `withQuery` [scopeParam " " scopes]+ , oauth2TokenEndpoint = host `withPath` "/oauth/token"+ , oauth2RedirectUri = Nothing+ }
+ src/Yesod/Auth/OAuth2/Twitch.hs view
@@ -0,0 +1,56 @@+{-# LANGUAGE OverloadedStrings #-}+-- |+--+-- OAuth2 plugin for http://twitch.tv+--+-- * Authenticates against twitch+-- * Uses twitch user id as credentials identifier+--+module Yesod.Auth.OAuth2.Twitch+ ( oauth2Twitch+ , oauth2TwitchScoped+ ) where++import Yesod.Auth.OAuth2.Prelude++import qualified Data.Text.Encoding as T++newtype User = User Text++instance FromJSON User where+ parseJSON = withObject "User" $ \o -> User <$> o .: "user_id"++pluginName :: Text+pluginName = "twitch"++defaultScopes :: [Text]+defaultScopes = ["user:read:email"]++oauth2Twitch :: YesodAuth m => Text -> Text -> AuthPlugin m+oauth2Twitch = oauth2TwitchScoped defaultScopes++oauth2TwitchScoped :: YesodAuth m => [Text] -> Text -> Text -> AuthPlugin m+oauth2TwitchScoped scopes clientId clientSecret =+ authOAuth2 pluginName oauth2 $ \manager token -> do+ (User userId, userResponse) <- authGetProfile+ pluginName+ manager+ token+ "https://id.twitch.tv/oauth2/validate"++ pure Creds { credsPlugin = pluginName+ , credsIdent = userId+ , credsExtra = setExtra token userResponse+ }+ where+ oauth2 = OAuth2+ { oauth2ClientId = clientId+ , oauth2ClientSecret = Just clientSecret+ , oauth2AuthorizeEndpoint = "https://id.twitch.tv/oauth2/authorize"+ `withQuery` [scopeParam " " scopes]+ , oauth2TokenEndpoint = "https://id.twitch.tv/oauth2/token"+ `withQuery` [ ("client_id", T.encodeUtf8 clientId)+ , ("client_secret", T.encodeUtf8 clientSecret)+ ]+ , oauth2RedirectUri = Nothing+ }
yesod-auth-oauth2.cabal view
@@ -1,23 +1,23 @@-cabal-version: 1.12-name: yesod-auth-oauth2-version: 0.7.0.1-license: MIT-license-file: LICENSE-maintainer: engineering@freckle.com+cabal-version: 1.18+name: yesod-auth-oauth2+version: 0.7.0.2+license: MIT+license-file: LICENSE+maintainer: engineering@freckle.com author: Tom Streller, Patrick Brisbin, Freckle Engineering -homepage: http://github.com/freckle/yesod-auth-oauth2-bug-reports: https://github.com/freckle/yesod-auth-oauth2/issues-synopsis: OAuth 2.0 authentication plugins+homepage: http://github.com/freckle/yesod-auth-oauth2+bug-reports: https://github.com/freckle/yesod-auth-oauth2/issues+synopsis: OAuth 2.0 authentication plugins description: Library to authenticate with OAuth 2.0 for Yesod web applications. -category: Web-build-type: Simple-extra-source-files:+category: Web+build-type: Simple+extra-doc-files: README.md CHANGELOG.md @@ -35,6 +35,7 @@ UnliftIO.Except URI.ByteString.Extension Yesod.Auth.OAuth2+ Yesod.Auth.OAuth2.Auth0 Yesod.Auth.OAuth2.AzureAD Yesod.Auth.OAuth2.BattleNet Yesod.Auth.OAuth2.Bitbucket@@ -53,6 +54,7 @@ Yesod.Auth.OAuth2.Salesforce Yesod.Auth.OAuth2.Slack Yesod.Auth.OAuth2.Spotify+ Yesod.Auth.OAuth2.Twitch Yesod.Auth.OAuth2.Upcase Yesod.Auth.OAuth2.WordPressDotCom