Kerberos/negotiate S4U2proxy authenticate on behalf of user - kerberos

I would like to do authentication at proxy on behalf of user via Kerberos/Negotiate protocol.
user will authenticate with form login with server, server knows the who the user is, and server has to authenticate to backend server on behalf of user using kerberos.
Please help me with sample code or point me to some good references.
thank you in advance
-csr

Michael: the OP is asking about what MS calls "constrained delegation," the S4U Kerberos extension they invented, rather than the standard delegation (TGT forwarding) to which you're referring.
CSR: first off: is the user providing their Kerberos password in your "form login?" If so, you don't need to use S4U; you can just kinit with the password and get credentials directly.
If not, then this is indeed one use case for which S4U is intended. You didn't say, but I'll assume you're in a Windows environment, although S4U has been added to MIT Kerberos as well.
Rather than have the client forward a TGT, S4U allows the domain administrator to authorize a service principal to independently impersonate any user to a limited set of other services. To enable a service for constrained delegation:
MMC "Users and Computers" snap-in
select the properties for the service account
"Delegation" tab
"trust... for delegation to specified services"
In your case, you'll also need to set "use any authentication protocol;" this enables "protocol transition." If your service were authenticating the user with Kerberos, you could have the DC require the service to present a recent ticket from the client, proving it has some business doing this. Since you're using different authentication method, though, you have to forgo that check; that's what protocol transition does.
I'd start here for understanding S4U: http://msdn.microsoft.com/en-us/library/cc246071(PROT.13).aspx.
I have written a patch for Apache mod_auth_kerb implementing constrained delegation for Unix web services, so it does in fact work. :)

Have the client to send a forwardable (OK-AS-DELEGATE) ticket to you. You can extract the TGT from that and impersonate to perform your task. This works in my case when I receive a service ticket from IE or FF and bind against the AD for the user.

Related

SPA webapp SSO federation

I have an SPA web app using openidconnect for authentication and authorization with local keycloak.
This app is now moving to an windows onprem infrastructure using AD, kerberos tickets and a central SSO.
users log in in their windows session, and then we shall be able to transparently login in our SPA web app. (ie with out entering credentials)
How can I convert kerberos ticket/authentication into Openidconnect world? Where is the magic?
Shall we add some kerberos in our app?
how can we retrieve our access token containing the user role?
thanks
Your SPA should continue to talk to Keycloak using OIDC, and no code in the SPA should need to change. Your APIs will also continue to receive the same access tokens.
You should only need to configure Keycloak to use AD for authentication as an LDAP data source. Here is an article on how to do that. It is an infrastructure job rather than just a coding one, so I would recommend collaboration with AD administrators on the environment setup.
AD is only one possible authentication method, and by doing things this way you keep your options open. You are likely to need to perform account linking, eg to identify users the same before and after the migration. There may be some data setup involved here, eg ensure AD has the same emails as the existing system.

What is the use of the pre-auth user in SPNEGO SSO configuration?

