openfortivpn icon indicating copy to clipboard operation
openfortivpn copied to clipboard

Support login SAML

Open NgoHuy opened this issue 5 years ago • 100 comments

Hi, I see that openfortivpn supported 2FA but no supports SAML. Can you implement this feature?

Best regards, Severus

NgoHuy avatar Mar 13 '21 14:03 NgoHuy

Any update on this from dev? Is it hard to implement?

tjsd avatar Apr 07 '21 16:04 tjsd

This would be a great feature

dpennington avatar Apr 08 '21 21:04 dpennington

While I probably won't have time myself, pull requests are welcome.

Should we use a library that implements SAML? It looks Lasso is or used to be the de facto standard for C programs, but as far as I can understand it's for writing service providers (SP) such as a FortiGate, not clients.

DimitriPapadopoulos avatar Apr 11 '21 06:04 DimitriPapadopoulos

This might be of interest: gp-saml-gui

It would help to have screen captures of what SAML authentication looks like with FortiCLient.

DimitriPapadopoulos avatar Apr 11 '21 07:04 DimitriPapadopoulos

My guess is that the cookie is retrieved by a possibly independent process, then fed to the VPN client which does not need to re-authenticate. If so, the question is, how do we retrieve the cookie? Can you describe the FortiClient workflow (with screen captures) or at least the expected workflow?

DimitriPapadopoulos avatar Apr 12 '21 04:04 DimitriPapadopoulos

I can provide some screenshots: image image

You get a popup that is asking for you microsoft credentials: image

tjsd avatar Apr 12 '21 10:04 tjsd

Hi, interested in helping to get this implemented. I can help with screenshots and I can see if I can provide some logs or run a sample session with mitmproxy to get request & responses (sanitized ofc). What kind of info would be helpful?

memco avatar Apr 18 '21 01:04 memco

I am also willing to help with this feature. Official client supports it. Would be wonderful if openfortivpn does it too.

heimmdal avatar May 19 '21 07:05 heimmdal

Patches are welcome 😀

DimitriPapadopoulos avatar May 19 '21 07:05 DimitriPapadopoulos

Perhaps you can have a look at openconnect. I am not certain it supports SAML yet, but it might be worth trying. If it does not, I suggest you open an issue there too. Perhaps they will have the resources to implement it more rapidly.

DimitriPapadopoulos avatar Jun 13 '21 21:06 DimitriPapadopoulos

Perhaps you can have a look at openconnect. I am not certain it supports SAML yet, but it might be worth trying. If it does not, I suggest you open an issue there too. Perhaps they will have the resources to implement it more rapidly.

openconnet does not support SAML but other project like https://github.com/yuezk/GlobalProtect-openconnect did it.

NgoHuy avatar Jun 17 '21 15:06 NgoHuy

I think they have a branch in the works - not the master branch. Perhaps support for SAML will be available after openconnect 9.0 is released.

Honestly, at this point and for lack of resources, I probably won't be able to write anything for openfortivpn before they do...

DimitriPapadopoulos avatar Jun 17 '21 15:06 DimitriPapadopoulos

Hi,

The company I work for will enable the SAML authentication. I'm not a C developer and thus I can not really help to implement the feature. But if you need some help for testing I would be glad to help you!

~~The bad thing is that I tested the official client on Gnome and KDE (Fedora and Arch) to help my IT team to validate the client on Linux, and it works fine, but I use i3 and I did not manage to get a working connection with it. When I try to connect the client opens the authentication form of the SSO platform used in my company (Okta), I fill my credentials but the client never completes the auth process. Of course nothing in my logs or in the output when I run the app from my terminal... I thought about some polkit or PAM issues but I could not find anything.~~

Does somebody have some tricks about that to help me waiting for a SAML implementation on openfortivpn ?

PS: Thank you very much for creating openfortivpn, it allowed me to not use the bloated and buggy official client for so long!

Edit: I managed to make the official client working on my system. It was both a polkit issue on my machine and a certificate mistake. But I'm still OK if you need some tests on an openfortivpn SAML implementation :wink:

msaunois-dzr avatar Jun 21 '21 08:06 msaunois-dzr

