mirror of
https://github.com/freckle/yesod-auth-oauth2.git
synced 2026-01-11 19:58:28 +01:00
Add AzureADv2 plugin
This is the same as the `AzureAD` plugin except: 1. It uses tenant-specific `microsoftonline.com` v2 OAuth2 endpoints (hence the name), which means accepting a new Tenant Id argument 2. It uses a space instead of `,` as the scopes separator Users of multi-tenant apps can provide a Tenant Id of `"common"`. I'm also not certain if the space-vs-comma scopes separator represents a bug in the `AzureAD` plugin, or just a difference in the actual v2 APIs. This inherits the behavior of using email address as the `credIdent` although this is definitely an `id` field in the User Response. I'm not sure if there are trade-offs one way or another. Using `id` could mean transparently handling Azure users changing their email, but I suspect your identity is implicitly tied to email within Azure anyway, so that would not be a case we'll ever see. In the future, we can deprecate the `AzureAD` plugin and suggest users migrate to this one.
This commit is contained in:
parent
8b46e82981
commit
ac1e48db97
@ -14,6 +14,10 @@ AUTH0_CLIENT_SECRET=x
|
|||||||
AZURE_AD_CLIENT_ID=x
|
AZURE_AD_CLIENT_ID=x
|
||||||
AZURE_AD_CLIENT_SECRET=x
|
AZURE_AD_CLIENT_SECRET=x
|
||||||
|
|
||||||
|
AZURE_ADV2_TENANT_ID=x
|
||||||
|
AZURE_ADV2_CLIENT_ID=x
|
||||||
|
AZURE_ADV2_CLIENT_SECRET=x
|
||||||
|
|
||||||
BATTLE_NET_CLIENT_ID=x
|
BATTLE_NET_CLIENT_ID=x
|
||||||
BATTLE_NET_CLIENT_SECRET=x
|
BATTLE_NET_CLIENT_SECRET=x
|
||||||
|
|
||||||
|
|||||||
@ -14,7 +14,7 @@ import Data.ByteString.Lazy (fromStrict, toStrict)
|
|||||||
import qualified Data.Map as M
|
import qualified Data.Map as M
|
||||||
import Data.Maybe (fromJust)
|
import Data.Maybe (fromJust)
|
||||||
import Data.String (IsString(fromString))
|
import Data.String (IsString(fromString))
|
||||||
import Data.Text (Text)
|
import Data.Text (Text, pack)
|
||||||
import qualified Data.Text as T
|
import qualified Data.Text as T
|
||||||
import Data.Text.Encoding (decodeUtf8)
|
import Data.Text.Encoding (decodeUtf8)
|
||||||
import LoadEnv
|
import LoadEnv
|
||||||
@ -25,6 +25,7 @@ import Yesod
|
|||||||
import Yesod.Auth
|
import Yesod.Auth
|
||||||
import Yesod.Auth.OAuth2.Auth0
|
import Yesod.Auth.OAuth2.Auth0
|
||||||
import Yesod.Auth.OAuth2.AzureAD
|
import Yesod.Auth.OAuth2.AzureAD
|
||||||
|
import Yesod.Auth.OAuth2.AzureADv2
|
||||||
import Yesod.Auth.OAuth2.BattleNet
|
import Yesod.Auth.OAuth2.BattleNet
|
||||||
import Yesod.Auth.OAuth2.Bitbucket
|
import Yesod.Auth.OAuth2.Bitbucket
|
||||||
import Yesod.Auth.OAuth2.ClassLink
|
import Yesod.Auth.OAuth2.ClassLink
|
||||||
@ -119,6 +120,7 @@ mkFoundation = do
|
|||||||
loadEnv
|
loadEnv
|
||||||
|
|
||||||
auth0Host <- getEnv "AUTH0_HOST"
|
auth0Host <- getEnv "AUTH0_HOST"
|
||||||
|
azureTenant <- getEnv "AZURE_ADV2_TENANT_ID"
|
||||||
|
|
||||||
appHttpManager <- newManager tlsManagerSettings
|
appHttpManager <- newManager tlsManagerSettings
|
||||||
appAuthPlugins <- sequence
|
appAuthPlugins <- sequence
|
||||||
@ -128,6 +130,7 @@ mkFoundation = do
|
|||||||
-- FIXME: oauth2BattleNet is quite annoying!
|
-- FIXME: oauth2BattleNet is quite annoying!
|
||||||
--
|
--
|
||||||
[ loadPlugin oauth2AzureAD "AZURE_AD"
|
[ loadPlugin oauth2AzureAD "AZURE_AD"
|
||||||
|
, loadPlugin (oauth2AzureADv2 $ pack azureTenant) "AZURE_ADV2"
|
||||||
, loadPlugin (oauth2Auth0Host $ fromString auth0Host) "AUTH0"
|
, loadPlugin (oauth2Auth0Host $ fromString auth0Host) "AUTH0"
|
||||||
, loadPlugin (oauth2BattleNet [whamlet|TODO|] "en") "BATTLE_NET"
|
, loadPlugin (oauth2BattleNet [whamlet|TODO|] "en") "BATTLE_NET"
|
||||||
, loadPlugin oauth2Bitbucket "BITBUCKET"
|
, loadPlugin oauth2Bitbucket "BITBUCKET"
|
||||||
|
|||||||
82
src/Yesod/Auth/OAuth2/AzureADv2.hs
Normal file
82
src/Yesod/Auth/OAuth2/AzureADv2.hs
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
{-# LANGUAGE OverloadedStrings #-}
|
||||||
|
-- |
|
||||||
|
--
|
||||||
|
-- OAuth2 plugin for Azure AD using the new v2 endpoints.
|
||||||
|
--
|
||||||
|
-- * Authenticates against Azure AD
|
||||||
|
-- * Uses email as credentials identifier
|
||||||
|
--
|
||||||
|
module Yesod.Auth.OAuth2.AzureADv2
|
||||||
|
( oauth2AzureADv2
|
||||||
|
, oauth2AzureADv2Scoped
|
||||||
|
) where
|
||||||
|
|
||||||
|
import Prelude
|
||||||
|
import Yesod.Auth.OAuth2.Prelude
|
||||||
|
|
||||||
|
import Data.String
|
||||||
|
import Data.Text (unpack)
|
||||||
|
|
||||||
|
newtype User = User Text
|
||||||
|
|
||||||
|
instance FromJSON User where
|
||||||
|
parseJSON = withObject "User" $ \o -> User <$> o .: "mail"
|
||||||
|
|
||||||
|
pluginName :: Text
|
||||||
|
pluginName = "azureadv2"
|
||||||
|
|
||||||
|
defaultScopes :: [Text]
|
||||||
|
defaultScopes = ["openid", "profile"]
|
||||||
|
|
||||||
|
oauth2AzureADv2
|
||||||
|
:: YesodAuth m
|
||||||
|
=> Text
|
||||||
|
-- ^ Tenant Id
|
||||||
|
--
|
||||||
|
-- If using a multi-tenant App, @common@ can be given here.
|
||||||
|
--
|
||||||
|
-> Text -- ^ Client Id
|
||||||
|
-> Text -- ^ Client secret
|
||||||
|
-> AuthPlugin m
|
||||||
|
oauth2AzureADv2 = oauth2AzureADv2Scoped defaultScopes
|
||||||
|
|
||||||
|
oauth2AzureADv2Scoped
|
||||||
|
:: YesodAuth m
|
||||||
|
=> [Text] -- ^ Scopes
|
||||||
|
-> Text
|
||||||
|
-- ^ Tenant Id
|
||||||
|
--
|
||||||
|
-- If using a multi-tenant App, @common@ can be given here.
|
||||||
|
--
|
||||||
|
-> Text -- ^ Client Id
|
||||||
|
-> Text -- ^ Client Secret
|
||||||
|
-> AuthPlugin m
|
||||||
|
oauth2AzureADv2Scoped scopes tenantId clientId clientSecret =
|
||||||
|
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
|
||||||
|
{ oauth2ClientId = clientId
|
||||||
|
, oauth2ClientSecret = Just clientSecret
|
||||||
|
, oauth2AuthorizeEndpoint =
|
||||||
|
tenantUrl "/authorize" `withQuery` [scopeParam " " scopes]
|
||||||
|
, oauth2TokenEndpoint = tenantUrl "/token"
|
||||||
|
, oauth2RedirectUri = Nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
tenantUrl path =
|
||||||
|
fromString
|
||||||
|
$ "https://login.microsoftonline.com/"
|
||||||
|
<> unpack tenantId
|
||||||
|
<> "/oauth2/v2.0"
|
||||||
|
<> path
|
||||||
@ -4,7 +4,7 @@ cabal-version: 1.18
|
|||||||
--
|
--
|
||||||
-- see: https://github.com/sol/hpack
|
-- see: https://github.com/sol/hpack
|
||||||
--
|
--
|
||||||
-- hash: 2aa7c7881c27a03f22715aa6db358fc5fe466f5967a09741265bd0f7a999e2b1
|
-- hash: 019ad5ce3ea29fb93dcf2bd6d9bc7870cebe0dabfc1d0dbceb18639a9f715b34
|
||||||
|
|
||||||
name: yesod-auth-oauth2
|
name: yesod-auth-oauth2
|
||||||
version: 0.7.0.3
|
version: 0.7.0.3
|
||||||
@ -41,6 +41,7 @@ library
|
|||||||
Yesod.Auth.OAuth2
|
Yesod.Auth.OAuth2
|
||||||
Yesod.Auth.OAuth2.Auth0
|
Yesod.Auth.OAuth2.Auth0
|
||||||
Yesod.Auth.OAuth2.AzureAD
|
Yesod.Auth.OAuth2.AzureAD
|
||||||
|
Yesod.Auth.OAuth2.AzureADv2
|
||||||
Yesod.Auth.OAuth2.BattleNet
|
Yesod.Auth.OAuth2.BattleNet
|
||||||
Yesod.Auth.OAuth2.Bitbucket
|
Yesod.Auth.OAuth2.Bitbucket
|
||||||
Yesod.Auth.OAuth2.ClassLink
|
Yesod.Auth.OAuth2.ClassLink
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user