cancel
Showing results for 
Search instead for 
Did you mean: 

Kerberos 401 authentication with form fallback

Daniel_W__13795
Nimbostratus
Nimbostratus

Hello,

 

we are using APM for SAML authentication. Domain joined machines should authenticate transparently with Kerberos, users without the ability to use Kerberos (non domain joined, Firefox without negotiate-settings) should receive a form to login.

 

Kerberos works fine, but users with non domain joined machines receive a browser authentication prompt and "Authentication required to access the resources.".

 

Does anybody has set up such a scenario? Any help is appreciated.

 

0691T000006ApZZQA0.png

 

39 REPLIES 39

Lucas_Thompson_
Historic F5 Account

I don't immediately see how it's possible to tell if a PC is able to authenticate without asking it via a 401, which produces a browser auth pop-up. Is there anything in the initial HTTP request that you can use to tell this class of clients from the other class of clients?

 

Well, perhaps you could use Group-Policy IEM tool to modify the User-Agent and show the 401 to only those guys via some simple VPE logic? But they would have to use only IE, unless there is some way to do this with Firefox to a group of PCs.

 

https://technet.microsoft.com/en-us/library/cc770379.aspx

 

Hi Lucas, thanks for your response. I already thought about changing the User-Agent so that I can check for this header. For the moment, I could live with the 401 prompt, when I can display the auth form after canceling the 401 prompt. But no matter what I do, I receive "Authentication required to access the resources.", when Negotiate is enabled in the 401 agent.

One possibility is to combine an IP address check and a client check to say "if the client is internal and running Internet Explorer, then they can probably do Keberos; otherwise, show the web form". For failed 401 returning "Authentication required to access the resources.", I think that must be a bug -- if the 401 fails, it should follow the failure branch to e.g. web form.

Sorry, it's not a bug, but is not desirable/expected behaviour either. When APM sends the 401 Unauthorized, the HTTP response content is the error message defined in the APM HTTP 401 Response block. This defaults to "Authentication required to access the resources.". Instead we would want it to return something that caused the client and APM to advance down the fallback path, perhaps like an auto-submit form that caused the fallback path to be executed. I have submitted bug C2012278 to request such an enhancement to the HTTP 401 Response block.

It should advance if the client issues a POST to my.policy. A GET May also do it but haven't tested that in this context. Maybe a bit of JavaScript. Let us know the ID number you get from support, it should be 6 digits.

Hi Lucas -- my case number is: C2012278.

Hi all -- I was able to get a workaround for this from F5 support, which seems to do the right thing. Quoting from the F5 support response: The setup involves checking for the session variable "session.logon.last.authparam". This variable gets set when the client is supporting "Negotiate", it is not set when the client supports "Basic". The necessary steps are listed below: - add "Variable Assign" before "HTTP 401 Response": "session.logon.last.authparam = return {}" (set session variable "session.logon.last.authparam" to blank) - configure "HTTP 401 Response" - "HTTP Auth Level": "negotiate" - "HTTP response message": "" - add "Special_Basic" branch rule: "expr {[mcget {session.logon.last.authparam}] == ""}" (this has to be placed ABOVE the "Negotiate" branch) Now when the client is not supporting Negotiate it goes down the "Special_Basic" branch. I tried it and the result looked to be as expected. If the user is prompted for Kerberos and Kerberos fails then the failure path (designated by the Special_Basic branch) is taken.

Hi Evan, Alternatively, instead of adding the variable assign and using the Special_Basic branch rule, you can try this: - configure "HTTP 401 Response" - "HTTP Auth Level": "negotiate" - "HTTP response message": - For the "Negotiate" branch change the default expression to: expr { [mcget {session.logon.last.authtype}] == "Negotiate" && [mcget {session.logon.last.authparam}] != "" }

Just wanted to say thank you Saravanan as your solution worked for me. Also wanted to note that although the workaround posted by Evan did work I was still having a browser login prompt when using IE11 but it worked fine on Chrome.

 

Thanks

 

Hi,

 

the last solution provided by Saravanan M K worked for me:

 

remove the BASIC_STATIC branch and replace Negotiate branch expression to

 

