Learn F5 Technologies, Get Answers & Share Community Solutions Join DevCentral

Filter by:
  • Solution
  • Technology
Answers

Kerberos 401 authentication with form fallback

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.

Image Text

1
Rate this Question
Comments on this Question
Comment made 20-Feb-2016 by Stanislas Piron 9621
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
0
Comment made 2 months ago by JoeTheFifth 301

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?

0

Answers to this Question

placeholder+image
USER ACCEPTED ANSWER & F5 ACCEPTED ANSWER

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

1
Comments on this Answer
Comment made 15-Jan-2016 by Daniel W. 277
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.
0
Comment made 15-Jan-2016 by Evan Champion 275
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.
0
Comment made 16-Jan-2016 by Evan Champion 275
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.
0
Comment made 17-Jan-2016 by Lucas Thompson
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.
0
Comment made 19-Jan-2016 by Evan Champion 275
Hi Lucas -- my case number is: C2012278.
0
Comment made 24-Jan-2016 by Evan Champion 275
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": "<script type="text/javascript"> window.onload = function () {window.location.reload()} </script>" - 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.
2
Comment made 28-Jan-2016 by Saravanan M K
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": <script type="text/javascript"> window.onload = function () {window.location.reload()} </script> - For the "Negotiate" branch change the default expression to: expr { [mcget {session.logon.last.authtype}] == "Negotiate" && [mcget {session.logon.last.authparam}] != "" }
2
Comment made 10-Feb-2017 by Nolan Jensen 158

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

0
Comment made 12-Sep-2017 by AN 165

@ Saravanan M K and Evan,

I tried your solutions and it didn't work for me... For Non-Domain computer I am getting login prompt (not login page) and it fails after two attempts. I had message box and found it was failing at kerberos Auth. Why it doesn't fallback on 401 response instead? I am running BIG-IP 12.1.1 Build 2.0.204 Hotfix HF2. Did I miss something ?

Image Text Image TextImage TextImage Text

0
Comment made 12-Sep-2017 by Stanislas Piron 9621

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}] != "" }
0
Comment made 13-Sep-2017 by AN 165

Hi Stanislas,

I've also tried Saravanan M K's solution. I found it still goes to Kerberos Auth and doesn't fallback to 401 responses. Following what I have: Image Text

Image TextImage TextImage Text

0
Comment made 13-Sep-2017 by AN 165

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

0
Comment made 13-Sep-2017 by AN 165

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.

0
Comment made 18-Sep-2017 by AN 165

@ 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 ?

0
Comment made 07-Nov-2017 by Chris Wentland 328

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

1
Comment made 15-Apr-2018 by Rich M 109

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?

0
Comment made 4 months ago by Nolan Jensen 158

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.

0
placeholder+image
USER ACCEPTED ANSWER & F5 ACCEPTED ANSWER

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 ?

0
Comments on this Answer
Comment made 03-Mar-2017 by Nolan Jensen 158

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.

0
Comment made 2 months ago by JoeTheFifth 301

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.

0
Comment made 2 months ago by JoeTheFifth 301

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.

0
Comment made 2 months ago by Kevin Stewart

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.

0
Comment made 2 months ago by JoeTheFifth 301

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 ?

0
Comment made 2 months ago by JoeTheFifth 301

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-SSO

0
placeholder+image
USER ACCEPTED ANSWER & F5 ACCEPTED ANSWER

JoeTheFifth,

What do you mean by adding all spns ?

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

ktpass -princ <spn> -mapuser <user> -ptype KRB5_NT_PRINCIPAL -pass 'password' -in <last keytab> -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.

0
Comments on this Answer
Comment made 2 months ago by JoeTheFifth 301

I don't have multiple spns for the moment. This will come later. I have multiple servers serving the same site which is running under the same service account. So I need only one keytab file. But what I need here is the setting like the wildcard HTTP/%h used in the Kerberos SSO to forward the request to the pool member. Right now I have to add webapp1.domain.com to the host file and put the ip of one single web server. Let me know if this is not clear. thanks

0
placeholder+image
USER ACCEPTED ANSWER & F5 ACCEPTED ANSWER

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).

0
Comments on this Answer
Comment made 2 months ago by JoeTheFifth 301

