[SAML plugin] Problems calling the login controller using http post requests


#1

Hi there,
we started implementing a SAML-SP authentication plugin for InvoicePlane using php-saml. Though hacking is not appreciated for IP1 I hoped that already preparing it for IP2 as a package would make things easier later for extraction. The package can be found in our github repo but is still under development. A perl installer script directly imports all files into InvoicePlane1 to hopefully let the SAML plugin be integrated into IP1 without big issues when the package is finished.

So far for introduction. A first check against an IDP seems to work as expected. Yet after the SAML request has been evaluated by the IDP and a SAML response send back to InvoicePlane, I always get an ServerError for forbidden requests. I found out that calling the Sessions.php controller using HTTP POST is not allowed. Though I checked all debug and webserver logs and dived into the applications folder I did not find out where to setup http post requests.

Is there a simple way to allow an HTTP POST request to call either any Sessions.php method or at least the login method passing a SAMLResponse object ?

Greetings,
Steve


#2

After diving into CodeIgniters Security concept I found out that the CSRF protection was the problem (I already thought something like that). Defining a separate API endpoint and including it into the csrf_exclude_uris array within the application/config/config.php file solved my problem.


#3

That totally erodes the purpose of the CSRF protection. I do not know how the plugin should work but is there no way to get a valid CSRF token from the application that can be used to perform the POST request?


#4

There would be one way, aka the utterly nasty way, which would consist in performing a CURL request to scrap the CSRF token + cookiejar/cookiefile before sending the POST request… ( ͡° ͜ʖ ͡°)

Then there is the proper implementation, which would consist in a unique secret API key per user. But hey,


#5

I’m not that sure if this would totally erode the purpose of the CSRF protection (yet I do not claim to totally understand CSRF).

From CodeIgntiter’s CSRF Security manual, the whitelisting is at least specifically implemented for this job:

Select URIs can be whitelisted from csrf protection (for example API endpoints expecting externally POSTed content).

Right now the normal login page is generated with a valid CSRF token which is passed as _ip_csrf cookie to the IDP. The IDP takes it over, generates the SAML response and redirects to the newly defined API endpoint of InvoicePlane (sessions/samlauth). The cookies is still send over but not accepted by csrf, using the exclude_csrf_uri at least lets me directly sign in via SAML. Subsequent communication is reusing directly the csrf protection again.

I would anyways prefer also a better solution, keeping especially CSRF active during authentication. From the POST side the IDP implementation is fixed, so all I would do here for correct separation is modifying the IP plugin. And for the moment I would prefer to not implement a secret API key per user…

FWIW
The SSO part of the plugin works flawlessly here and is merged to the master branch in case anybody would like to check it out - the plugin is developed for the current InvoicePlane git master branch, not the web zip package. Logout is untested and might not work, my IDP solution right now does not support logout requests. Still a lot to do in future.

There is still a question about licensing because of some lines of code. As soon as this is fixed I might consider making a pull request to InvoicePlane, at least I’m thinking that a SAML plugin might be useful. Surely the CSRF question should also be solved beforehand.