expr { [mcget {session.logon.last.authtype}] == "Negotiate" && [mcget {session.logon.last.authparam}] != "" }

I also tried removing basic and leaving Negotiate in 401 branch rule but still same issue. Thanks.

 

Further to my investigation with debug I found following line:

 

bigip debug apmd[16352]: 01490000:7: memcache.c func: "mc_convert_session_var_to_mc_key()" line: 2564 Msg: Converted Var: session.logon.last.authparam to Session Var tmm.session.fa70bd95.session.logon.last.authparam

 

It assigned variable to session.logon.last.authparam when I am trying to access URL from outside with session variable as shown above.. so there is no way branch rule in 401 HTTP response will fallback... because session.logon.last.authparam}] != "" will always have variable and it will go to kerberos Auth.

 

@ Alexandre Allaire @ Nolan Jensen @ Lucas Thompson @ Stanislas Piron @ Saravanan M K

 

Ppl who confirmed solution is working.. Can I get some help? what did they do that is different than what I have in my above configuration ?

 

Hey AN, are you still having issues with this functionality? I am working on an issue right now where IE and Chrome WERE functional, but have stopped working. What we've noticed is that the authorization window is still presented, but we can just cancel it, and authentication is successful. It may be related to a Microsoft bug MS16-119. Can you attempt to cancel the login and see if that works?

 

Thanks!

 

Chris Wentland

 

I have been trying to set this up but IE and Chrome on none domain pc's always prompt for credentials.

 

If I change the javascript to alert() I see it runs after the authentication popup so not sure how this will work?

 

If I cancel the authentication popup then the policy follows the fallback to the logon page but this won't be acceptable.

 

Any ideas on pre logon checks to run when source ip will not be an option?

 

AN,

 

I don't have a answer for you but wanted you to know I originally reported this as working. However just had a report today that when I have a non domain joined computer connected to our network the browser will prompt for username and password. You have the configuration the same as I do so appears to be an issue.

 

I can also confirm what Chris said if I cancel the browser login prompt I am then taken to my F5 login page and have no issues getting to allow ending.

 

Stanislas_Piro2
Cumulonimbus
Cumulonimbus
Hi, Did the solution provided by Evan and Saravanan solve your issue? I have the same need (kerberos for domain computers, SAML for others) and this is really helpful for all others to know if you got a solution. I tried the solution on my lab successfully but it's better to know if you validate for production users. Stanislas

Alexandre_Allai
Nimbostratus
Nimbostratus

The solution works but I still have Firefox prompting for credential first. If I cancel it switch back to Kerberos. Any way to force Firefox to use Kerberos prior to basic auth ?

 

Alexandre,

 

In order to have this work on firefox I had to go to about:config > search for network.negotiate-auth.trusted-uris and add the site you are trying to access. This resolved any prompts I had on firefox.

 

I have implemented something similar without the 401 prompt but it requires the hostname of the website to be added to the local intranet sites like Nolan said. I use the ECA Profile to trigger an ntlm auth between clients and then look in the ntlm messages exchanged to get the user name and domain. I need this info to redirect specific domains or non-ad users to a form login. Let me know if you need additional info.

 

Quick question: how does the 401 response kerberos auth work in the case of a web farm? In the apm kerberos sso you put HTTP/% in the spn so that it uses the hostname and talks to the pool member. How does this work in the 401 setup. I tried HTTP/% in the spn name but no luck.

 

In the case where you have multiple sites resolving to a single VIP and (Kerberos) access policy, you'd either need to switch the access policies based on incoming client IP subnet, or overload the APM keytab file to include all of the SPNs and keys.

 

I'm probably missing something here. I have one web application with hostname webapp1.domain.com. The app is running on multiple servers with service account webappsvc@domain.com I have an spn for this service account HTTP/webapp1.domain.com. I generated the keytab file and configured the aaa kerberos server with thiskeytab and i put webapp1.domain.com in the server name. If I put webapp1.domain.com in the hosts file and point it to the ip of one web server the auth works fine. But I have many servers. In the case of kerberos sso with kcd you only need to put HTTP/% in the spn to tell the bigip to talk to one of the nodes in the pool. What do you mean by adding all spns ?

 

By the way here is the flow of NTLM authentication to an IIS server:

 

