Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: SAML/SSO/2FA support #1034

Closed
wants to merge 0 commits into from
Closed

Conversation

LorenzISR
Copy link

@LorenzISR LorenzISR commented Oct 28, 2022

This is a WIP. Fixes #867

I have implemented SAML/SSO using firefox/geckodriver. It is already working, but missing a lot of features and the code needs better documentation. I am opening a pull request here to get feedback from you. It would be great if you could test this and give me feedback if it is working for you (reacting with a 👍). If you get the Error ERROR: Failed to create the webdriver session. please try again few times. This is a known issue. See below for a technical explanation. Please report any other errors that you encounter trying to run it multiple times.

How to use

You need to compile my branch (https://github.com/LorenzISR/openfortivpnSAML.git). Except from the normal dependencies, you will need geckodriver and firefox (snap version does not work).

Please run openfortivpn with --saml=firefox (Firefox is the only supported browser at the moment). You don't need to set your username or password. For example,

openfortivpn vpn.host.tld:443 --saml=firefox

should work if you don't need any other flags to connect (Please see below in TODO because these features might not be implemented yet.).

Technical explanation

I am creating a custom Firefox profile with custom properties in ~/.mozilla/firefox/openfortivpn/. The custom properties include disabling the first launch screen, experiments, tab/url bar, etc.

When the saml setting is enabled, we checking if the profile exists. If the profile exists, it will continue, if not, it will create the profile with the prefs.js and userChrome.css file and then continue. Then, openfortivpn launches geckodriver (See here for what geckodriver does: https://firefox-source-docs.mozilla.org/testing/geckodriver/index.html) as the user given by the SUDO_UID enviroment variable (In a child process). This is needed because geckodriver will launch firefox and firefox cannot easily run as root. If SUDO_UID is not set, you need to set it manually to the user that should run the browser.

Then we make a request to localhost:4444 (default geckodriver port) to create a new webdriver session (See the webdriver sepc here: https://w3c.github.io/webdriver). This will launch the browser and return a session id. With this session id, you can tell the just launched browser what to do. With a POST /session/<id>/url {"url": "<domain>/remote/saml/start"} we tell the browser to go to the saml website.

What we do now is just looping and checking every 1/4 second if the SVPNCOOKIE has been set with GET /session/<id>/cookie/SVPNCOOKIE {}. If we are looping more than COOKIE_MAX_TIMEOUT_SECS (set in saml.c:22 to 5 minutes) we are breaking the loop and exiting with an error to avoid wasting processing power when the PC is not used. When we got the cookie, we destroy the webdriver session using DELETE /session/<id> {} and waiting until it has been destroyed. After that, we kill geckodriver. We set the cookie that we got to the cfg.cookie variable and continue running normally.

TODO:

  • Support for authentication realms
  • Investigate if WebKit2GTK is actually a better solution
  • Use the specified port
  • Support for chromium
  • Better code documentation
  • Support for other platforms (*BSD, MacOS)
  • Add to the README
  • Add to --help
  • Connection to geckodriver is failing sometimes, fix this.
    (This is not a complete list, more to come)

@LorenzISR LorenzISR mentioned this pull request Nov 2, 2022
@LorenzISR LorenzISR marked this pull request as draft November 3, 2022 10:25
@Newbytee
Copy link

Newbytee commented Nov 7, 2022

Have you considered using e.g. WebKit2GTK instead of this Firefox setup? It's built to be embedded in applications like this. Don't get me wrong, I love Firefox, but I think WebDriver is intended more as an interface for testing than something for end users.

With that said, thanks a bunch for this! Just in time for my university sadly starting to require FortiClient VPN for access to certain resources.

@LorenzISR
Copy link
Author

Oh, I haven't thought of WebKitGTK, that's actually a pretty good idea! I will have a look, thanks very much for the suggestion!

@DimitriPapadopoulos
Copy link
Collaborator

Perhaps the core openfortivpn shouldn't be changed into a GUI program instead of a command line program. It would be great if a library was available to mimic a browser from within a command line program, and that could be used to interact with HTML or JavaScript forms pages. I don't know of such a library.

@Newbytee
Copy link

It would be great if a library was available to mimic a browser from within a command line program, and that could be used to interact with HTML or JavaScript forms pages. I don't know of such a library.

There are programs like that, namely elinks and w3m. However, neither of them are particularly well-supporting of modern web standards and would not be sufficient to authenticate SAML/SSO/2FA in most if not all cases. Additionally, I don't think they have an API like WebKit2GTK.

@DimitriPapadopoulos
Copy link
Collaborator

DimitriPapadopoulos commented Nov 29, 2022

Thank you for the list of programs. I was already aware of ELinks but it is not maintained any more (latest stable version in 2009 and unstable in 2012). It looks like w3m is not in better shape (last version 0.5.3 released in 2011). And indeed, they would have to provide an API to interact with forms.

Perhaps it's best to rewrite openfortivpn with callbacks, to be set in main(). The purely command line program would be unable to do SAML, or just start a browser. A GUI version would be able to start WebKitGTK instead. And GUI clients, including NetworkManager, could implement their own callbacks, more GUI-oriented.

@Newbytee
Copy link

Why did you delete all the code? This was still useful even if not in a mergeable state.

@LorenzISR
Copy link
Author

The commits where a mess, so I deleted them. The new pull request is #1042
Can you test if this is working for you?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Support login SAML
3 participants