I don't code in C but I might be able to fill in some of the gaps in case someone wants to take this up. I enabled ssl debug logging on a fortigate a connected with the windows client and I saw the following requests. I don't think you need any kind of saml library just a browser and a way to extract part of the response. The official client uses electronjs to display the login.

  1. /remote/info
  • contains remoteauthtimeout in seconds. this while not needed is important as the user can take a long time to login but the fortigate will timeout the session.
  1. /remote/saml/start
  • redirects to the saml idp login page
  1. /remote/saml/login
  • redirected here from the IDP. a cookie gets set here
  1. /sslvpn/portal.html
  2. /remote/fortisslvpn
  • looks like it sets a cookie via javascript <script> var cookie_str='pc2QKF5dD...8pgsU9zoYJbwP0H8='; </script>
  1. /remote/licensecheck
  • I don't know if this is required. I don't have ems but 🤷‍♂️
  1. /remote/fortisslvpn_xml
  • this looks like the list of routes/dns/etc
  1. /remote/sslvpn-tunnel?uuid=[HEX]

lart2150 avatar Aug 17 '21 18:08 lart2150

I'm not a developer either, but I can help test any patch or new version.

The company enabled yesterday, of course, without testing ignoring Linux users (they only support those who use Windows), and in my case with Arch, not even the official client (version 7.0.0.18) is working, but a colleague with Ubuntu didn't work either .

rtsantanna avatar Aug 19 '21 17:08 rtsantanna

I did a clean install, to test the crap of the manufacturer's official client.

The packages you installed from installing the forticlient package were:

