I'm writing a set of WCF services that rely on transport security with Windows Authentication using the trusted subsystem model. However, I want to perform authorization based on the original client user that initiated the request (e.g. a user from a website with a username/password). I'm planning to achieve this by adding the original user's credentials in the header before the client sends the message and then the service will use the supplied credentials to authorize the user. So I have a few questions about this implementation:
1) using transport security with windows auth, I do NOT need to worry about again encrypting the passed credentials to ensure the validity... WCF automatically takes care of this - is this correct?
2) how does this implementation prevent a malicious service, running under some windows account within the domain, to send a message tagged with spoofed credentials. for e.g. a malicious service replaces the credentials with an Admin user to do something bad?
Thanks for any help.
What binding are you using? Is this service only within your corporate LAN, or do you plan to go outside the firewall?
To answer your question (as far as I can)
1) With Windows authentication over transport security, the transport layer will be encrypted and safe - no need to worry about additional encryption of credentials etc.
2) It cannot. If a malicious service manages to "hijack" some valid Windows credentials and poses as "John Doe" who has an account on your corporate network, there's no way the WCF service can distinguish this from a valid request by John Doe.
Related
I've been using wcf for a while and its authentication mechanisms, Windows, UserName/Password, Client certificate for a while.
I'd like to better understand how WCF uses these authentication mechanisms internally when creating SOAP messages and sending them.
Specifically, are the authentication credentials passed by wcf in every SOAP request, or does it only pass the authentication credentials in the first request and then some kind of token is issued and passed back and forth during subsequent sessions?
Are these authentication credentials (username+password, windows, client certificate) passed in a different manner depending on whether the security mode is transport or message? Is it that in message mode, the authentication credentials are inside the SOAP message, while in the transfer mode, http headers are other transport protocol specific are used to pass the authentication credentials?
Lets just assume that the SOAP message is secured using https when Transport mode is used and encrypted when using Message Mode and not worry about message privacy or tampering for this question.
You've asked several big qeustions, but I'll try to answer the question about sessions.
Session and authentication handling depend on the binding you're using. If you're using basichttpbinding, for instance, the host basically acts like a web server and no persistant "sessions" are created; as a result each SOAP request you send must contain everything necessary for authentication on the host. However, there are some bindings available like WSHTTPBinding that allow for the creation of security and reliability sessions that persist after the initial authentication using a token.
Wrapping the message in SSL should prevent problems.
I am trying to call a Sharepoint Web Service via WCF from inside a .ASHX on a different server. My code works if I run inside of Visual Studio's debug web server, but not from IIS. The working server works in various authentication modes (Kerberos, NTLM), and the non-working one doesn't work in any. I am impersonating the same user in both cases.
Using NTLM, I recorded a working session and non-working session in Wireshark. In the working one, Wireshark parses the NTLM data and reports a DOMAIN and USER NAME that I expect. In the non-working one, it shows
DOMAIN: NULL
USER NAME: NULL
I have debugged in IIS and impersonation is definitely working at the point of the service call. If I check WindowsIdentity.GetCurrent(), it's the user I expect.
If I inspect the WCF service proxy on the working and non-working servers, they look identical -- the part that deals with ClientCredentials is set to "" for Username and Password for both versions.
Any ideas on what else to check? Why would the NTLM data have DOMAIN and USER NAME set to NULL -- where does it pick that up from?
According to this:
http://support.microsoft.com/kb/207671
When IIS services an HTTP request, IIS performs impersonation so that access to resources to handle the request is limited appropriately. The impersonated security context is based on the kind of authentication performed for the request. The five different types of authentication available from IIS 4.0 are:
Authentication Type Impersonation Type
------------------------------------ ---------------------
Anonymous Access (no authentication) Network
Auto Password Synchronization is
ON (ON=default)
Anonymous Access (no authentication) IIS Clear Text
Auto Password Synchronization is OFF
Basic Authentication IIS Clear Text
NT Challenge/Response Authentication Network
Client SSL Certificate Mapping Interactive
In my case, I have a Network Token, but
Network tokens are "NOT" permitted to access network resources. (Network tokens are named so because this kind of token is traditionally created by a server when a user is authenticated across the network. To allow the server to use a network token to act as a network client and access another server is called "delegation" and is considered a possible security hole.)
The KB has many possible ways to avoid the problem
We are using WCF services. Right now, we are using Windows Auth but this is not for long. Some services will sit outside the firewall and use username/password verified in the database.
My tech lead is "scared" at how easy any user can "Add Reference" to the services we have and just party on. He wants to "guard" the services by adding another identity - the application. He wants the service to accept requests from certain applications so the certain users cannot just use the service - add reference to it and call. It’s the notion of the application having an identity + credentials that is the operative principle here, as services on the network may need to authenticate those credentials prior to fulfilling a request, in order to prevent rogue code inside the network (i.e., NOT the application) from accessing services using “Joe User” end-user credentials.
Does this make any sense?
Then he believes the Juval Lowy's book has, in an Appendix that discusses sending more than one identity during a WCF call (Security Interceptor). There is no specific suggestion that all of those have to be end-user identities and if that is the case, one of those could be the identity of the application making the request.
How can this be done?
Thanks,
Sam
The problem with sending an application identity is that the secret used to confirm that identity has to be stored somewhere. If it is visible to one application on a machine then generally it will be visible to other applications running under the same identity.
Would your manager be happy with "it came from an authorised machine"? If that's the case you could simply use Client Certs
Its also worth taking a step back: if the user is authenticated and is authorized to perform the functionality they have requested, why do you care which application they came from - if they are who they say they are and they are allowed to do what they are requesting then why couldn't they use, say, fiddler to make the request - isn't that the point of a service (rather than a closely coupled client server app)?
You might want to look through Common Security Scenarios in the MSDN documentation to see if any of those options fit your needs.
The options that pops to my eye are Transport Security with Certificate Authentication and Message Security with Mutual Certificates. Both rely on X.509 certificates. The latter option is on the message level, so you can handle certificate delivery and security negotiation however you want.
To make it a lot harder for someone to add a reference to your service you could just remove the mex endpoint. This way it would be very difficult for a stranger to create a valid request message.
You can then distribute the WSDL manually, only to people you trust.
I have a web service hosted in IIS 7 that is to be called from a WCF client that runs in a different domain.
Currently, the wsHTTP binding has been configured using default settings. When the call is made the service complains that the client couldn't be authenticated (Message : The request for security token could not be satisfied because authentication failed.). I guess this is because it's trying to use windows authentication and the clients ID cannot be validated against the AD server of the service.
What's the best way to get around this? Can the service be configured to run under the ID of a local account? How best to check the call has come from authorised client? I'd rather avoid certificate generation and management if possible. Ideally, I'd authenticate the client by username / password by then have the service operate under it's own local ID - to gain access to resources on the service server.
Any advise gratefully received.
Thanks
Rob.
You can use user name and password but your service should use certificate if you don't want to send user name and password in plain text. Your option is either:
HTTPS with user name and password in message
Message security with user name and password in message
Both requires certificate.
Here's a good tutorial that I used to do just that.
http://www.codeproject.com/KB/WCF/wcf_https_usernameauth.aspx?msg=3527563#xx3527563xx
(I tried searching, but couldn't find any truly helpful links.)
We are implementing a set of WCF services. What I would like to do in these services is have the clients (which will be trusted application servers) be able to pass a token of some sort to the web service to authenticate. I do not want to be required to pass username/password on the initial or subsequent requests (because in some cases the calling application server may not have the password). Windows and Kerberos are not usable in our specific circumstance.
I had thought to just create a simple custom UserNameSecurityTokenAuthenticator class and modify it so that if the password is empty, it takes userName as the string-encoded token value (obviously checking the token itself to verify that it's valid at that point), but if the password is not empty, forwarding on the username/password to a MembershipProvider for checking. Basically I'd like to overload the username/password authentication to provide for token passing as well.
Is this possible? Can I simply plug in a token authenticator like this, or is there some other simple way to "intercept" requests like this (and update the actual username value from the decrypted token)?
Or is there some other incredibly simple way to allow the client to pass a custom token and have the server accept it that I'm just missing?
If it's a fairly controlled environment and not too many clients involved, then I'd try to set up something along the lines of the B2B scenario securing the transport link using certificates on both ends.
Certificates are not bound to Windows or an AD domain, and setting them up is a one-time job.
Read more about that WCF security scenario:
MSDN: Transport Security with Certificate Authentication
Fundamentals of WCF Security: Business Partner Applications
. WCF Security How-To's