Basic question: how does one setup a web application and web services where they use windows authentication to connect the web application to the web service?
I have inherited an application written in asp.net 2.0 and am working to migrate it to asp.net 4.8. The solution is designed with a project for the web UI and a project for the web services. I have deployed both projects to an IIS site on a Windows 2019 server as separate applications on the same server in the Default Web Site. Each has their own application pool with AppPoolIdentity as the identity and both use Windows Authentication method and have all other authentication methods disabled. Each application is set to use pass-through-authentication when connecting.
When I run the UI application project it tries to call the first web service and I get 401 Unauthorized at the web service call. I have added some logging in the web application and the web service and can see it is authenticating me on the web application and verified the exact url (http://localhost/{appname}/authenticate.asmx) being used to call the web service but it is rejecting the attempt to access the web service with the 401 Unauthorized error from the web application. When I independently access the webservice it is accessible, authenticates me, and works as expected verified by logging output.
What do I need to change to get the application to connect to the web service with the same authenticated user? Do I need to change the AppPoolIdentity to something else like a service account or set it to Network Service or something else? I would have thought the UI application would pass-through the authenticated user to the web wervice but that must not be happening and I am not sure what to set to enable that connectivity.
Thank you in advance.
I have a website written in ASP.NET WebForms, which accesses web services that are written in ASP.NET WebAPI. For security, I closed port 8079 (web services) so that web services could only be accessed via the website, but that it would not be possible to request web services directly from the Internet. When I request a page on a website, through the Fiddler program, I see a request for a website, but I don’t see a request from a website for web services. Everything works well. But now I have made another website written in AngularJS and I want this website to also access my closed web services. Is this possible through AngularJS? Below is the request code for web services via ASP.NET website.
HttpResponseMessage response =
client.GetAsync("http://localhost:8079/api/values/5").Result;
if (response.IsSuccessStatusCode)
{
Task<string> data = response.Content.ReadAsStringAsync();
result += data.Result;
}
As a result, the site(AngularJS) and ASP.Net MVC Web Application should be available on the Internet, and web services (ASP.NET WebAPI) should not be available on the Internet.
Currently, the client accesses the web services directly, but it’s necessary to make the client access the web server and the web server access the web services
Even if you create another ASP.NET app (a kind of 'facade') that handles requests from the client, and invokes web services internally, this alone won't solve the problem:
If the facade accepts requests from any client and just sends them to the web services, it is not different from exposing the web services directly to the internet.
As #Andrei Dragotoniu pointed out, you have to secure your services by only accepting requests from authorized clients.
How to authorize access to web services
A common way of securing access to web services is JSON Web Token (JWT). The token contains encrypted claims that explain the identity (and maybe other aspects) of the client. Typically it works as follows:
A new token is generated on the server upon successful authentication of the client. The authentication can be either manual (a login form), or automatic (for example, with OAuth).
Once the token is generated, it is returned to the client. The client then starts attaching the token as an HTTP header to every request it sends to the web services. On every request, the web services validate the attached token.
This blogpost provides more information and examples of using JWT in C#.
API Gateways
The requirement of limiting access to web services to an internal network is not uncommon. A typical solution here is API Gateway.
(from Wikipedia) Gateway: a server that acts as an API front-end, receives API requests, enforces throttling and security policies, passes requests to the back-end service and then passes the response back to the requester. A gateway often includes a transformation engine to orchestrate and modify the requests and responses on the fly. A gateway can also provide functionality such as collecting analytics data and providing caching. The gateway can provide functionality to support authentication, authorization, security, audit and regulatory compliance.
More on API Gateways in this article. One of the most popular API Gateways is Kong.
Even if you deploy your web service in intranet, you cannot consume the web service from client browser (Angular or JS Applications).
One possible solution could be,
Deploy the web service in intranet web server.
Create a proxy web service in the edge server (they are both intranet & internet facing). Proxy web service should just expose the required methods by obscuring the original web methods.
Consume proxy web service from client-side applications.
Otherwise, client-side applications can never consume the intranet web services.
Optionally, if you create NodeJS, ASP.Net based web applications, it can be deployed on edge web servers that can talk to intranet web services and users (living in the internet) cannot access web services directly.
UPDATE:
Moreover, based on your code above, it looks like you are trying to consume web service from .Net Runtime Managed Code (ASP.Net MVC). Well, in that case, AngularJS will ajax to your controller-action. Then controller, in the edge server, can talk to any intranet web service. AngularJS need not talk to Web Service. It is straight-forward now.
"When I request a page on a website, through the Fiddler program, I see a request for a website, but I don’t see a request from a website for web services"
That statement is true in a very limited context, but the reality is much bigger than that.
The requests from a website to its own API can easily be seen by using browser tools for example ... hit F12 in any browser and look under the Network tab, this is something anyone can do to see what a website ( any website ) is doing.
You need to protect your API somehow. You can use something like OAuth2 or you could do it at server level. You can lock down a server to only accept connections from your website's IP address for example. You can also make it so that the server the API is on is completely locked down. You can lock down the API.
You just need to realize that you do have a security issue if you don't do something. The tech stack you use is irrelevant for this.
I have a WebAPI based master web service which provides a list of Azure Service Bus Relay endpoints for on-premises WCF services based on the client who logged onto the Master Service via a WPF desktop App using ADAL Azure Active Directory logon. This works fine, and the master service returns a Service Bus endpoint for the client who logged in.
The client can then connect to the WCF on-premises service via the returned Service Bus endpoint no problem.
However there are certain methods in the on-premises WCF service which need to impersonate the calling client-user and this is where I am stuck. Does anyone know of a way to be able to impersonate a client who has called a WCF service via the Azure Service Bus relay?? I can't "log the user on" in order to impersonate them because I don't know their domain password, I only have available their logon UPN.
You can potentially solve this problem in the same way I did when writing a paper about flowing an identity through azure service bus queues. You would need to have elevated priveledges for your service account running the on premise service which may introduce a vulnerability depending on how your solution works but if you can mitigate that then this approach would work.
The paper is on the following link:
Flowing a Windows Identity through Azure Service Bus Queues
http://microsoftintegration.guru/publications/whitepapers/
Hope this helps
Mike
I am deploying a .NET web service that connects to a database.
When a user within the domain connects to the webservice, I want their identity to be known by the webservice (since a subsequent call to the DB from the webservice uses a USER_ID() function to know which user is making the request).
The app pool that is running the web service is configured to run under a domain account that allows access to the database. When I query the web service, it is connecting as that account of the app pool, and not the user that is calling the web service.
I have tried various different impersonation configurations but I can't get the web service to interpret the caller's identity. Can anyone advise what I am doing wrong? Is the fact that my app pool that is running under a named account causing the problem? Should it be configured to something else?
No, it's not the app pool's problem. Impersonation has to be also set from configuration files which in fact, it's probably already been specified.
Now, you didn't mention what of service you are using. For the service to be aware of who is making the request through impersonation the service must be running in asp.net compatibility mode so it can participate in the asp.net pipeline. It's a pretty basic topic, but if you need more info, then refer to the MSDN article below
http://msdn.microsoft.com/en-us/library/system.servicemodel.activation.aspnetcompatibilityrequirementsattribute(v=vs.110).aspx
Leo
A system I'm working on has a web service which calls a WCF service. The request to the web service is received with the user's Kerberos credentials and we want to call the WCF service using these credentials.
Is it possible? if yes, how?
Yes. It is possible. You may have to use the WCF delegation. Delegation is perfect fit for backend service calls with the authentication done on front end.
Please refer to Delegates and Impersonation. The impersonation level set to Delegate would enable you to authenticate a service running in a different machine from the caller server.