I'm using (with satisfaction) some web services from an Android application.
I use https (I bought a SSL certificate).
I want to prevent unwanted accesses from others that know the urls of my web services.
I use a "secret key" that the app must provide to the web service method, but it's stored in a constant variable inside the code and I know this is not the best solution to ensure security.
Android web service call (using ksoap):
try {
SoapObject request = new SoapObject(configuration.getNamespace(), methodName);
request.addProperty("securityKey", SECURITY_KEY);
C# web service
[WebMethod]
public string UserRegistraion(string securityKey, string data)
{
if (securityKey != Environment.SecurityKey)
{
return "WRONG_KEY";
}
What's the best way to achieve the definitive solution?
EDIT:
As someone suggested, I asked the same question also on security.stackexchange.com
https://security.stackexchange.com/questions/30850/web-services-how-prevent-illegal-accesses
You simply can't do this. You should obfuscate your code. This is an old battle of software developers vs. crackers
You can't block someone on using/analyzing a code that resides on the client-side, but you can make it difficult in a point that almost all people will give up on doing it because it is too much hard to exploit your code.
Related
I have one API and two different domain. How can I check which domain host triggered api request?
Example:
API: example.API.com
Domain1: example.Domain1.com
Domain2: example.Domain2.com
and I want to know which domain call my API?
I used C# for my code, maybe there is a ready way to solve my problem but if not then maybe some advice on how to approach the problem?
I try code.
string host = _httpContextAccessor.HttpContext?.Request.Headers.Referer.FirstOrDefault();
This code gives me the full url of the client, but I don't know if that's a good way because
this can be null.
I am currently working on a school project with a classmate. We've decided on making the classic setup of an Administration-client (Blazor Server) and a Member-client (Angular).
We have 7 Projects in the solution so far:
Solution
├───Project.MemberClient (Angular)
├───Project.AdminClient (Blazor Server)
├───Project.Api (REST API)
├───Project.Application (CQRS & Mediatr)
├───Project.Core (Entities, Enums, Interfaces)
├───Project.Infrastructure (Database Context & Migrations)
└───Project.Test
We're using EntityFramework for the database, which both the API and Blazor Server have access to, through Mediatr.
Unfortunately, we can't come to terms with how we should handle the use of the API.
My classmate is convinced that both Blazor Server client and the Angular client should go through the REST API.
I'm convinced that we don't need to go through the API with the Blazor Server-client, since it can access Mediatr through Dependency injection. I feel it's silly to go through the API to deserialize a C# object to JSON just to serialize it again straight after.
This is a request on the API:
[HttpPost("organizr-user")]
[ProducesResponseType(StatusCodes.Status200OK)]
public async Task<ActionResult<OrganizrUserResponse>> CreateOrganizrUser([FromBody] CreateOrganizrUserCommand command)
{
var result = await _mediator.Send(command);
return Ok(result);
}
This is a request on Blazor Server:
private async Task OnButtonSave_Clicked()
{
_userCreated = false;
_showErrors = false;
var query = new RegisterUserRequest
{
FirstName = _firstName,
LastName = _lastName,
Gender = (Gender)_gender,
Address = _address,
PhoneNumber = _phoneNumber,
Email = _email,
Password = _password,
ConfigRefreshPrivilege = _refreshConfiguration
};
var result = await Mediator.Send(query);
if (!result.Succeeded)
{
_showErrors = true;
_errors = result.Errors.ToList();
}
else
{
_userCreated = true;
}
}
I feel (yeah, there are a lot of feelings involved) like we still uphold the principle of only one access point by the use of Mediatr. Blazor doesn't need the API, but Angular does.
What would be the right way to go about this?
I am glad you are taking this school project so seriously.
As is with all architectural decisions - "it depends". There is no such thing as a silver bullet approach, only the best for you situation.
I think you both have some points. You are correct in saying you are upholding a single point of access, and thus reducing the amount of code you need to write - but that is not the only thing to consider here. You need to ask yourself a few more questions.
You should treat this as an production application that has the potential to scale
Here are some questions you should ask yourself.
Are the API and the Blazor web server going to be hosted on the same server as the database ?
API's should be stateless, are you going to keep that consideration while writing your blazor web app, since they consume the same code ?
Is your application scalable ? How will you implement things like load balancing on both the API and the blazor web server ?
Can I easily replace/change some in the overall design if needed ?
If I had to choose for you, I would suggest filtering everything through a web API.
Here is why:
You have more options around hosting - you can host your blazor web application on one server and the database/webAPI on another.
It forces developers into "The pit of success". If you have 10 developer working on this product, it's easier for them to think of the application as "one API" rather than an "API and a server that uses the same code". This may not seem important now, but trust me, large scale application can get very hairy very quickly if you don't keep things as simple as possible.
Creating load balancers on Blazor web server can be tricky, since it uses SignalR to communicate with the client.
Testing becomes easier. What if your blazor application has functionality that your Angular client doesn't? That means it would never be built into the web api. Now you need to do things like load testing, stress testing, etc on two separate servers rather than just the web API. The testing required on the Blazor web server would be heavily scaled down if everything ran through the Web API.
And last but not least,the Blazor developers pride themselves on how easy it is to switch between Blazor client and Blazor web server. What if, in future, you decide that Blazor web server isn't the best solution, and you would prefer blazor client ? If everything was running through an Web API this would be a few lines of code. If not - you have a lot of refactoring to do.
I think its a better idea to write a few extra lines to "serialize and deserialize " through an API now, and save yourself potential hassle later.
This is my opinion based off my personal experiences - keep things simple, readable and scalable.
I hope this helped.
Let me know if you would like me to clarify anything.
Happy coding!!
I maintain an ASP.NET Web API project which supports a simple REST end point for clients to post XML data to our server. This site is setup to support BasicAuthentication and works very well. All of our security checks are done at the network firewall and on the machine itself using custom Windows User accounts. Recently, one of our clients requires that we support a SOAP end point to receive the XML data as well.
My thought was to simply add a new WebService (Blah.svc) with supporting interface having the required [ServiceContract] and [OperationContract] attributes to my interface. I had hoped that I could simply expose the URL to our client and it would "just work". I am able to hit the end point, but this service is not able to extract the user name.
Here is my sample code:
public string CreateWorkItem(string xml)
{
var userName = HttpContext.Current.User.Identity.Name;
if (string.IsNullOrEmpty(userName))
userName = "NO USER NAME";
var elem = XElement.Parse(xml);
return $"Hello [{userName}]! You sent [{elem.Value}].";
}
Here are my results:
I've scoured the web to try and find out how to get access to the BasicAuthentication details in a Soap message, but I'm not having any luck. All the examples that I'm finding require that I create a new WCF project and expose it with a lot of web.config settings, or the examples are ~5 years old using older techniques.
I'd like this service to simply publish with my WebAPI project using the Publish... option inside Visual Studio. Unfortunately, I've not found a common denominator to make it work. I'm sure I'm missing something, and I hope someone can help.
Any help would be greatly appreciated!
Check this link out: WCF Services and ASP.NET
In short you need to enable ASP.NET Compatibility in your WCF service.
However, you may want to look into using OperationContext.Current.ServiceSecurityContext.*
The fact that it is HttpContext.Current.User.Identity.Name is returning null means either:
User is null; or
User is Anonymous
I have a few ideas to help resolve the issue.
1. Your User.Name is actually null
You might want to debug by grabbing HttpContext.Current.User and see if it's correct.
2. Go direct: get the cookie via a parameter
Try and pass the HttpContext as a parameter so you can grab the cookie?
public string CreateWorkItem(HttpContext context, string xml)
{
var username = context.Current.User.Identity.Name;
...
}
3. Your configurations are not setup properly
The alternative is that maybe your web.config or Global.asax is not setup to properly.
I'm coming to .net web api from a JavaScript background, and I'm trying to make a proxy to help with a cross domain JSON request. I'm GETing from a server I don't control the source code for, so I can't configure CORS directly. Likewise, it doesn't speak JSONP.
So two questions as I try to get my head around Web API:
1) Is Httpclient the right tool for this job? (if not, what is?)
2) If httpclient IS the right tool, what is an absolute bare bones httpclient config so I can test this out? Not worried about throwing exceptions or anything else other than just GETing API data and feeding it to a jQuery client.
I guess one other piece of information that would be nice would be building username / password authentication into the http request.
Any help is much appreciated, as are links to any good blogs / tutorials / etc that might help as an introduction to this sort of thing. I've watched several today alone, and I'm still not able to get a basic http request going on the server side without resorting to cutting / pasting other people's code.
Thanks in advance!
** EDIT - To make this question a bit more clear, what I'm trying to test is 1) Can the proxy connect to the third party server, which involves authentication via a username and password 2) Can the proxy then respond to the jQuery client request with the JSON data it received from the third party server.
Thanks to all who have taken the time to respond.
HttpClient seems to be ok in this job.
About the minimal config- it depends on what the third party expects. In most cases would work out-of-the-box, but there always may be some minor tweaks like headers and/or auth code.
I have just found some blog entry where some author shows how to test such a proxy and shows the proxy code too. Please see: http://www.davidbreyer.com/programming/2014/10/11/create-fake-responses-to-rest-service-calls-in-c/
You can find info about sending credentials here: How to use credentials in HttpClient in c#?
HTH
EDIT:
this sample code should work (copied from blog above and modified):
public class Proxy
{
public async Task<ExampleDto> GetExample(int id)
{
var client=new HttpClient();
//set some auth here
//set other headers
var response = client.GetAsync(
string.Format("/api/restserviceexample/{0}", id))
.Result.Content.ReadAsAsync<ExampleDto>();
return await response;
}
}
It's so simple that you can just run it and see if the other server responds. If not, you can play with headers - since all the session info and user auth info are sent using ookies and/or headers, all you have to do is to see how it's made with regular browser and then fake it on the server. Probably best tool for this job will be Fiddler.
However - there is one thing to consider. If the other service has special method for authorization (other than passing credentials with each request) the whole thing becomes tricky, since your proxy should perform authorization using their service, then store their auth cookie on the server or propagate them to the browser and attach them with all next requests.
First, you don't need ASP.NET with C# if you really want minimal.
.NET has great http handling without ASP. Check out classes like HttpListener, HttpListenerContext, HttpListenerRequest, etc... Yes, you'll have to write some boilerplate as your application, but these classes are pretty good.
See among others:
http://www.codeproject.com/script/Articles/ViewDownloads.aspx?aid=599978
Second, if you want user & password, I'd checkout using oauth authentication so you don't have to deal with them directly. Google Plus, Windows Live, Facebook, etc... all have similar OAuth 2.0 APIs for that. See among others:
http://msdn.microsoft.com/en-us/library/dn659750.aspx
https://developers.google.com/+/web/signin/server-side-flow
https://developers.facebook.com/docs/facebook-login/manually-build-a-login-flow/v2.2
What is the best practice when you need to authenticate specific OperationContracts, while using the default MembershipProvider for security (FormsAuthentication).
I guess that doing Membership.ValidateUser and Membership.GetUser just won't cut it when using WebServices, right?
In other words: How can I verify that a user is allowed to use specific methods in the webservice (that the user is authenticated/"logged on")?
Yeah--you can't really use FormsAuthentication in this case. But there is excellent infrastructure available in WCF for managing role-based access to individual methods: http://msdn.microsoft.com/en-us/magazine/cc948343.aspx
I have been known to over-engineer things, so when I use WCF in my web applications, I wrap the service in my web app. This way my web app calls the abstraction.
Now, what you can do is apply your code access security (CAS) on the wrapper.
Example code might look like this (tons of details omitted for brevity)
internal class ServiceWrapper
{
Service Svc;
public ServiceWrapper()
{
Svc = ServiceClient();
}
[System.Security.Permissions.PrincipalPermission(System.Security.Permissions.SecurityAction.Demand, Role = "HelloWorld")]
public string HelloWorld()
{
return Svc.HelloWorld();
}
}
In a perfect world, we would want CAS to be a bit more dry (don't repeat yourself), meaning handled in the WCF as you suggest. But this might be a good middle of the road if know you can lock down your WCF app and control who calls it :-)
That would help you simplify getting the ball rolling...
Good luck!