feat(auth): formatted output of user queries
This commit is contained in:
parent
453034100b
commit
d4cfce317d
@ -10,6 +10,7 @@ module Auth.OAuth2
|
|||||||
, oauth2MockServer
|
, oauth2MockServer
|
||||||
, mockPluginName
|
, mockPluginName
|
||||||
, queryOAuth2User
|
, queryOAuth2User
|
||||||
|
, UserDataException
|
||||||
) where
|
) where
|
||||||
|
|
||||||
import Data.Maybe (fromJust)
|
import Data.Maybe (fromJust)
|
||||||
@ -70,47 +71,54 @@ oauth2MockServer port =
|
|||||||
---- User Queries ----
|
---- User Queries ----
|
||||||
----------------------
|
----------------------
|
||||||
|
|
||||||
data UserData = UD deriving (Show)
|
data UserDataException = UserDataJSONException JSONException
|
||||||
instance FromJSON UserData where
|
| UserDataInternalException Text
|
||||||
parseJSON _ = pure UD
|
deriving Show
|
||||||
|
|
||||||
queryOAuth2User :: forall m . (MonadIO m, MonadThrow m, MonadHandler m)
|
instance Exception UserDataException
|
||||||
|
|
||||||
|
queryOAuth2User :: forall j m . (FromJSON j, MonadIO m, MonadThrow m, MonadHandler m)
|
||||||
=> Text
|
=> Text
|
||||||
-> Text
|
-> m (Either UserDataException j)
|
||||||
-> m (Either JSONException Value)
|
queryOAuth2User userID = runExceptT $ do
|
||||||
queryOAuth2User authPlugin userID = do
|
(queryUrl, tokenUrl) <- liftIO mkBaseUrls
|
||||||
(queryUrl, tokenUrl) <- liftIO $ mkBaseUrls authPlugin
|
|
||||||
req <- parseRequest $ "GET " ++ queryUrl ++ unpack userID
|
req <- parseRequest $ "GET " ++ queryUrl ++ unpack userID
|
||||||
mTokens <- lookupSessionJson SessionOAuth2Token
|
mTokens <- lookupSessionJson SessionOAuth2Token
|
||||||
unless (isJust mTokens) . liftIO . fail $ "Tried to load sesion Oauth2 tokens, but there are none"
|
unless (isJust mTokens) . throwE $ UserDataInternalException "Tried to load session Oauth2 tokens, but there are none"
|
||||||
eNewToken <- refreshOAuth2Token @m (fromJust mTokens) tokenUrl (authPlugin == azurePluginName)
|
# ifdef DEVELOPMENT
|
||||||
case eNewToken of
|
let secure = False
|
||||||
Left e -> return $ Left e
|
# else
|
||||||
Right newTokens -> do
|
let secure = True
|
||||||
setSessionJson SessionOAuth2Token (Just $ accessToken newTokens, refreshToken newTokens)
|
# endif
|
||||||
getResponseBody <$> httpJSONEither @m @Value (req
|
newTokens <- refreshOAuth2Token @m (fromJust mTokens) tokenUrl secure
|
||||||
{ secure = authPlugin == azurePluginName
|
setSessionJson SessionOAuth2Token (Just $ accessToken newTokens, refreshToken newTokens)
|
||||||
, requestHeaders = [("Authorization", encodeUtf8 . ("Bearer " <>) . atoken $ accessToken newTokens)] })
|
eResult <- lift $ getResponseBody <$> httpJSONEither @m @j (req
|
||||||
|
{ secure = secure
|
||||||
|
, requestHeaders = [("Authorization", encodeUtf8 . ("Bearer " <>) . atoken $ accessToken newTokens)] })
|
||||||
|
case eResult of
|
||||||
|
Left x -> throwE $ UserDataJSONException x
|
||||||
|
Right x -> return x
|
||||||
|
|
||||||
mkBaseUrls :: Text -> IO (String, String)
|
|
||||||
mkBaseUrls authPlugin
|
mkBaseUrls :: IO (String, String)
|
||||||
| authPlugin == azurePluginName = do
|
mkBaseUrls = do
|
||||||
Just tenantID <- lookupEnv "AZURE_TENANT_ID"
|
# ifndef DEVELOPMENT
|
||||||
return ( "https://graph.microsoft.com/v1.0/users/"
|
Just tenantID <- lookupEnv "AZURE_TENANT_ID"
|
||||||
, "https://login.microsoftonline.com/" ++ tenantID ++ "/oauth2/v2.0" )
|
return ( "https://graph.microsoft.com/v1.0/users/"
|
||||||
| authPlugin == mockPluginName = do
|
, "https://login.microsoftonline.com/" ++ tenantID ++ "/oauth2/v2.0" )
|
||||||
Just port <- lookupEnv "OAUTH2_SERVER_PORT"
|
# else
|
||||||
let base = "http://localhost:" ++ port
|
Just port <- lookupEnv "OAUTH2_SERVER_PORT"
|
||||||
return ( base ++ "/users/query?id="
|
let base = "http://localhost:" ++ port
|
||||||
, base ++ "/token" )
|
return ( base ++ "/users/query?id="
|
||||||
| otherwise = fail $ "Unsupported auth plugin: " ++ unpack authPlugin
|
, base ++ "/token" )
|
||||||
|
# endif
|
||||||
|
|
||||||
|
|
||||||
refreshOAuth2Token :: forall m. (MonadIO m, MonadThrow m, MonadHandler m)
|
refreshOAuth2Token :: forall m. (MonadIO m, MonadThrow m, MonadHandler m)
|
||||||
=> (Maybe AccessToken, Maybe RefreshToken)
|
=> (Maybe AccessToken, Maybe RefreshToken)
|
||||||
-> String
|
-> String
|
||||||
-> Bool
|
-> Bool
|
||||||
-> m (Either JSONException OAuth2Token)
|
-> ExceptT UserDataException m OAuth2Token
|
||||||
refreshOAuth2Token (_, rToken) url secure
|
refreshOAuth2Token (_, rToken) url secure
|
||||||
| isJust rToken = do
|
| isJust rToken = do
|
||||||
req <- parseRequest $ "POST " ++ url
|
req <- parseRequest $ "POST " ++ url
|
||||||
@ -125,8 +133,11 @@ refreshOAuth2Token (_, rToken) url secure
|
|||||||
return $ body ++ [("client_id", fromString clientID), ("client_secret", fromString clientSecret), ("scope", "openid profile")]
|
return $ body ++ [("client_id", fromString clientID), ("client_secret", fromString clientSecret), ("scope", "openid profile")]
|
||||||
else return $ ("scope", "ID Profile") : body
|
else return $ ("scope", "ID Profile") : body
|
||||||
$logErrorS "\27[31mAdmin Handler\27[0m" $ tshow (requestBody $ urlEncodedBody body' req{ secure = secure })
|
$logErrorS "\27[31mAdmin Handler\27[0m" $ tshow (requestBody $ urlEncodedBody body' req{ secure = secure })
|
||||||
getResponseBody <$> httpJSONEither @m @OAuth2Token (urlEncodedBody body' req{ secure = secure })
|
eResult <- lift $ getResponseBody <$> httpJSONEither @m @OAuth2Token (urlEncodedBody body' req{ secure = secure })
|
||||||
| otherwise = liftIO $ fail "Could not refresh access token. Refresh token is missing."
|
case eResult of
|
||||||
|
Left x -> throwE $ UserDataJSONException x
|
||||||
|
Right x -> return x
|
||||||
|
| otherwise = throwE $ UserDataInternalException "Could not refresh access token. Refresh token is missing."
|
||||||
|
|
||||||
instance Show RequestBody where
|
instance Show RequestBody where
|
||||||
show (RequestBodyLBS x) = show x
|
show (RequestBodyLBS x) = show x
|
||||||
|
|||||||
@ -24,6 +24,7 @@ import Handler.Utils.Memcached
|
|||||||
import Foundation.Authorization (AuthorizationCacheKey(..))
|
import Foundation.Authorization (AuthorizationCacheKey(..))
|
||||||
|
|
||||||
import Yesod.Auth.Message
|
import Yesod.Auth.Message
|
||||||
|
import Yesod.Auth.OAuth2 (getAccessToken, getRefreshToken)
|
||||||
import Auth.LDAP
|
import Auth.LDAP
|
||||||
import Auth.OAuth2
|
import Auth.OAuth2
|
||||||
import Auth.PWHash (apHash)
|
import Auth.PWHash (apHash)
|
||||||
@ -131,6 +132,9 @@ oAuthenticate :: ( MonadHandler m, HandlerSite m ~ UniWorX
|
|||||||
=> Creds UniWorX -> m (AuthenticationResult UniWorX)
|
=> Creds UniWorX -> m (AuthenticationResult UniWorX)
|
||||||
oAuthenticate creds@Creds{..} = liftHandler . runDB . withReaderT projectBackend $ do
|
oAuthenticate creds@Creds{..} = liftHandler . runDB . withReaderT projectBackend $ do
|
||||||
$logErrorS "OAuth" $ "\a\27[31m" <> tshow creds <> "\27[0m"
|
$logErrorS "OAuth" $ "\a\27[31m" <> tshow creds <> "\27[0m"
|
||||||
|
setSessionJson SessionOAuth2Token $ (getAccessToken creds, getRefreshToken creds)
|
||||||
|
sess <- getSession
|
||||||
|
$logErrorS "OAuth" $ "\27[34m" <> tshow sess <> "\27[0m"
|
||||||
now <- liftIO getCurrentTime
|
now <- liftIO getCurrentTime
|
||||||
|
|
||||||
let
|
let
|
||||||
|
|||||||
@ -9,17 +9,14 @@ module Handler.Admin.OAuth2
|
|||||||
|
|
||||||
import Import
|
import Import
|
||||||
-- import qualified Data.CaseInsensitive as CI
|
-- import qualified Data.CaseInsensitive as CI
|
||||||
import Data.Text()
|
import Data.Aeson.Encode.Pretty (encodePretty)
|
||||||
--import qualified Data.Text as Text
|
import qualified Data.Text.Lazy as T
|
||||||
|
import qualified Data.Text.Lazy.Encoding as T
|
||||||
--import qualified Data.Text.Encoding as Text
|
--import qualified Data.Text.Encoding as Text
|
||||||
--import Foundation.Yesod.Auth (CampusUserConversionException())
|
--import Foundation.Yesod.Auth (CampusUserConversionException())
|
||||||
import Handler.Utils
|
import Handler.Utils
|
||||||
|
|
||||||
# ifdef DEVELOPMENT
|
import Auth.OAuth2 (queryOAuth2User)
|
||||||
import Auth.OAuth2 (queryOAuth2User, mockPluginName)
|
|
||||||
# else
|
|
||||||
import Auth.OAuth2 (queryOAuth2User, azurePluginName)
|
|
||||||
# endif
|
|
||||||
|
|
||||||
|
|
||||||
getAdminOAuth2R, postAdminOAuth2R :: Handler Html
|
getAdminOAuth2R, postAdminOAuth2R :: Handler Html
|
||||||
@ -28,15 +25,12 @@ postAdminOAuth2R = do
|
|||||||
((presult, pwidget), penctype) <- runFormPost $ identifyForm ("adminOAuth2Lookup"::Text) $ \html ->
|
((presult, pwidget), penctype) <- runFormPost $ identifyForm ("adminOAuth2Lookup"::Text) $ \html ->
|
||||||
flip (renderAForm FormStandard) html $ areq textField (fslI MsgAdminUserIdent) Nothing
|
flip (renderAForm FormStandard) html $ areq textField (fslI MsgAdminUserIdent) Nothing
|
||||||
|
|
||||||
let procFormPerson :: Text -> Handler (Maybe Text)
|
let procFormPerson :: Text -> Handler (Maybe T.Text)
|
||||||
procFormPerson lid = do --return . Just $ "Mock reply for id " <> lid
|
procFormPerson lid = do --return . Just $ "Mock reply for id " <> lid
|
||||||
# ifdef DEVELOPMENT
|
eUserData <- queryOAuth2User @Value lid
|
||||||
let authPlugin = mockPluginName
|
case eUserData of
|
||||||
# else
|
Left e -> throwM e
|
||||||
let authPlugin = azurePluginName
|
Right userData -> return . Just . T.decodeUtf8 $ encodePretty userData
|
||||||
# endif
|
|
||||||
eUserData <- queryOAuth2User authPlugin lid
|
|
||||||
return . Just $ tshow eUserData
|
|
||||||
mOAuth2Data <- formResultMaybe presult procFormPerson
|
mOAuth2Data <- formResultMaybe presult procFormPerson
|
||||||
|
|
||||||
--((uresult, uwidget), uenctype) <- runFormPost $ identifyForm ("adminOAuth2Upsert"::Text) $ \html ->
|
--((uresult, uwidget), uenctype) <- runFormPost $ identifyForm ("adminOAuth2Upsert"::Text) $ \html ->
|
||||||
|
|||||||
@ -13,6 +13,7 @@ $# SPDX-License-Identifier: AGPL-3.0-or-later
|
|||||||
Antwort: #
|
Antwort: #
|
||||||
<dl .deflist>
|
<dl .deflist>
|
||||||
<dt>
|
<dt>
|
||||||
#{show answers}
|
<pre>
|
||||||
|
#{answers}
|
||||||
<dd>
|
<dd>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user