403 Error Web App to Web App with Client Certificates


P

Peter Sedman

Hi,

I'm trying to write a ASP.NET application that calls another ASP.NET
application using the HttpWebRequest class.

I need to secure the communicate with Client Certificates. I'm adding a
certificate to the request but get a 403 error when running.

I've read that this was a problem with the ASPNET process not being able to
access the certificate store and that a hot fix is available but it will be
part of the .NET Framework 1.0 service pack
(http://support.microsoft.com/?id=817854). We're running .NET Framework
1.1, presumably it's part of this?

Here's my code, I get a 403 error when it hits the req.GetRequestStream
line:

Private Sub PostData(ByVal req As HttpWebRequest, ByVal data As Byte(),
ByVal CertFileName as string)
Dim x509Cert As X509Certificate =
X509Certificate.CreateFromCertFile(CertFileName)
req.ClientCertificates.Add(x509Cert)

' Open data stream for the request and write data (SEND) and close
stream
Dim outputStream As Stream = req.GetRequestStream
outputStream.Write(data, 0, data.Length)
outputStream.Close()
End Sub

Anybody have any ideas how I can get this to work?

Thanks,
Peter
 
Ad

Advertisements

S

Steven Cheng[MSFT]

Hi Peter,

Thank you for the posting. Regarding on the issue, I am
finding proper resource to assist you and we will update as soon as posible.

Regards,

Steven Cheng
Microsoft Online Support

Get Secure! www.microsoft.com/security(This posting is provided "AS IS",
with no warranties, and confers no rights.)
 
M

[MSFT]

Hi Peter,

For 1.1 framework :
821156 INFO: ASP.NET 1.1 June 2003 Hotfix Rollup Package
http://support.microsoft.com/?id=821156
Along with this fix you will need to install the client certificate under
the Local_Machine registry hive and not the Current_User hive. You will
then need to give the ASP.Net account access to the private key for the
client certificate to get all of this to work. You can use KeyWiz.EXE for
this purpose.

Also, you may consider following solution:

Invoke the Web service from a Serviced Component, and use a Microsoft
Windows service to automatically load the profile of the certificate user
so that the Serviced Component can retrieve the client certificate and then
communicate with the Web service over SSL.

1. Create a Windows service program with only one function to run under the
certificate user identity.

2. Create a Serviced Component that runs under the identity of the
certificate user.

3. Move the authentication code from the ASP.NET application to the
Serviced Component. Verify that the Serviced Component runs under the
identity of the certificate user.

4. Call the Serviced Component method from the ASP.NET Web application.

Hope this help,

Luke
 
P

Peter Sedman

Hi Luke,

Thanks for the reply. The url you provide for the June 2003 Hotfix Rollup
Package is confusing. In the web page it has a download url for .Net
Framework 1.1 Service Pack 1 and then a couple of paragraphs on the
following appears:

"To resolve this problem immediately, contact Microsoft Product Support
Services to obtain the hotfix. For a complete list of Microsoft Product
Support Services phone numbers and information about support costs, visit
the following Microsoft Web site:
http://support.microsoft.com/default.aspx?scid=fh;[LN];CNTACTMS
"
Do I download the .NET Framework 1.1 sp 1 or contact MS to get the hotfix?

Thanks
Peter
 
M

[MSFT]

Hi Peter,

Has the problem been resolved? If you need further assistance, please feel
free to let me know.

Luke
 
Ad

Advertisements

K

Kim Hellan

Hi,

I'm also having the exact same problem as Peter.
So could you please post in this group the answers to Peters hotfix and
keywiz.exe questions?

Thanks,
Kim
 
J

jlento

I have a similar, yet different problem.

I have a .dll that I've been able to successfully run in both a test and
production environment that does a WebRequest.Create() and a
request.GetResponse() with a digital certificate attached.

Everything works fine when I put a Windows frontend in front of my .dll.
However, when I put an Web page in front of my .dll, the server I am dealing
with returns an HTTP 403 Forbidden error.

When I do a hash of the HttpWebRequest object created with the Windows
frontend, I get the exact same hash every time. When I do a hash of the
HttpWebRequest object created with the Web page front end, I get a different
hash eash time. Obviously there's a difference in how the HttpWebRequest
object is being created depending upon the front end being used and this
difference is the source of my problems.

I initally thought of instantiating the request object using the Windows
front end, then serialize the object and save it to a database. Subsequent
calls would de-serialize the request object and use it. Trouble is, the
request uses a variable query string, which as far as I can tell must be in
place at the time Create() is called. There's no way to set this property
after the object has been instantiated
 
Ad

Advertisements

J

Joe Kaplan \(MVP - ADSI\)

Are you sure the client certificate private key is available to the account
that is running the web code? That seems like the most likely reason you
would get a failure.

Joe K.
 
J

jlento

Joe,

As far as I can tell - Yes.

When I step through the code both with the windows and the web front end,
the certificate retrieved hashes to the same value. However, is simply
obtaining the certificate and attaching it to the request enough? Are there
some permissions that need to be set somewhere to allow the certificate to be
used?
 
J

Joe Kaplan \(MVP - ADSI\)

Are you supplying the certificate from a file? One thing to keep in mind is
that no matter how you tell the client which certificate to use, Windows is
still going to try to get the private key for the certificate by looking for
that in the available CSP containers. It is stored separately from the
certificate and is protected by the OS.

If the identity you are running under is different in both cases (check
System.Security.Principal.WindowsIdentity.GetCurrent().Name), then the CSP
containers that are available will be different too as there is a "per user"
store and a machine wide store.

If the cert private key is installed in the machine wide store, then I think
this will work or if it is installed in the store for the user running the
code. I'm not a great expert at crypto key containers, so I'm not the best
person to ask all the details on. I just know that this is a common issue
that comes up.

Joe K.
 
J

jlento

Joe,

I'm looking at that right now.

It looks like the only accounts that have access to the private key are me
and the system.

I'm assuming that ASPNET is the user running the .dll when using the web form.

Do you know anything about the winhttpcertcfg tool? I'm trying to grant the
ASPNET user access to the private key using this, but can't seem to get the
user name correct. I'm using (domain_name)\ASPNET, but the tool doesn't seem
to like that.

I also tried passing my credentials to the request, but that too didn't work.
 
J

jlento

Joe,

Just got it! - Thanks for your help.

Joe Kaplan (MVP - ADSI) said:
Are you supplying the certificate from a file? One thing to keep in mind is
that no matter how you tell the client which certificate to use, Windows is
still going to try to get the private key for the certificate by looking for
that in the available CSP containers. It is stored separately from the
certificate and is protected by the OS.

If the identity you are running under is different in both cases (check
System.Security.Principal.WindowsIdentity.GetCurrent().Name), then the CSP
containers that are available will be different too as there is a "per user"
store and a machine wide store.

If the cert private key is installed in the machine wide store, then I think
this will work or if it is installed in the store for the user running the
code. I'm not a great expert at crypto key containers, so I'm not the best
person to ask all the details on. I just know that this is a common issue
that comes up.

Joe K.
 
Ad

Advertisements

J

Joe Kaplan \(MVP - ADSI\)

It will definitely be <machine name>\ASPNET as that's a local account.

Depending on how authentication is set up on the site, you could also try
logging in as you and enabling impersonation.

I'm not sure how or if the winhttpcertcfg tool fits into this. I'm not sure
which stack HttpWebRequest is using under the hood. It might be something
you can use though.

Another thought might be trying to put the certificate private key into the
machine store instead of the current user store. Depending on the
exportability of the cert, you can probably do that with the certificates
MMC.

Joe K.
 
J

Joe Kaplan \(MVP - ADSI\)

If you can explain carefully what you did to get this working, hundreds of
future Google searches on this thread will be very happy with what they find
at the bottom :)

Joe K.
 
Ad

Advertisements

J

jlento

Joe,

Sorry for the delay in getting back.

All I did (I say that with a bit of sarcasim - it took me over 3 days to get
to this point) was grant ASPNET access to the private key to the certificate
using the winhttpcertcfg tool:

winhttpcertcfg -g -c LOCAL_MACHINE\MY -s (MyCertificate) -a ASPNET

As it turns out, the user who installs the certificate is automatically
granted access to the private key, in my case, me. That's why things worked
with the Windows front end. I was the user and (by chance) I had installed
the certificate. When the web front end comes along, I am no longer the
user, ASPNET is. I saw the certificate being found and attached to the web
request, yet hidden is the fact that ASPNET didn't have access to the private
key. Once that happen, everything worked.
 
Ad

Advertisements


Top