Right. I have a KCD setup already running. Now. Can you point me to a rssource to acheive this: hotname (url which users will be targetting) is registred in dns as: hostname = IP of virtual server On this VS I have a 401 (kerberos only) access profile I imported the keytab file of the user under which the site is running in IIS. I created the kerberos aaa server. I added webapp1.domain.com to the bigip hosts file => webapp1.domain.com = webserver1 ip. Let's say I have 2 servers. Now users put webapp1.domain.com in their browsers and are redirected to the VS. The access profile policy runs and everything is fine. But I'm using only one server here. how does this setup work in a farm setup !! How can I make APM look for the SPN HTTP/webapp1.domain.com on both servers when choosing the node from the VS pool. I'm sure this hasn't been done to be used with one web server. I'm certainly missing a configuration step here. May be a variable assign or a another way of doing this.

0
Comment made 2 months ago by Kevin Stewart

We're still mixing up AAA and SSO here (KCD = SSO). AAA and SSO have nothing to do with one another. In fact, you can completely remove the AAA (401 and Kerberos auth) from the access policy, and Kerberos SSO will still work as long as you provide a user name to delegate for. So, if you have two or more servers in a pool, and those servers are all using the same IIS service account, you need only apply a static SPN in the SPN Pattern field. When you do this, APM doesn't have to lookup the server's SPN.

Otherwise, the VIP that the client talks to should also be completely independent of the servers in the pool. The client doesn't have to request a name that matches a pool member SPN. The client only needs to match the name in the AAA keytab file, which could be from a completely different AD account.

So let's say you have three servers in the pool, webserver1, webserver2, webserver3, and they're all running under the same IIS service account - "webserver". You'd have a single (static) SPN then - HTTP/webserver.domain.com@DOMAIN.COM. This is the value you'd use in the APM Kerberos SSO SPN Pattern field, and this is the name APM would use to fetch a delegated Kerberos ticket.

The client browser, however, has no idea what the pool members are, and shouldn't. Let's say the client resolves the VIP to https://www.site.com. In the APM Kerberos AAA, you'd create a keytab using this name (HTTP/www.site.com@MYDOMAIN.COM), potentially from a different AD account which doesn't have to be part of any IIS service.

The client accesses the site (https://www.site.com), gets an initial 401, fetches a Kerberos ticket for HTTP/www.site.com, and presents that to APM. APM validates this via the Kerberos auth agent in the VPE, and client side Kerberos is complete. APM SSO then performs Kerberos Protocol Transition by taking the username from the client side auth (via the session.logon.last.username variable) and does an S4U2Self to get a TGT for the delegation account on behalf of the user. APM then selects a pool member. Depending on how you have the SPN Pattern defined, APM will either use the client side HTTP Host header as the server name (%h), look up the name from a reverse DNS request of the selected pool member IP (%s), or simply use the static SPN string (if all servers are using the same account). APM will use this name to fetch a delegated Kerberos ticket, and then send the HTTP request to the selected pool member with a preemptive Kerberos Authorization header (doesn't wait for a 401).

The only link that client side auth and server side auth have is the username derived from the successful client side auth.

0
Comment made 2 months ago by JoeTheFifth 301

Ok Got it to work. The confusion was on the DNS setup. So far I've been testing with an APM policy using KCD. So I only used hosts files on client computers and of course KCD does not require a hosts file entry on the bigip to work. The wildcard HTTP/%h works fine to pick up the hostname so the kerberos sso goes on. In the case of a Kerberos 401 response the bigip needs to lookup the hostname/spn registred in the keytabfile. So I added the entry site.domain.com = VS ip (we are talking about the same VS which is serving the web site and which is using the access policy). In production the BigIP will use DNS to lookup the hostname. That's why I found it confusing. In the kerberos SSO configuration the bigip is able to target one of the nodes for in the kcd process using the site hostname. in the AAA configuration it needs DNS or a hosts file entry telling it that the site hostname is the same VS IP the user is targeting. This is maybe designed so that you can use multiple VSs for different purposes but it was confusing in my case. So problem solved. It was stated in the support guide but i've been playing so much with the KCD setup I completely overlooked the DNS lookup config and my test computers use hosts files.

Thanks for the help Stewart. Now if you have a few minutes to look at my next question here: https://devcentral.f5.com/questions/grab-username-domain-from-a-kerberos-ticket-header-62018

0
placeholder+image
USER ACCEPTED ANSWER & F5 ACCEPTED ANSWER

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.

0