https://blogs.technet.microsoft.com/mist/2018/02/14/windows-authentication-http-request-flow-in-iis/

 

IIS is a user mode application. It sits on top of HTTP.sys, which is the kernel mode driver in the Windows network stack that receives HTTP requests. IIS picks up requests from http.sys, processes them, and calls http.sys to send the response.

 

IIS, with the release of version 7.0 (Vista/Server 2008), introduced Kernel Mode authentication for Windows Auth (Kerberos & NTLM), and it's enabled by default on all versions. This feature offloads the NTLM and Kerberos authentication work to http.sys. Http.sys, before the request gets sent to IIS, works with the Local Security Authority (LSA, lsass.exe) to authenticate the end user. IIS just receives the result of the auth attempt, and takes appropriate action based on that result.

 

Before diving into both Kerberos and NTLM request/response flows, it's worth noting that the vast majority of HTTP clients (browsers, apps, etc.) don't send any credentials on their first request for a resource. This means that first request is anonymous, even if credentials have been configured for that resource. This anonymous request, when Windows Auth is enabled and Anonymous Auth is disabled in IIS, results in an HTTP 401 status, which shows up as "401 2 5" in the normal IIS logs. Both request flows below will demonstrate this with a browser, and show that it is normal.

 

The NTLM and Kerberos exchanges occur via strings encoded into HTTP headers.

 

If you want to avoid the initial 401 response you have to configue IE and Firefox for that. Chrome picks IE settings:

 

Example: https://support.avg.com/SupportArticleView?l=en&urlname=How-to-configure-silent-authentication-for-S...

 

Kevin_Stewart
F5 Employee
F5 Employee

JoeTheFifth,

 

What do you mean by adding all spns ?

 

You can "overload" the keytab file by using the -in option with ktpass:

 

ktpass -princ -mapuser -ptype KRB5_NT_PRINCIPAL -pass 'password' -in -out c:\keytab.next

You'd run this command for each SPN, adding the resulting key information to the last keytab file.

 

If you want to avoid the initial 401 response you have to configue IE and Firefox for that

 

Even if you put the URL in the browser's trusted intranet sites list, I believe (specifically for Kerberos) that the browser still makes an initial anonymous request.

 

Kevin_Stewart
F5 Employee
F5 Employee

I think we're mixing (client side) AAA and (server side) SSO here. Totally different things.

 

For client side, you create a keytab file that contains the key (or keys) for the SPN(s) that browser clients will be accessing. In your case you have a single site, so you have a single hostname in the keytab file.

 

For server side, you don't use a keytab. Server side Kerberos uses Protocol Transition and Constrained Delegation. CD allows APM to do S4U2Proxy - proxied Kerberos, and PT allows APM to do S4U2Self - which is how it doesn't rely on client side Kerberos to function. Server side Kerberos requires basically 2 things:

 

  • Access to a KDC - to fetch delegated Kerberos tickets to an application. This implies rights to (an account) and a path to (DNS SRV and direct access).
  • The name (SPN) of the account to request a ticket to. This is sometimes the hardest to achieve depending on the nature of the services, but can generally be defined in one of three options:

     

    • A static SPN value (ex. HTTP/servers.mydomain.com@MYDOMAIN.COM) - where all of the target web servers are running under the SAME service account, so no need to have APM try to go figure it out.
    • The %s option (ex. HTTP/%s@MYDOMAIN.COM) - where APM uses reverse DNS from the selected pool member IP to get the name used in the Kerberos ticket request. This would usually be where the servers are each owned by their respective machine accounts. This could also rely on a local Hosts file in lieu of DNS.
    • The %h option (ex. HTTP/%h@MYDOMAIN.COM) - where APM simply uses the client's HTTP Host header as the name to use in the Kerberos ticket request.

The important thing to understand here is that client side and server side Kerberos are completely independent things. Protocol Transition makes server side Kerberos possible as long as you have the two previously-defined things (access and a name).

 

JoeTheFifth
Altostratus
Altostratus

I can't find the QOUTE button so I'm replying to this: Even if you put the URL in the browser's trusted intranet sites list, I believe (specifically for Kerberos) that the browser still makes an initial anonymous request.

 

