-
Notifications
You must be signed in to change notification settings - Fork 130
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
How to connect when only okta auth is used #116
Comments
Starting with the disclaimer that I don't use or have access to Okta myself… @arthepsy and @cizra have figured out a lot of things about how it works. See this comment with a summary: #98 (comment) Breaking it down a little further…
… and lastly, if anyone is willing and able to let me play around with their Okta VPN login for a couple hours, perhaps while screensharing, then I can probably simplify it further. Please email me if so. (I won't need to do anything besides test the authentication process.) |
Awesome, thanks for the pointers. Our Okta stuff seems to require a bunch of javascript nonsense, so the pan-globalprotect-okta script doesn't quite work, but I'm gonna work to modify it and pass through a browser and see if I can get that going. I sadly can't lend you any Okta credentials as mine are work related. |
The login process in my VPN is so involved I found it easier to steal auth cookies from Firefox (using Python's browsercookie) and then use RoboBrowser to get the token |
Yeah, I think @cizra's approach of doing the authentication in the browser and then stealing the cookies is probably the lowest-hassle approach. |
@nicklan, did you figure out a good way to handle this? It'd be really awesome if you Okta users could write up a how-to guide on OpenConnect+Okta, since this comes up a lot :-D |
So, I can't seem to get this going. By hacking up the scripts a bit, I'm able to use a combo of my browser and python to get the auth-usercookie. But then I can't actually connect. If I try the command you gave above I get:
and if I try the one that the arthepsy/pan-globalprotect-okta script spits out, I get:
|
This is just a random idea, but are you sure that the Also, are you certain that the cookie you're receiving should be named
There's a mistake in this one. The ——— Unfortunately, I know almost nothing of how Okta can integrate with GlobalProtect. There seems to be a lot of possible variation. I would suggest that you play around with To mimic what you've been trying so far (username + portal-userauthcookie, blank password, submit to portal login interface), try the following: ./test-globalprotect-login.py -u "[email protected]" -p "" \
https://[vpn-server]/global-protect/getconfig.esp \
portal-userauthcookie=deadbeef01234567 |
@nicklan, it turns out that I'm the one who broke @arthepsy's script (:man_facepalming:) in a too-hasty PR. I'm not sure if it'll make any difference, but you may want to test it after fixing the syntax error I mentioned above (you can just apply dlenski/pan-globalprotect-okta@2029f19). |
P.S. I've commited the fix and also added OKTA totp support (previously, it supported only Google). |
Thanks for the replies. I'm using the updated script and still getting the same error. At the core:
I've tried both with and without the Here's the response I get for the getconfig request in the script. Lots redacted, so let me know if there might be useful info I left out:
I'll try messing with the test-globalprotect-login.py you linked and see if I can figure anything out. Thanks for all the help! |
So after trying every combination of things I can think of, I'm not able to get any further than some variation of:
Are there some docs for how this is supposed to work so I can try some other stuff? Thanks! |
Unfortunately not. All public knowledge about how the GlobalProtect VPN works comes from my reverse engineering, with various bits and pieces that others have helped me fill in — especially in this area of authentication.
I'd say you included all of the interesting/relevant parts of the This gives me an idea! Here's an outline of the what the official GP VPN clients do…
The OpenConnect C binary can start this process at either (3) or (5). Up until now, I thought you were getting stuck at (3). But it appears that @arthepsy's script is getting you through (3) successfully. So the logical next step is to (4), not repeating (3). Grab my latest $ ./test-globalprotect-login.py -u "$USER" -p "$PASSWORD" \
https://$GATEWAY/ssl-vpn/login.esp \
portal-userauthcookie=$PUAC \
portal-prelogonuserauthcookie=empty \
scep-cert-auth-cookie=$SCAC If all goes well, then 🍻, and you'll get this output:
Run that command and you're on your way to (5). If so, the Okta script ought to be modified to direct the user to the gateway rather than the portal as the logical next step. |
PS: Although GlobalProtect is a black box, Okta has plenty of API documentation: https://developer.okta.com/docs/api/resources/oidc You may want to scrutinize the web pages that lead to the |
Arg! This seemed very promising, but trying to log into the gateway still just gives me a 512 as:
I did have to enable --no-verify although I could probably avoid that by telling python to use the certs that are returned in step 3. I will have a look at the okta docs and see what I can figure out. Thanks! |
👌
Basically, what you want to keep in mind here is that you've already figured out how to login to the portal via Okta, and presumably the output of the Okta login process contains clues about what to do next to connect to the GlobalProtect server. |
i had this 512 error also, just like @arthepsy writes, fix connection string by appending |
@Atoms, you mean in the python script, like: cmd = '\nprintf "{1}" | openconnect --dump -vvv --protocol=gp -u "{0}" --usergroup portal:portal-userauthcookie --passwd-on-stdin {2}' I've tried that and it doesn't seem to make a difference. Of note, I can't seem to use the --passwd-on-stdin option, it just always gives:
So I've been removing that and pasting the cookie in. But I dump out the contents of the request and I can see that it's sending the correct base64 encoded version of the cookie as part of the POST body, so I don't think that's the issue. |
Try moving newline in "\n{1}" |
This is not correct. OpenConnect is certainly smart enough to remove the trailing
This doesn't make any sense. Unless openconnect is asking you for other input before the password, echo "$PASSWORD" | openconnect --passwd-on-stdin --dump -vvv --prot=gp -u "$USERNAME" --usergroup portal:passwd "$HOST" Everyone's using Linux here, right? |
@dlenski, no, this is correct, openconnect do ask for additional input and fails with ioctl error as @nicklan, @Atoms and me mentioned. This one - I'm using FreeBSD, @Atoms is using Linux. Not sure about @nicklan, would guess it's Linux. |
And yes, to answer question, which You asked previously, without PIPE, it also waits for some input... before writing out "Please enter your username and password". |
Here's the backtrace for two This is before "Please enter your username and password"
This is after "portal-userauthcookie":
|
So, first read happens in https://github.com/dlenski/openconnect/blob/master/main.c#L1276 and second in https://github.com/dlenski/openconnect/blob/master/main.c#L2007. Actually, that was my initial guess, that it asks for password and later for cookie, but didn't verify. Looks like issue is in this check: https://github.com/dlenski/openconnect/blob/master/main.c#L2003 |
Good catch @arthepsy. 🤦♂️ I had submitted a patch upstream to add better hints for which form fields should be considered "the password", but they weren't accepted. For now, you should be able kludge around this problem with a patch like… diff --git a/main.c b/main.c
index 379cf5d..d2e21c0 100644
--- a/main.c
+++ b/main.c
@@ -1999,8 +1999,7 @@ static int process_auth_form_cb(void *_vpninfo,
empty = 0;
} else if (opt->type == OC_FORM_OPT_PASSWORD) {
- if (password &&
- !strncmp(opt->name, "pass", 4)) {
+ if (password) {
opt->_value = password;
password = NULL;
} else { |
HA, got it! :) Turns out it wants a
arg as part of the POST body for the Thanks again for all the help, and lmk if there's any more stuff I can check for you while I'm in "debug" mode :) |
That's the only thing that was missing? The gateway login works with |
yep. if clientos is missing or linux64 i get the 512, otherwise all works just fine. |
That is a pretty infuriatingly misleading error. You can use I try to avoid lying to the server about the OS whenever possible, but it sounds like it's necessary to lie to the gateway in this case. So once you add the magic value of |
This seems closely related to #86, where a user encountered a different misleading error when |
Huh… so you have to put this query string boilerplate onto the end of the prelogin request, otherwise it won't include the SAML login info? Does it matter if the
TBD… 🤷♂️ |
Just ran a couple of experiments — the missing bit seems to be The host-id doesn't matter. |
Per this comment (#116 (comment)), `clientos=Windows` (or `=Mac`) is required to get the servers to respond correctly when using SAML. This is similar to other cases where the official clients and servers sometimes respond with bizarre misleading errors if `clientos` doesn't have one of the magic acceptable values (see 7f7d739). The official clients also include `os-version` (free-form), `kerberos-support=yes`, and in newer versions `ipv6-support=yes` as well.
Okay, I have a modified version of https://github.com/arthepsy/pan-globalprotect-okta that works with my config: https://github.com/nicklan/pan-globalprotect-okta |
@nicklan I tried to compare this to a change I just made to see if our clients were doing similar things, but am having trouble separating your code changes from your whitespaces changes. Do you have a version where the whitespace changes are made separately? |
@aclindsa yeah, I maybe should have stuck with tabs, so it was easier to see, but my emacs really likes spaces :) Umm, |
…rdless of actual OS I've tried, whenever possible not to lie to the server about the client configuration. However, there are now multiple cases where a GlobalProtect server responds with a misleading error when the `ssl-vpn/login.esp` request doesn't contain the exact, magic value of `clientos=Windows`. * dlenski/openconnect#86 ("Assign private IP address failed" unless `clientos=Windows` in `ssl-vpn/login.esp` request) * dlenski/openconnect#116 ("Invalid username or password" unless `clientos=Windows` in `ssl-vpn/login.esp` request) These cases are very difficult to debug because they seem to be suggesting totally unrelated errors. For reliability, this patch makes openconnect always specify `clientos=Windows` in relevant requests, regardless of the actual `vpninfo->platname`. (The `vpninfo->platname` value can still be sent in the "free-form" `os-version` field, as far as I can tell.) Signed-off-by: Daniel Lenski <[email protected]>
…rdless of actual OS I've tried, whenever possible not to lie to the server about the client configuration. However, there are now multiple cases where a GlobalProtect server responds with a misleading error when the `ssl-vpn/login.esp` request doesn't contain the exact, magic value of `clientos=Windows`. * dlenski#86 ("Assign private IP address failed" unless `clientos=Windows` in `ssl-vpn/login.esp` request) * dlenski#116 ("Invalid username or password" unless `clientos=Windows` in `ssl-vpn/login.esp` request) These cases are very difficult to debug because they seem to be suggesting totally unrelated errors. For reliability, this patch makes openconnect always specify `clientos=Windows` in relevant requests, regardless of the actual `vpninfo->platname`. (The `vpninfo->platname` value can still be sent in the "free-form" `os-version` field, as far as I can tell.) Signed-off-by: Daniel Lenski <[email protected]>
Per this comment (#116 (comment)), `clientos=Windows` (or `=Mac`) is required to get the servers to respond correctly when using SAML. This is similar to other cases where the official clients and servers sometimes respond with bizarre misleading errors if `clientos` doesn't have one of the magic acceptable values (see 7f7d739). The official clients also include `os-version` (free-form), `kerberos-support=yes`, and in newer versions `ipv6-support=yes` as well.
Per this comment (#116 (comment)), `clientos=Windows` (or `=Mac`) is required to get the servers to respond correctly when using SAML. This is similar to other cases where the official clients and servers sometimes respond with bizarre misleading errors if `clientos` doesn't have one of the magic acceptable values (see 7f7d739). The official clients also include `os-version` (free-form), `kerberos-support=yes`, and in newer versions `ipv6-support=yes` as well.
…forms, including preliminary SAML support Until recently, I've believed the prelogin.esp to be useless, because the initial GlobalProtect login form always contains the same two fields: username and password. However, the prelogin response is also important for signalling when SAML login is required. When the VPN uses SAML login, the official GP clients redirect the user to a web-based authentication flow (e.g. Okta, dlenski/openconnect#116). That auth flow eventually sends the official client back to the GP VPN, armed with a special cookie field, `portal-userauthcookie` or `prelogin-cookie`, that needs to be submitted in place of the password (already supported by openconnect as of 8b2bc5f). This preliminary SAML support simply includes the SAML method and URL in the form banner, and fails with an error message if the cookie field name was not specified (since it cannot be autodetected). Signed-off-by: Daniel Lenski <[email protected]>
@dlenski did you decide on a way to pass the cookie to openconnect on the command line? |
Yes. You can use the normal password-passing mechanism in OpenConnect v8.x. The only reason this didn't work was because of a bug/oversight, which was fixed in b6dc821: $ echo "COOKIE_FIELD_VALUE" | \
openconnect --protocol=gp -u username --passwd-on-stdin \
portal.company.com/portal:COOKIE_FIELD_NAME You can also use the new, more flexible Does that answer this question? |
In case it's of use to anyone, I've uploaded a simple script that is working for me here: https://github.com/zdave/openconnect-gp-okta/blob/master/openconnect-gp-okta It authenticates directly with the gateway rather than the portal, and only supports Okta's push MFA method. Use like:
As every setup seems to be different I don't expect this will work for many other people, however @ffainelli it ought to work for you as we work for the same company... |
@zdave it does work for me, thanks a lot! Any chance you could drop me an email? |
Inspired by @zdave's nice, simple clean implementation of Okta auto-login (zdave/openconnect-gp-okta)… and by sheer necessity, because I need to use a couple VPNs where the programmatic login simply doesn't work… I created a tool to do the SAML login interactively with a GUI, from the Linux CLI: https://github.com/dlenski/gp-saml-gui It pops up a graphical login window using GTK WebKit2 WebView, then grabs the cookies once you login successfully, and outputs their values so you can use them in a script to connect with OpenConnect. whew |
@dlenski Beautiful, thank you for taking the time to do this! |
is this master ready? |
For anyone who stumbles upon this thread but is looking for something slightly different, I just wrote this and it might be relevant to your case: How to use "openconnect" (via the |
This method works for me , it's updated at 2022. |
The context surrounding this issue is extremely different from what it was 4.5 years ago when the issue was originally opened. Locking to prevent further comments. Open issues on https://github.com/dlenski/gp-saml-gui, https://github.com/zdave/openconnect-gp-okta/blob/master/openconnect-gp-okta, or https://gitlab.com/openconnect/openconnect instead. |
My company uses only Okta to authenticate to GlobalProtect. I've tried lots of ways of calling openconnect but nothing seems to work for me. A couple of representative examples:
or:
Let me know if you need more info, and thanks for the project!
The text was updated successfully, but these errors were encountered: