WCF - Third party application authentication - wcf-security

I am currently working on an iPhone application. This application calls back to WCF services exposed through my ASP.NET web application. Currently, my WCF operation looks like the following:
[OperationContract]
[WebInvoke(Method = "POST")]
public string SubmitMessage(string message, int priority)
{
try
{
// Process message
// Return success code | message
}
catch (Exception)
{
// Return error code | message
}
}
My web application is using ASP.NET Forms Authentication. My challenge is, I only want authenticated users to be able to call this operation from their iPhone. I know that the iPhone SDK has baked in support for XML. However, I’m not sure how to lock down my WCF operation such that only authenticated users can access it.
How do I make my WCF operation only accessible to authenticated users from third party applications?
Thank you

This has to be done in both sides of the transfer, namely server (WCF site) and client (iPhones).
If you're using SOAP endpoints then you should look for Objective-C SOAP client libraries. This way all you will have to do is to setup best security options to your needs and your server-side code will be almost identical as it is at the moment.
Instead if you're exposing as RESTful endpoints I suggest you to look for an OpenID(&OAuth) approach. Here also, there are .NET and Objective-C libraries available. I belive this solution would require much more coding in both of the sides.

Related

Securing Legacy Web-Service site using anonymous authentication for local access

I have a legacy WebForms application that consumes (ASP.net) Web-Services (using anonymous access) that reside on the same IIS server (same domain, different apps each with their own dedicated app pool). This application was hosted in a secured VPN but now there is a request to host it publicly.
What is the expedient (yet secure) method to secure the web services site without doing a substantial re-coding (on the application level). I have tried configuring the Web-Service site in IIS so that it enables only the Service account (Identity) under which the Web Applications App Pool runs but the current request mode coming from the application is always using Anonymous access. I need to restrict access to allow only the this specific web application. I am thinking of an ISAPI filter, but it is not recommended for IIS 7+ ?
ADDENDUM: I would love to find an IIS based solution. Currently I am trying to restrict access based to just the Web Application source. Problem is (as stated) is those request are all "Anonymous" if I could make those requests use "Network Service" or some other local Identity then I would be set.
I recommend you to use IdentityServer and OpenIdConnect to do that.
IdentityServer is a .NET/Katana-based framework and hostable component
that allows implementing single sign-on and access control for modern
web applications and APIs using protocols like OpenID Connect and
OAuth2. It supports a wide range of clients like mobile, web, SPAs and
desktop applications and is extensible to allow integration in new and
existing architectures.
OpenID Connect 1.0 is a simple identity layer on top of the OAuth 2.0
protocol. It allows Clients to verify the identity of the End-User
based on the authentication performed by an Authorization Server, as
well as to obtain basic profile information about the End-User in an
interoperable and REST-like manner. https://connect2id.com/learn/openid-connect
Using this, you can ask identity server to give you an access token and Id Token.
An identity token represents the outcome of an authentication process.
It contains at a bare minimum an identifier for the user (called the
sub aka subject claim). It can contain additional information about
the user and details on how the user authenticated at the OP.
An access token allows access to a resource. Clients request access
tokens and forward them to an API. Access tokens contain information
about the client and the user (if present). APIs use that information
to authorize access to their data.
In your case, you can for example implement the client credentials flow between your Webforms app and the WebService. (In this flow you are not gonna ask nothing to the users of the WebForms app). So, the idea is that the WebForms app is going to ask identity server to give it an access token to access the webservices resources. In the WebService you have to implement the authorization based on whatever you want (Scopes, claims etc). Please read LeastPrivilege blog (Dominick Baier), He is the master of these topic along with his buddy Brock Allen. Since I cannot post more than 1 link in StackOverflow which is really bad, you have to google them or google any additional information.
If you want a user authentication, you can use Implicit, Code or Hybrid flow. But that depends on what you really want to do.
I reckon you may have to do a bit of code but it's not too much. You can figure out a way to ask for authorization before any endpoint is reached.
I hope I was clear. If not, please ask me for more explanation.
After more research I have settled on an http Module Solution, as it has the following benefits:
• Minimal Coding
• No need to modify existing code base
• Easy deployment
• Follows existing ASP.Net security models for (Local access)
The Module (VS:DLL Project)
using System;
using System.Web;
using System.Threading;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace FilterModule
{
class AuthorizeLocal : IHttpModule
{
public void Init(HttpApplication app)
{
app.BeginRequest += new EventHandler(OnBeginRequest);
}
private void OnBeginRequest(Object s, EventArgs e)
{
HttpApplication app = s as HttpApplication;
HttpRequest req = app.Request;
HttpContext context = app.Context;
if (!req.IsLocal) // Is the request from a Local Source?
{
context.Response.Close(); // close the response: ends request
}
/* Optional Test Code - to view locally create an html page TestModule.html in target site */
string Identity = Thread.CurrentPrincipal.Identity.Name;
string filePath = context.Request.FilePath;
string fileExtension = VirtualPathUtility.GetExtension(filePath);
string fileName = VirtualPathUtility.GetFileName(filePath);
if (fileName.ToLower().Equals("testmodule.html"))
{
try
{
app.Context.Response.Write("app: " + app.ToString());
context.Response.Write("<br/>server: " + app.Server.ToString());
context.Response.Write("<br/>Thread.CurrentPrincipal.Identity.Name: " + Thread.CurrentPrincipal.Identity.Name);
context.Response.Write("<br/>HttpRequest: " + req.Url.ToString());
context.Response.Write("<br/>req.UserHostName: " + req.UserHostName);
context.Response.Write("<br/>req.UserHostAddress: " + req.UserHostAddress);
context.Response.Write("<br/>filePath: " + filePath);
context.Response.Write("<br/>fileName: " + fileName);
context.Response.Write("<br/>fileExtension: " + fileExtension);
context.Response.Write("<br/>req.IsLocal: " + req.IsLocal.ToString());
context.Response.Write("<br/>req.LogonUserIdentity: " + req.LogonUserIdentity);
context.Response.Write("<br/>req.UserHostName : " + req.UserHostName);
context.Response.Write("<br/>req.AnonymousID " + req.AnonymousID);
context.Response.Write("<br/>req.IsAuthenticated : " + req.IsAuthenticated);
}
catch (Exception Ex)
{
context.Response.Write("<br/> " + Ex.ToString());
}
}
//if (_eventHandler != null)
// _eventHandler(this, null);
}
public void Dispose()
{
}
}
}
Implementation
Add the compiled DLL (FilterModule.dll) to the Web Service (site) bin Directory.
Add the following to module definition in the Web Service (or site) configuration file (web.config)
in the <system.webServer> section under <modules>
add the following:
<add name ="FilterModule" type="FilterModule.AuthorizeLocal" />

Is it possible to restrict access to REST API built using Web API 2?

I built a REST API using ASP.NET Web API 2, so I could deliver data from a backend database to my applications running on any platform (mobile, web, desktop etc) However up until now, I simply call the website with the controller I need data from and that's it, it sends back the JSON string in the response.
But, the data is kind of special, and there is nothing to prevent another developer from simply calling the controllers and getting back the exact same data and building their own application around it.
My question is - is there anyway to restrict access to the API so that only my applications can get valid response from the server. (i.e. prevent other developers from using my REST API)
I already read these documentation Security, Authentication, and Authorization in ASP.NET Web API I'm just not sure which of these scenarios apply to me, or if any will do what I am asking.
EDIT - Another piece of info, my web service is running on Azure in case it is relevant.
Did you happen to check token based authentication?Please go through https://stackoverflow.com/a/38670221/4868839 and https://www.youtube.com/watch?v=rMA69bVv0U8 must be a good to start with.
there are different way to validate your web api.
Authentication Filters in ASP.NET Web API 2
using you can customise your authentication filter
you can refer sample Reference link
Token Based Authentication using ASP.NET Web API 2, Owin, and Identity
//App_Start/Startup class
public void ConfigureAuth(IAppBuilder app)
{
OAuthAuthorizationServerOptions OAuthServerOptions = new OAuthAuthorizationServerOptions()
{
AllowInsecureHttp = true,
TokenEndpointPath = new PathString("/v1/accesstoken"),
AccessTokenExpireTimeSpan = TimeSpan.FromDays(AppConfiguration.AccessTokenExpireDuration),
Provider = new SampleOAuthProvider() // class that override your method
};
// Token Generation
app.UseOAuthBearerTokens(OAuthServerOptions);
}
You can find reference from inherits Default implementation of IOAuthAuthorizationServerProvider used by Authorization
i hope it sholud helps you thanks.

SignalR Chat App in WinForm With Remote Clients