yes. That's the normal behaviour. See the blog above:

 

Before diving into both Kerberos and NTLM request/response flows, it's worth noting that the vast majority of HTTP clients (browsers, apps, etc.) don't send any credentials on their first request for a resource. This means that first request is anonymous, even if credentials have been configured for that resource. This anonymous request, when Windows Auth is enabled and Anonymous Auth is disabled in IIS, results in an HTTP 401 status, which shows up as "401 2 5" in the normal IIS logs. Both request flows below will demonstrate this with a browser, and show that it is normal.

 

I don't have an issue with that. My only issue for the moment is using multiple servers with a site configured to run under a user account.

 

JoeTheFifth
Altostratus
Altostratus

Hi Stanislas. Do you confirm this works for non-domain users? Like I said earlier the 401 pop up will occur for browsers who do not trust the url/hostname. I don't see how this can work for user (domain or non domain) without putting the url in the intranet trusted zone (ex IE). I understand internal users (domain) get the trusted url configured but that's not the case for non domain or external users. Are you external users trusting the url/hosname?

 

To be honest, I didn't test the solutions that are suggested here in the various answers of this post, but I've worked out a workaround. The workaround I've created uses javascript and the HTML5 Web Worker technology to determine if a browser is willing to perform Kerberos authentication. If so, it will proceed to authenticate the user by using Kerberos authentication. If not, it will fallback to another authentication method, like SAML for example. You can find my solution here:

 

https://devcentral.f5.com/s/articles/APM-Kerberos-Auth-or-fallback-to-another-authentication-method

https://devcentral.f5.com/s/articles/Transparent-Kerberos-Authenticaton-and-APM-fallback-authenticat...

 

bradhanson
Altocumulus
Altocumulus

bumping this as it has been a while since there was activity.. but we are running into the same problem and are on version 14.

Why would APM 401 decide to issue this message "Authentication required to access the resources." and STOP the entire policy evaluation??

It should exit on 'fallback' and provide the access policy to continue and decide what to do..

Other things mentioned (to do some tests BEFORE issuing the 401) seem to be nothing more than a workaround to not get stuck on the 401 and it's ABORT of the policy.

This just makes something that should be so simple very very complicated ... simple .. negotiate/Kerberos fail.. go to fallback.. let the policy issue a login form.

 

I set to basic+negotiate and it will follow the basic path for the user but we don't want to issue the basic credentials box.. We want to issue the login form if it isn't able to authenticate using Kerberos.

 

Before I open a case with support, I am seeing if there are some others who have gone down this path and any other advise.

Much appreciated!!!

Kevin_Stewart
F5 Employee
F5 Employee

It’s actually not that simple, and not really an APM issue. The problem is that there’s no event to fire on. When the client (browser) receives the 401, it has to do something. It’ll either try to satisfy the negotiate request, or fail. And if it fails, it doesn’t send anything back to the server, hence nothing for the server (APM) to trigger on.

 

The prescribed workarounds usually involve making sure the client *can* authenticate, often by making sure they’re on the right network (by source IP).

So you are indicating that the message ""Authentication required to access the resources." is being issued by the browser and not by the APM?

I can't see anything on some quick searches that indicate any such message other than brining up some references to F5 APM.

 

I can do a trace.. I tried the procedure outlined 5 years ago. it doesn't work. If i set to negotiate+basic it follows the basic path, if i set to negotiate it returns "Authentication required to access the resources.".

 

So if it is the browser that is stuck and stops, perhaps firefox or edge would work differently? THanks for your quick response Kevin, much appreciated.

 

Kevin_Stewart
F5 Employee
F5 Employee

No, not what I'm saying. When the server sends its 401, it's also going to send one or more "Authorization" headers, which can either have a value of "Basic", "NTLM", or "Negotiate" (which means Kerberos or NTLM). The browser uses this information to decide how to authenticate. For example, if only a Basic authorization header is sent, the browser can only respond with Basic credentials. If it gets a Negotiate, and it's a member of a domain, it'll try Kerberos or NTLM (with a preference for Kerberos). If, however, it cannot satisfy any of these, it will just fail. It won't send anything back to the server. It won't ask for other options. It will just fail.

 