Packages to install (from repository https://repo.fortinet.com/repo/7.0/centos/8/os/x86_64): forticlient

Below, the installed dependencies:

libXScrnSaver
m4
mailx
make
ncurses-compat-libs
nss-tools
patch
postfix
redhat-lsb-core
redhat-lsb-submod-security
spax
yum-utils

After that, I called the binary from a terminal, to log what would be done. Configured the VPN portal (just put the address and the SAML option).

Below, I put the output of the process (I decharacterized so I don't have problems):

[infra@teste-fortinet ~]$ forticlient 
Platform detected: fedora
[ '/opt/forticlient/gui/FortiClient-linux-x64/FortiClient' ]
Saml - init
did-finish-load
renderer ready -  IPC_RENDERER_REQUEST.FETCH_INVITATION_CODE 2021-08-19T20:04:02.768Z
this.inviteCode=null
IPC_RENDERER_REQUEST.LOADED
Events - processArgv
[ '/opt/forticlient/gui/FortiClient-linux-x64/FortiClient' ]
certificate-error url=https://vpn.address.com/remote/info
saml-login https://vpn.address.com:443/remote/saml/start
Saml - doSamlAuth
{ authTimeout: '600',
  ignoreCert: false,
  type: 1,
  url: 'https://vpn.address.com:443/remote/saml/start' }
Saml - loadUrlWithType type=1 url=https://vpn.address.com:443/remote/saml/start
samlReq.url = https://vpn.address.com:443/remote/saml/start
samlReq.type = 1
beginUrl.href = https://vpn.address.com/remote/saml/start
certificate-error url=https://vpn.address.com/remote/saml/start
Gtk-Message: 17:05:22.632: GtkDialog mapped without a transient parent. This is discouraged.
continue-error-certificate https://vpn.address.com/gateway-realm:443/remote/saml/start
Saml - reloadWindow authTimeout = 600
Saml - loadUrlWithType type=1 url=https://vpn.address.com/gateway-realm:443/remote/saml/start
certificate-error url=https://vpn.address.com/gateway-realm:443/remote/saml/start
FortiSAMLInstance.IgnoreCertificate url=https://vpn.address.com/gateway-realm:443/remote/saml/start
samlType=1 logDomainCookies - https://vpn.address.com
certificate-error url=https://vpn.address.com/sslvpn/css/ssl_style.css
FortiSAMLInstance.IgnoreCertificate url=https://vpn.address.com/sslvpn/css/ssl_style.css
samlType=1 logDomainCookies - https://vpn.address.com
certificate-error url=https://vpn.address.com/sslvpn/css/ssl_style.css
FortiSAMLInstance.IgnoreCertificate url=https://vpn.address.com/sslvpn/css/ssl_style.css
samlType=1 logDomainCookies - https://vpn.address.com
Saml - 'did-finish-load'
Saml - currentPath=https://vpn.address.com/gateway-realm:443/remote/saml/start
samlType=1 logDomainCookies - https://vpn.address.com
SAML - current path: https://vpn.address.com/gateway-realm:443/remote/saml/start
Saml - handleRedirect url=https://vpn.address.com/gateway-realm:443/remote/saml/start
Saml will-nativgate newUrl=https://vpn.address.com/remote/login
Saml - handleRedirect url=https://vpn.address.com/remote/login
Saml will-redirect url=https://vpn.address.com/remote/login?lang=en
certificate-error url=https://vpn.address.com/sslvpn/js/login.js?q=17551d5deba7dad25bffcfacc62cb666
FortiSAMLInstance.IgnoreCertificate url=https://vpn.address.com/sslvpn/js/login.js?q=17551d5deba7dad25bffcfacc62cb666
samlType=1 logDomainCookies - https://vpn.address.com
certificate-error url=https://vpn.address.com/remote/fgt_lang?lang=en
FortiSAMLInstance.IgnoreCertificate url=https://vpn.address.com/remote/fgt_lang?lang=en
samlType=1 logDomainCookies - https://vpn.address.com
certificate-error url=https://vpn.address.com/remote/fgt_lang?lang=en
FortiSAMLInstance.IgnoreCertificate url=https://vpn.address.com/remote/fgt_lang?lang=en
samlType=1 logDomainCookies - https://vpn.address.com
Saml - 'did-finish-load'
Saml - currentPath=https://vpn.address.com/remote/login?lang=en
samlType=1 logDomainCookies - https://vpn.address.com
SAML - current path: https://vpn.address.com/remote/login?lang=en
Saml - handleRedirect url=https://vpn.address.com/remote/login?lang=en
Saml - 'close' state=4
cancelAndExit state=4 currentWindow=[object BrowserWindow]
closeServer
Saml - 'closed' state=4

rtsantanna avatar Aug 19 '21 20:08 rtsantanna

Can't offer any help, but also affected by the SAML issue. Bought a raspberry pi last year to use as a thin client, and been unable to do so since work added the SAML requirement (again, like other posters, non-windows is not really considered) - as far as I can tell, openfortivpn is the only way to use fortinet vpn on an arm device - so really hope this is possible!

andyrowlett avatar Nov 17 '21 11:11 andyrowlett

For what it's worth, the @master branch of OpenConnect does support Fortinet SSL VPNs, but I think it doesn't support SAML yet, either.

DimitriPapadopoulos avatar Nov 17 '21 17:11 DimitriPapadopoulos

Not sure of anybody is working on this. Using 1.17.1, instead of "/remote/login" - it goes to "/remote/saml/start". However, the redirect to "https://login.microsoftonline.com/" this part, I have no idea how to handle it. Any suggestions are welcome. Thanks.

jng3555 avatar Feb 25 '22 23:02 jng3555

Not sure of anybody is working on this. Using 1.17.1, instead of "/remote/login" - it goes to "/remote/saml/start". However, the redirect to "https://login.microsoftonline.com/" this part, I have no idea how to handle it. Any suggestions are welcome. Thanks.

I can see a few solutions, each has their pros and cons.

  1. Show the URL to the user, ask the user to proceed in a real web browser, and eventually copy & paste the result back. The Linux OneOrive client does this. It works, but I personally do not like the solution, because it requires extra user interactions.
  2. Run a headless web browser and performs the necessary steps inside the browser. This allows non-interactive use, but may break if Microsoft changes their login page. Some people may also have a distaste of the added overhead of a headless web browser.
  3. Dealing with the HTTP GET/POST requests in the code, and parse the HTML / JavaScript responses. This is the lightweight and non-interactive solution, but does require a bit of extra effort and may break if Microsoft changes their login page.
  4. Let an external program handles it, pass the URL to the external program and expect the result back from it. User may choose to use any of the above methods to implement the external program, everyone is happy.

bowensong avatar Mar 17 '22 19:03 bowensong

I expect there are multiple different SAML providers following a certain standard, I had to use Forticlient recently with SAML, there was no trace of anything Microsoft related.

debalance avatar Mar 20 '22 09:03 debalance

I expect there are multiple different SAML providers following a certain standard, I had to use Forticlient recently with SAML, there was no trace of anything Microsoft related.

Hmm, in that case, I can only see two ways out of this - interactive authentication in a web browser or an external program.

I personally prefer the later with some reference implementations, and one of them is the interactive authentication. The user should be able to use the reference implementation out of box if they prefer, or implement their own non-interactive version for their SAML provider.

bowensong avatar Mar 20 '22 18:03 bowensong

My company has just started requiring SAML. After battling a bit with the official Forticlient, which keeps dropping the connection soon after creating the tunnel, I decided to look into ways to get the VPN working with openfortivpn.

This is the result: https://github.com/gm-vm/openfortivpn/tree/saml

The solution is far from ideal, it requires you to login from a browser, grab the SVPNCOOKIE and paste it in the console, but it's good enough for me for now.


Thinking about this a bit more, I don't think there is too much room for improvement here.

One way to make things better is that of having a standardized way to launch an external application to deal with the authentication and have the SVPNCOOKIE passed back.

I think that supporting every SAML provider reliably in a generic way without a browser is probably close to impossible. In my case, for example, I have to use Cisco's Duo, which does more than requiring username and password.

gm-vm avatar Mar 26 '22 12:03 gm-vm

Thank you @gm-vm!

I don't know if I made a mistake but I tried to add saml = 1 in the config file and the program returns WARN: Bad key in configuration file: "saml".

However using the flag --saml works fine, I just had to take the port into account for the login URL because my IT team set up another port.

cyb3rd4d avatar Mar 28 '22 07:03 cyb3rd4d

@MartialGeek thank you for the fixes.

Meanwhile I wrote a tiny Qt application to grab SVPNCOOKIE more easily. It is basically a QtWebEngine that opens the SAML page and prints the SVPNCOOKIE to stdout as soon as it is set. This is the application: https://github.com/gm-vm/openfortivpn-webview

My idea was that of passing the path to this program to openfortivpn through some command line argument and have it run it as needed. It was too late when I remembered that openfortivpn must run as root and I definitely do not want to run a browser as root. I could get that to work the way I wanted with a combination of sudo --preserve-env, fork() and setuid(), but I did not really like how it ended up looking.

I therefore decided to change approach and have SVPNCOOKIE passed as argument. I have also made it possible to pass it through stdin, so that I can do something like this:

openfortivpn-webview my_host 2>/dev/null | sudo openfortivpn my_host --svpn-cookie -

I have created a new branch here: https://github.com/gm-vm/openfortivpn/tree/svpn_cookie

As I mentioned in my previous message, I really doubt I can get this working reliably without a browser.

This is for example an overview of the steps needed when using Duo. The overview omits the required steps for the setup of the mobile application: https://duo.com/docs/sso#saml-identity-provider

gm-vm avatar Mar 28 '22 11:03 gm-vm

I think it is OK to use a browser as a first step. It is also OK to launch the browser before openfortivpn as a first step.

Note the ongoing effort to implement SAML in OpenConnect too. You might want to have a look, see for example https://gitlab.com/search?group_id=500944&project_id=2335175&scope=issues&search=SAML.

DimitriPapadopoulos avatar Mar 28 '22 11:03 DimitriPapadopoulos

If the browser window is NOT lunched by the VPN software, how is reconnecting going to be handled?

Keep in mind the SVPNCOOKIE cookie may have fairly short expiry time or is limited to single use only, but other cookies for keeping track of the user login status may have much longer validity and can be used to get the short lived cookie again when needed.

For example, with the FortiClient VPN, it pops up the login window when reconnecting, and closes it in a few seconds without requiring any user interaction if the user is already logged in. The whole process is just a lots of HTTP redirection with the "set-cookie" headers.

bowensong avatar Mar 28 '22 11:03 bowensong

Automatic reconnection with --persistent doesn't work well anyway, it resends the same password, which of course cannot work with SAML. I was against this option, the same can be achieved with an encapsulating script or proper init/systemd parameters, or by the NetworkManager plugin.

Indeed the proper way would be to attempt to reconnect with a cookie first, then re-enter new credentials. But you're right that reconnection with a cookie doesn't seem to work that well in Fortinet products anyway, see discussion about this somewhere in the OpenConnect issues or merge requests.

DimitriPapadopoulos avatar Mar 28 '22 11:03 DimitriPapadopoulos

I definitely do not want to run a browser as root

I think it is a wise decision!

If the browser window is NOT lunched by the VPN software, how is reconnecting going to be handled?

We may need to watch the status of openfortivpn? I mean if the program that runs the browser acts as a daemon, it could monitor the openfortivpn process and re-lunch a login window under certain circumstance (some status code for example)?

cyb3rd4d avatar Mar 28 '22 11:03 cyb3rd4d