I'm using SPNEGO in order to implement SSO solution. During the configuration, I was required to use domain user credentials in 2 steps:
In the web.xml of my application:
<init-param>
<param-name>spnego.preauth.username</param-name>
<param-value>myuser</param-value>
</init-param>
<init-param>
<param-name>spnego.preauth.password</param-name>
<param-value>mypassword</param-value>
</init-param>
In the setspn command: setspn -A <mySPN> myuser
When I used this configuration, the username of the user "myuser" was retrieved by the Java application using getRemoteUser(). So the SSO worked fine. But when I tried to open a session as other users (on the same windows server) it worked also, so I am a little bit confused. This led me to these questions:
Why did the SSO work for all the other users of the domain? Do I have to use the same user in both web.xml and setspn command? And which user to choose? What's the exact use of the SPN in the Kerberos scenario? Do I have to execute the command setspn in every windows computer or there is a way to do it just once?
This account is part of what defines the server's identity within Kerberos.
Kerberos is a symmetric-key protocol. Each user has a symmetric key that's shared between the user and the KDC, and similarly each service (acceptor) has a symmetric key that's shared between the service and the KDC.
When a user requests tickets for a specific "service principal", the KDC will return them encrypted using that service's key. So in order for a service to decrypt those Kerberos tickets, it also needs some way to know the key associated with its own service principal.
Often, the service key is generated randomly and provided through a "keytab" file. However, in Active Directory systems, most service accounts are regular user accounts which have a password – so their key can be derived from the service's password instead.
It seems that your SPNEGO module supports both methods (see lines 150-160) – it can be given a keytab or a password.
In any case, the setting has absolutely nothing to do with the clients that will be connecting to your service. It only establishes the server's own identity.
What's the exact use of the SPN in the Kerberos scenario?
It's similar to the domain name field in HTTPS certificates. For example, when a browser performs Kerberos authentication to https://example.com, it will always request a Kerberos ticket for the SPN HTTP/example.com from the KDC.
If you're familiar with OAuth2 or SAML or JWTs, I believe the Kerberos SPN would be the rough equivalent of the "audience" field in SAML assertions, or the "aud" field in JWTs.
(Note that the browser only knows your service by its SPN, and doesn't care about the actual service accounts that are used behind the scenes – e.g. Active Directory happens to map SPNs to real "user" accounts in this case, but other Kerberos implementations do it differently)
Do I have to use the same user in both web.xml and setspn command?
Yes, it needs to be the same user, because the service must be able to decrypt tickets that were issued for its SPN, so it needs to know the same symmetric key.
And which user to choose?
Create a new, dedicated account just for that service. Do not use a real "person" account.
Use a long, highly random password, and mark it as non-expiring. Additionally, make sure to enable both "Account supports Kerberos AES xxx-bit" features in the account's options (assuming your Java SPNEGO thing supports AES, which it really ought to).
Do I have to execute the command setspn in every windows computer or there is a way to do it just once?
No, it doesn't matter where you execute it, because it only edits the actual account on the domain controllers – it leaves no trace on the local machine. (Specifically, it sets the servicePrincipalName LDAP attribute for the provided account.)
Clients only recognize your service by its SPN, and they have no need to know about the account mapping that's done by the KDC behind the scenes.

SSO using Kerberos on Windows and Linux

We have a client/server based application that is developed internally. Clients and server communicate over a TCP/IP connection with an application-specific protocol. The clients run on Windows and the server runs on Linux. All machines are in the same Active Directory/Kerberos domain/realm.
Currently, the user enters a username and password when they start the application. The server checks the username and password (authentication). Based on the username, the server also determines access to resources (authorization).
We want to add Single Sign-On (SSO) capabilities to the application. That is, we do not want the user to enter a username and password but we want to automatically logon as the current Windows user.
Of course, determining the current Windows user has to be done securely.
I have come up with the following setup:
I use SSPI (Negotiate) on Windows and GSSAPI on Linux.
When the client connects to the server, it uses AcquireCredentialsHandle (Negotiate) to get the credentials of the current Windows user.
The client uses InitializeSecurityContext (Negotiate) to generate a token based on these credentials.
The client sends the token to the server.
The server uses gss_acquire_cred() to get the credentials of the service. These are stored in a .keytab file.
The server receives the token from the client.
The server uses gss_accept_sec_context() to process the token. This call also returns the "source name", that is the current Windows user of the client.
The server uses the "source name" as the username: the server performs no additional authentication. The server still performs authorization.
This works but I do have some questions:
Is this secure? It should not be possible for the client to specify any other username than the Windows user of the client process. If a user has the credentials to create a process as another user (either legally or illegally) than this is allowed.
Should I perform additional checks to verify the username?
Are there alternative ways to achieve SSO in this setup? What are their pros and cons?
What you've described here is the correct way to authenticate the user. You should not have to worry about the user specifying a different name; that's what Kerberos takes care of for you.
If the client is able to obtain a service ticket, then they must have been able to authenticate against the KDC (Active Directory). The KDC creates a service ticket that includes the user's name, and encrypts it with the service's secret key.
The client would not be able to create a ticket for the server with a fake name, because it doesn't have the necessary key to encrypt the ticket.
Of course, this all assumes that you've set everything up correctly; the client should not have access to the service's keytab file for example, and the service should not have any principals in its key tab except its own.
There's a pretty detailed explanation of how it works here.

How does SPN with Kerberos works

As I understand it,
SPN is an authenticating tool for windows services.
Kerberos is a
user authentication service
SPNEGO-GSSAPI is the third party API to
be able to use those services.
SSPI : is the Neutral layer to send
request from SPNEGO to SPN service.
Am I completely lost?
Trying to figure out how it works but information, is either too precise or not enough.
Ok a more verbose answer:-
SPN - Service Principal Name. It is an identifier associated with each account in a KDC implementation(AD, OpenLDAP etc). Basically if your account acts as a service to which a client authenticates, the client has to specify "who" it wants to communicate to. This "who" identifier is the SPN. This is the strict definition. Many people often call the client name (UPN - User Principal Name) of a service as SPN. This happens when the service itself may act as a client( google the delegation scenario ). This is not strictly correct but widely assumed true.
Kerberos is a protocol for authentication. It is a name for a framework. It involves a third party server(called KDC or Key Distribution Centre) and involves a series of steps of acquiring tickets(tokens of authentication). It is really complicated so http://en.wikipedia.org/wiki/Kerberos_(protocol)
To some extent you got this right. GSSAPI is an API but SPNEGO is not. GSSAPI is technically agnostic to the auth mechanism you use, but most folks use it for kerberos authentication. SPNEGO is a pseudo mechanism, in the sense it declares an RFC for authentication based communication in HTTP domain. Strictly speaking SPNEGO is a specification but most folks also consider it as an implementation. For instance, Sun and IBM JDK provides "mechanism providers" for SPNEGO token generation but GSSAPI is used to actually call it. This is done in many projects(Tomcat as a Server is and example that come to the top of my head and one of the folks who answered this question developed it).
SSPI is an analogue to GSSAPI in windows. Its a different API which ends up doing something very similar to GSSAPI.
Not quite.
SPN simply means 'Server Principal Name' and is the AD or Kerberos slang for the service you try to authenticate against.
Kerberos is a user authentication service, more or less yes. It also provides security for network messages and calls between services.
SPNEGO-GSSAPI* is a kind of strange beast. GSSAPI (Generic Security Service Application Program Interface) is an API to (in principle) different authentication services, it provides negotiation of the mechanisms used. Often the only mechanism available will be Kerberos though. It is the usual API to attach 3rd party programs to Kerberos when you are on Unix (defined in various RFCs, for example RFC 2743 )
On the windows platform SSPI is the generic layer, so it compares to GSSAPI.
SPNEGO is kind of a strange hybrid. It is a mechanism to be used in SSPI, HTTP Auth or GSSAPI which negotiates another auth protocol (for example Kerberos or NTLM if you are on Windows), so it basically does the same thing GSSAPI does again in a different way.
Typical uses of SPNEGO are HTTP authentication to a windows domain, for example IIS uses it if you use 'Integrated windows authentication'. It is also used when you select the 'Negotiate' options for SSPI. See for example RFC 4559
Almost all of your understandings are wrong.
Here it goes:
SPN: A specific service-class is bound to a specific account, e.g. HTTP to www.stackoverflow.com => HTTP/www.stackoverflow.com#STACKOVERFLOW.COM
Yes
3./4. GSS-API (Unix)/SSPI (Windows): Mechanism neutral API to interact with. E.g, Kerberos 5, NTLM, SPNEGO, etc.
SPNEGO: It is one of many mechnisms supported by GSS-API/SSPI. It is actually a pseudo-mech.

Kerberos delegation and port-specific SPNs

I have a system in which I use Kerberos with simple delegation to have an AD user's credentials forwarded from a website to a downstream HTTP REST service using integrated Windows authentication. All servers are Windows Server 2012 R2.
This works great.
The issue comes when I started doing Powershell remoting to the same servers that my backend HTTP service runs on. Enter-PSSession makes a Kerberos auth request for the WSMan service on the target machine. AD sees this request, and encrypts the requested ticket with the identity that my custom HTTP service runs as, which the WSMan service obviously cannot use, and remoting fails.
I know it's possible to force IE to do port-specific SPN requests (via KB908209), but I have not been able to have the 2nd hop (i.e. the IIS-brokered request) to do a port-specific request. Nor have I been able to get powershell to make a port-specific request on 5985 for WSMan.
To make things more concrete:
Client browser makes a request to ServerA. Browser makes a Kerberos ticket request to AD for HTTP/ServerA, which is granted and then sent to ServerA.
ServerA wants to make a delegated request to http://ServerB:15200.
ServerA makes a request to AD for a Kerberos ticket for SPN HTTP/ServerB. It does not make a request for SPN HTTP/ServerB:15200. I want it to.
If I have my SPN set up as HTTP/ServerB:15200, simple delegation in IIS fails, but powershell remoting works. If I have my SPN set up as HTTP/ServerB, simple delegation works but powershell remoting fails. If I have my SPN set up as HTTP/ServerB:5985, nothing works.
I am totally stumped at this point -- doesn't seem like delegation and per-port SPNs play nicely together?
You can workaround this by setting up an alias for ServerB, give the HTTP/ServerBAlias SPN to the IIS account and HTTP/ServerB to the PS account, and then make ServerA send its requests to ServerBAlias. Or use the FQDN (e.g. ServerB.domain.local) in one SPN and the NETBIOS in the other (e.g. ServerB).
Or, you can look at how this person hosted WinRM in IIS with a custom account.
Do you have ms-DS-Allowed-to-Delegate-to attribute for HTTP/ServerA set to the list of HTTP/ServerB and HTTP/ServerB:15200?