And since there's no request from the browser if it fails, there's no event for the server (APM) to respond to. APM cannot follow a fallback branch, simply because the client didn't send any request. You can actually see this if you fire up Developer tools in your browser (or Fiddler). It doesn't matter if it's Edge, Firefox, Chrome, whatever. This is how all browsers behave with Windows Integrated Authentication. That you're setting negotiate+basic, and the browser selects Basic, means that the browser itself can't satisfy the negotiate request, so falls back to Basic.

bradhanson
Altocumulus
Altocumulus

Thanks again, Kevin. Appreciate all you are sharing.

So then, we have devices that are not joined to the domain.. or are not setup for Kerberos. Before the 401 query, is there something that can be done to check to see if the client/client browser is joined so a 401 negotiate is only done when they are able to respond?

Our current situation is that some devices don't have a policy that provides for this and they should be presented with a login form by APM.

Think I will open a support ticket to see what they might be able to suggest.

 

JoeTheFifth
Altostratus
Altostratus

You can but it you need a few requirements:

Add the web app hostname or a wildcard domain name like *.mywebapp.com to the intranet zone (ie, chrome) or trusted.uris (firefox). Safari is out of the game here sorry. All devices should do this even people not in your AD domain. This won't work for people coming from the internet but will do for partners coming from an internal network and using your AD domains or a trusted domain.

Now you need an ECA Profile enabled on the VS.

This also requires an NLTM configuration with an computer object created in you Active Directorry.

This way all devices will need to do an NTLM challenge with this computer (F5 computer object created in AD) and you will have to use an iRule to decode the NTLM message and get the user/domain info.

All allowed domains (datagroup list or inside the irule) for which you don't need an APM login page wll do an sso login (automaric login). All the domains not in the allowed list will be redirected to the APM login page.

It's not a straightforward task but I have it all set up and running.

JoeTheFifth
Altostratus
Altostratus

For mobile devices you use certificates to check for allowed domains then either do an apm page or Kerberos sso based on what you get from the device. If no client certificate then go to an apm login page.

Kevin_Stewart
F5 Employee
F5 Employee

That's just it. There are a number of options here. JoeTheFifth is talking about computer checks - the computer or mobile device identifies itself, and you use that information to decide whether or not to challenge the user. And that *usually* gets tracked as an IP address in a table.

 

If you can't manage the client devices though, the easiest option is to divide users by subnet. Authenticate-able users on one subnet, contractors and customers on another... That would be the simplest solution.

 

It's also possible to do "step-up" auth options. Gov customers will often do this. Bring all users to a non-auth landing page and let them choose how to authenticate - AD, client cert, user/pass. Whatever they click on triggers a secondary step-up mechanism. It's not transparent to the user of course, but a reasonable solution nonetheless.

bradhanson
Altocumulus
Altocumulus

Thanks all. Yes I agree, checking their IP can determine if the device is on the internal network. There are cases, however, where a device internal is not joined to the network and Kerberos 401 will fail.

 

It seems it could be possible to alter the response message that is displayed. It would be nice if this was a standard option. A few ideas better than issuing a simple 'Authentication required to access the resources" message. Not quite sure what the URL would be to continue the access policy 'fallback' or another branch on the 401:

  1. Present a login page and the user can complete and submit to continue the access policy. This would provide a familiar set of information that the users are familiar with (the basic login tends to confuse people and not everyone trusts it as they don't know who is asking for their information).
  2. Embed a link to a login page (somehow) <a href>. If there is a URL available that the user could click to respond back to the 401 and hit the 'fallback' or perhaps another custom branch of that step.
  3. Meta http-equiv refresh to the response URL so the user would not need to click anything.
  4. Javascript to handle a redirect to a login page.

Just seems there should be cleaner way to allow the user to proceed, especially when the SSO was initiated by the service provider.

 

Noushad_Vellad1
Nimbostratus
Nimbostratus

I found when refreshing the page, it is falling back to form based logon screen.

So I have just added the below java script to "HTTP response message"

<script>
location.reload();
</script>

 

Screenshots are provided for your reference

 

Noushad_Vellad1_0-1663586409043.png

 

Noushad_Vellad1_1-1663586441810.png