i am new in signalR , i have tried and learn from different web sites like github and etc etc
But i couldn't find the solution for my problem.... and now i am getting confused...
My problem is:
I have developed a Chat app in Winform with Web Services and Centralized Database and it is working fine in different countries as in different branches of one organization.
But i want to convert that Chat App into SignalR to achieve more efficiency but i couldn't understand , how to do it in SignalR. because All tutorials of SignalR on Web in one Solution.
like Web , Console or WinRT communicated with each other but they are in one solution but in my scenerio i cannot put the service or Web Page in WinForm application.
Please please help me out in this manner.
What you need to do is use the SignalR for .NET clients. Bring that into your project using NuGet assuming you are using Visual Studio.
You will need to import the following generally:
using Microsoft.AspNet.SignalR.Client;
using Microsoft.AspNet.SignalR.Client.Hubs;
Assuming you are following most of the tutorials on the web you can need the following to connect:
public IHubProxy Proxy { get; set; }
public HubConnection Connection { get; set; }
Also you will need to set the connection like so:
public string Host = "http://YourSignalRChatAppLocationOnAzureOrLocally.cloudapp.net/";
Connection = new HubConnection(Host);
//Assuming your SignalR hub is also called ChatHub (If you followed most tutorials it will be)
Proxy = Connection.CreateHubProxy("ChatHub");
This part will need to be in an async function:
//If you are passing an object back and fourth otherwise String is fine
Proxy.On<ChatMessage>("Send", hello => OnSendData("Recieved send " + hello.Username + " " + hello.Content));
await Connection.Start();
More material fro the link below, this guy has it running on Console app, WPF app, and web clients so you can see the difference.
Standard tutorial on how to make the web server.
SIGNALR MESSAGING WITH CONSOLE SERVER AND CLIENT, WEB CLIENT, WPF CLIENT

asp web service: check if user is logged-in

I'm creating a web service that'll be called from a web form in asp.net. How does the web service check if the user is logged-in and if it is the logged-in user that's actually requesting the service?
thanks
It cannot. Since you're going to call the web service from ASP.NET, you're building a 3-tier application.
Tier 1 is the browser and tier 2 is ASP.NET web application. They share cookies and session variables, so ASP.NET can always authenticate the user. And you already know that.
Tier 3 is the web service. Communication between 2 and 3 is done over a different HTTP connection, sharing different cookies (actually none) and session variables (again, actually none because calls are stateless).
You then have no way to allow the web service on tier 3 to authenticate the client on tier 1.
HOWEVER...............
There is still a possibility, but only if your web service is local to your ASP.NET webapp. That's unlikely to occur, really, because web services are made for remote calls, not local calls. I don't think it's your case.
If this is a local web service, as djechelon suggests, They will share session state you are all set. Use djechelon's answer, ignore mine :)
If not: ask the larger question: what is stoping someone from calling your web service outside the context of your web app: using a tool like soapUI?
1) lock down your service (using WCF Security).
http://msdn.microsoft.com/en-us/library/ms731925.aspx
2) create a local webservice that checks authentication/authorization, and calls the webservice: passing the authorization information.
This is one approach that values the operation the WS performs over redundant Webservice calls. It is your disgression if a WS that calls another fits your performance needs.
You can Enable Session in WebMethod like this:
[WebMethod(EnableSession = true)]
public string DoSomthing(string para)
{
user = new SystemUser();
if (!user.Authenticate())
{//401 Unauthenicated}
}
Authenticate Method:
public bool Authenticate()
{
try
{
if (HttpContext.Current.Session["UName"] == null || HttpContext.Current.Session["Role"] == null)
{
return false;
}
else
{
this.Id = HttpContext.Current.Session["UName"].ToString();
this.Role = (Core.Role)HttpContext.Current.Session["Role"];
return true;
}
}
catch (Exception ex)
{
throw new Exception("Authenticate",ex);
}
}

ASP.net web services

I am using a web service which sets the Thread.CurrentPrincipal object while logging in and soon later when another webmethod of the same web service accesses Thread.CurrentPrincipal, its different/resets
Can someone tell me if this is expected or can different webmethod calls from the same client can access the same Thread.CurrentPrincipal object
Thanks
As soon as you stop using a thread it goes back into the thread pool.
The next call will take a thread from the thread pool, but you have no control which one you get.
You need to send information about which user is making the call, with each request.
This is expected, every new web request is actually new thread. And every web request reset stuff like CurrentThread, CurrentCulture and so on.
What are you trying to do is authentication session. There are many possible solutions. But to suggest something I have to specify technology you use.
For example, ASP.NET ASMX Services can use Forms Authentication. Also they are aware about ASP.NET Session.
With WCF, you can enable ASP.NET support, so you will have same stuff like for ASP.NET ASMX Services. But you also can leverage on Windows Communication Foundation Authentication Service.
Anyways need more info from you.
If you are using the built-in ASP .NET authentication for your website and then just calling the web service from a web page, you may be able to enable session variables and user context information in the methods of the web service with a decoration. Like this:
[WebMethod(EnableSession=true)]
public void MyWebMethod()
{
string mySessionVar = HttpContext.Current.Session["sessionVar"].ToString();
IPrincipal currentUser = HttpContext.Current.User;
...
}
If that doesn't solve your problem, tell us what are you using the Thread.CurrentPrincipal object for (what you are pulling out of the Thread.CurrentPrincipal object). Perhaps there is another solution.

Resources