diff --git a/messages/uniworx/categories/authorization/de-de-formal.msg b/messages/uniworx/categories/authorization/de-de-formal.msg index f9a26de23..4c0773001 100644 --- a/messages/uniworx/categories/authorization/de-de-formal.msg +++ b/messages/uniworx/categories/authorization/de-de-formal.msg @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: 2022 Gregor Kleen ,Sarah Vaupel ,Steffen Jost ,Winnie Ros +# SPDX-FileCopyrightText: 2022-2024 Gregor Kleen ,Sarah Vaupel ,Steffen Jost ,Winnie Ros ,David Mosbach # # SPDX-License-Identifier: AGPL-3.0-or-later @@ -139,3 +139,5 @@ FormHoneypotNamePlaceholder: Name FormHoneypotComment: Kommentar FormHoneypotCommentPlaceholder: Kommentar FormHoneypotFilled: Bitte füllen Sie keines der verstecken Felder aus + +SingleSignOut: Abmeldung bei Azure diff --git a/messages/uniworx/categories/authorization/en-eu.msg b/messages/uniworx/categories/authorization/en-eu.msg index b539efbf1..7dc17b924 100644 --- a/messages/uniworx/categories/authorization/en-eu.msg +++ b/messages/uniworx/categories/authorization/en-eu.msg @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: 2022 Gregor Kleen ,Sarah Vaupel ,Steffen Jost ,Winnie Ros +# SPDX-FileCopyrightText: 2022-2024 Gregor Kleen ,Sarah Vaupel ,Steffen Jost ,Winnie Ros ,David Mosbach # # SPDX-License-Identifier: AGPL-3.0-or-later @@ -140,3 +140,5 @@ FormHoneypotNamePlaceholder !ident-ok: Name FormHoneypotComment: Comment FormHoneypotCommentPlaceholder: Comment FormHoneypotFilled: Please do not fill in any of the hidden fields + +SingleSignOut: Azure logout diff --git a/routes b/routes index 2376c33af..e42a707e5 100644 --- a/routes +++ b/routes @@ -1,4 +1,4 @@ --- SPDX-FileCopyrightText: 2022-2023 Sarah Vaupel , Gregor Kleen ,Sarah Vaupel ,Steffen Jost ,Wolfgang Witt +-- SPDX-FileCopyrightText: 2022-2024 Sarah Vaupel , Gregor Kleen ,Sarah Vaupel ,Steffen Jost ,Wolfgang Witt ,David Mosbach -- -- SPDX-License-Identifier: AGPL-3.0-or-later @@ -46,6 +46,8 @@ /static StaticR EmbeddedStatic appStatic !free /auth AuthR Auth getAuth !free +/ssout SSOutR GET !free -- single sign-out (OIDC) + /metrics MetricsR GET !free -- verify if this can be free /err ErrorR GET !free diff --git a/src/Application.hs b/src/Application.hs index 08fef42ee..215f4631d 100644 --- a/src/Application.hs +++ b/src/Application.hs @@ -164,6 +164,7 @@ import Handler.PrintCenter import Handler.ApiDocs import Handler.Swagger import Handler.Firm +import Handler.SingleSignOut import ServantApi () -- YesodSubDispatch instances import Servant.API diff --git a/src/Auth/OAuth2.hs b/src/Auth/OAuth2.hs index 613a1ddd5..c85af461b 100644 --- a/src/Auth/OAuth2.hs +++ b/src/Auth/OAuth2.hs @@ -11,12 +11,13 @@ module Auth.OAuth2 , mockPluginName , queryOAuth2User , UserDataException +, singleSignOut ) where import Data.Maybe (fromJust) import Data.Text -import Import.NoFoundation hiding (unpack) +import Import.NoFoundation hiding (pack, unpack) import Network.HTTP.Simple (httpJSONEither, getResponseBody, JSONException) @@ -148,3 +149,23 @@ instance Show RequestBody where show (RequestBodyLBS x) = show x show _ = error ":(" + + ----------------------- +---- Single Sign-Out ---- + ----------------------- + +singleSignOut :: forall a m. (MonadHandler m) + => Maybe Text -- ^ redirect uri + -> m a +singleSignOut mRedirect = do +# ifdef DEVELOPMENT + port <- liftIO $ fromJust <$> lookupEnv "OAUTH2_SERVER_PORT" + let base = "http://localhost:" <> pack port <> "/logout" +# else + let base = "" -- TODO find out fraport oidc end_session_endpoint +# endif + endpoint = case mRedirect of + Just r -> base <> "?post_logout_redirect_uri=" <> r + Nothing -> base + redirect endpoint + diff --git a/src/Foundation/Instances.hs b/src/Foundation/Instances.hs index ca9dc9ad3..e4d81cf88 100644 --- a/src/Foundation/Instances.hs +++ b/src/Foundation/Instances.hs @@ -174,6 +174,11 @@ instance YesodAuth UniWorX where addMessage Success . toHtml $ mr Auth.NowLoggedIn + -- onLogout = do + -- AppSettings{..} <- getsYesod appSettings' + -- when appSingleSignOn $ singleSignOut @UniWorX Nothing + + onErrorHtml dest msg = do addMessage Error $ toHtml msg redirect dest diff --git a/src/Foundation/Navigation.hs b/src/Foundation/Navigation.hs index bf486ed22..c0a642a2e 100644 --- a/src/Foundation/Navigation.hs +++ b/src/Foundation/Navigation.hs @@ -73,6 +73,7 @@ breadcrumb :: ( BearerAuthSite UniWorX => Route UniWorX -> m Breadcrumb breadcrumb (AuthR _) = i18nCrumb MsgMenuLogin $ Just NewsR +breadcrumb SSOutR = i18nCrumb MsgSingleSignOut Nothing breadcrumb (StaticR _) = i18nCrumb MsgBreadcrumbStatic Nothing breadcrumb (WellKnownR _) = i18nCrumb MsgBreadcrumbWellKnown Nothing breadcrumb MetricsR = i18nCrumb MsgBreadcrumbMetrics Nothing @@ -546,7 +547,7 @@ defaultLinks = fmap catMaybes . mapM runMaybeT $ -- Define the menu items of the , navIcon = IconMenuLogout , navLink = NavLink { navLabel = MsgMenuLogout - , navRoute = AuthR LogoutR + , navRoute = SSOutR -- AuthR LogoutR , navAccess' = NavAccessHandler $ is _Just <$> maybeAuthId , navType = NavTypeLink { navModal = False } , navQuick' = mempty diff --git a/src/Handler/SingleSignOut.hs b/src/Handler/SingleSignOut.hs new file mode 100644 index 000000000..44ec813a2 --- /dev/null +++ b/src/Handler/SingleSignOut.hs @@ -0,0 +1,23 @@ +-- SPDX-FileCopyrightText: 2024 David Mosbach +-- +-- SPDX-License-Identifier: AGPL-3.0-or-later + +module Handler.SingleSignOut + ( getSSOutR + ) where + +import Import +import Auth.OAuth2 (singleSignOut) +import qualified Network.Wai as W + + +getSSOutR :: Handler Html +getSSOutR = do + app <- getYesod + let logoutR = intercalate "/" . fst . renderRoute $ AuthR LogoutR + root = case approot of + ApprootRequest f -> f app W.defaultRequest + _ -> error "approt implementation changed" + AppSettings{..} <- getsYesod appSettings' + if appSingleSignOn then singleSignOut (Just $ root <> "/" <> logoutR) else redirect (AuthR LogoutR) +