1313use Icinga \Application \Logger ;
1414use Icinga \Authentication \LoginButton ;
1515use Icinga \Authentication \LoginButtonForm ;
16+ use Icinga \Authentication \Auth ;
17+ use Icinga \Authentication \User \ExternalBackend ;
1618use Icinga \Common \Database ;
1719use Icinga \Exception \AuthenticationException ;
18- use Icinga \Forms \Authentication \Cancel2FAForm ;
1920use Icinga \Forms \Authentication \Challenge2FAForm ;
2021use Icinga \Forms \Authentication \LoginForm ;
2122use Icinga \Web \Controller ;
2223use Icinga \Web \Helper \CookieHelper ;
2324use Icinga \Web \RememberMe ;
2425use Icinga \Web \Session ;
2526use Icinga \Web \Url ;
27+ use ipl \Html \Contract \Form ;
2628use RuntimeException ;
2729use Throwable ;
2830
@@ -58,11 +60,47 @@ public function loginAction()
5860 && $ user ->getTwoFactorEnabled ()
5961 && Session::getSession ()->get ('2fa_must_challenge_token ' , false )
6062 ) {
61- $ form = new Challenge2FAForm ();
62- $ cancel2faForm = new Cancel2FAForm ();
63- $ cancel2faForm ->handleRequest ();
63+ $ form = (new Challenge2FAForm ())
64+ ->setAction (Url::fromRequest ()->getAbsoluteUrl ())
65+ ->on (Form::ON_SUBMIT , function (Challenge2FAForm $ form ) {
66+ if ($ redirectUrl = $ form ->getRedirectUrl ()) {
67+ $ this ->redirectNow ($ redirectUrl );
68+ }
69+ })
70+ ->on (Form::ON_SENT , function (Challenge2FAForm $ form ) {
71+ $ isCsrfValid = $ form ->getElement ('CSRFToken ' )->isValid ();
72+ $ isCancelPressed = $ form ->getPressedSubmitElement ()?->getName() === $ form ::SUBMIT_CANCEL ;
73+
74+ if ($ isCsrfValid && $ isCancelPressed ) {
75+ Session::getSession ()->purge ();
76+ $ this ->redirectNow (Url::fromRequest ());
77+ }
78+ });
6479 } else {
65- $ form = new LoginForm ();
80+ $ form = (new LoginForm ())
81+ ->setAction (Url::fromRequest ()->getAbsoluteUrl ())
82+ ->on (Form::ON_SUBMIT , function (LoginForm $ form ) {
83+ if ($ redirectUrl = $ form ->getRedirectUrl ()) {
84+ $ this ->redirectNow ($ redirectUrl );
85+ }
86+ })
87+ ->on (Form::ON_REQUEST , function ($ request , LoginForm $ form ) {
88+ $ auth = Auth::getInstance ();
89+ $ onlyExternal = true ;
90+ // TODO(el): This may be set on the auth chain once iterated. See Auth::authExternal().
91+ foreach ($ auth ->getAuthChain () as $ backend ) {
92+ if (! $ backend instanceof ExternalBackend) {
93+ $ onlyExternal = false ;
94+ }
95+ }
96+ if ($ onlyExternal ) {
97+ $ form ->addMessage ($ this ->translate (
98+ 'You \'re currently not authenticated using any of the web server \'s authentication '
99+ . 'mechanisms. Make sure you \'ll configure such, otherwise you \'ll not be able to login. '
100+ ));
101+ $ form ->onError ();
102+ }
103+ });
66104
67105 if (RememberMe::hasCookie () && $ this ->hasDb ()) {
68106 $ authenticated = false ;
@@ -99,7 +137,7 @@ public function loginAction()
99137 $ this ->httpBadRequest ('nope ' );
100138 }
101139 } else {
102- $ redirectUrl = $ form ->getRedirectUrl ();
140+ $ redirectUrl = $ form ->createRedirectUrl ();
103141 }
104142
105143 $ this ->redirectNow ($ redirectUrl );
@@ -114,7 +152,7 @@ public function loginAction()
114152 ->sendResponse ();
115153 exit ;
116154 }
117- $ form ->handleRequest ();
155+ $ form ->handleRequest (ServerRequest:: fromGlobals () );
118156 }
119157
120158 $ loginButtons = [];
0 commit comments