I'm new to WCF (Most of my time, I worked with ASP.NET Web API & MVC).
I wonder there is any AuthorizeAttribute in WCF or not (custom implementation is ok) .
For example:
+) In Web API, I have these steps :
-) Call [POST] api/login with email & password to login
-) Store email & password in front-end site, each time front-end sends a request, they have to include email & password in header for authentication.
-) In back-end, AuthorizeAttribute reads email & password of request header, do validation then authenticate the request as it is valid.
My question is:
Can my WCF application have an Attribute to do the same work as the API does ?
Thank you
You could implement your custom UserNamePasswordValidator:
public class MyValidator : UserNamePasswordValidator
{
public override void Validate(string user, string password)
{
// Do your validation logic.
// In case of unauthorized access throw appropriate exception.
}
}
And configure service behavior to use it:
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="behavior_name">
<serviceCredentials>
<userNameAuthentication userNamePasswordValidationMode="Custom"
customUserNamePasswordValidatorType="SomeNamespace.MyValidator, AssemblyName" />
</serviceCredentials>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
Also it is not a good idea to store password. Would be better to generate an auth token by this login & password, and use that token.
Related
We are using Message Inspector to customize the SOAP message by adding some information at client side and retrieving the added information at the server side.
We are also using Custom Authorization Manager by using ServiceAuthorizationManager to use retrieved SOAP based Message information.
To customize the SOAP messages, we are overriding two methods:
a) BeforeSendRequest (Client Side) - This method is used to customize the SOAP message header in Message Inspector.
public object BeforeSendRequest(ref System.ServiceModel.Channels.Message request, System.ServiceModel.IClientChannel channel)
{
Dictionary<string,string> headerInfo = new Dictionary<string,string>();
headerInfo.Add("UserId","1111");
MessageHeader header = MessageHeader.CreateHeader("LocalName", "NamespaceURI", headerInfo);
request.Headers.Add(header);
return null;
}
b) AfterReceiveRequest (Server Side) - This method is used to fetch the customized SOAP message in Message Inspector.
public object AfterReceiveRequest(ref System.ServiceModel.Channels.Message request, System.ServiceModel.IClientChannel channel, System.ServiceModel.InstanceContext instanceContext)
{
Dictionary<string, string> headerInfo = request.Headers.GetHeader<Dictionary<string, string>>("LocalName", "NamespaceURI");
return null;
}
Now, when request is made from the client side then first call is being made in Custom Authorization Manager class instead of AfterReceiveRequest() in Message Inspector at Server side.
We have registered our Custom Authorization Manager in the App.config file as shown:
<serviceBehaviors>
<behavior name="SampleAuthorizationService.Service1Behavior">
<serviceMetadata httpGetEnabled="false"/>
<serviceDebug includeExceptionDetailInFaults="false"/>
<serviceAuthorization principalPermissionMode="Custom" serviceAuthorizationManagerType="SampleAuthorizationSecurity.CustomAuthorizationManager, SampleAuthorizationSecurity">
<authorizationPolicies>
<add policyType="SampleAuthorizationSecurity.CustomAuthPolicy, SampleAuthorizationSecurity"/>
</authorizationPolicies>
</serviceAuthorization>
</behavior>
</serviceBehaviors>
The flow should be from Message Inspector to Custom Authorization Manager at server side. But, in our case the flow is exactly opposite i.e. from Custom Authorization Manager to Message Inspector.
This might be happening due to Registration of Custom Authorization Manager in the App.config.
Can anyone help me out to change the flow from Message Inspector to Custom Authorization Manager at server side?
I couldn't find a way to invoke Message Inspector before Service Authorization Manager, so I solved this problem by redefining method CheckAccess(OperationContext operationContext, ref Message message) in Service Authorization Manager and doing all the work in this method. It's not a pretty solution but it does the work :)
I'm desperately in need of a working example of a WCF 4 RESTful web service. Our SaaS ticketing system (zendesk.com) can communicate with an URL target using HTTP GET, POST or PUT. I have not done any web related work (only c# console apps) but have now been tasked to create a WCF 4 web service with the following requirements:
Secured via HTTPS
Secured via username / password
Read and process the data from the SaaS system that is transmitted as application/x-www-form-urlencoded information, for example:
http://somedomain/a/path?value=message+with+placeholders+evaluated
My current code is as follows:
namespace WcfService2
{
[ServiceContract]
public interface IService1
{
[OperationContract]
[WebInvoke]
void ClearAlert(Stream input);
}
}
namespace WcfService2
{
public class Service1 : IService1
{
public void ClearAlert(Stream input)
{
StreamReader rawTicketData = new StreamReader(input);
string ticketData = rawTicketData.ReadToEnd();
rawTicketData.Dispose();
//Do some work with ticketData
}
}
}
The web.config file:
<services>
<service behaviorConfiguration="MetaDataBehavior" name="WcfService2.Service1">
<endpoint behaviorConfiguration="RestBehavior" binding="webHttpBinding" bindingConfiguration="" name="REST" contract="WcfService2.IService1" />
</service>
</services>
<behaviors>
<endpointBehaviors>
<behavior name="RestBehavior">
<webHttp />
</behavior>
</endpointBehaviors>
<behaviors>
I am currently using only HTTP (not HTTPS) for development and testing hence the missing binding entry / entries for HTTPS as well as any entries for login purposes in the web.config, at least I assume that is what / where I need to add the needed configuration but again, I have no knowledge.
I would more than appreciate any help / assistance I can get in creating a web service with the three above described requirements.
Thanks to all!
William
How we could authenticate/authorize WCF RESTful service (that uses webHttpBinding (and not wsHttpBinding, like in SOAP case))?
I.e. we want to use Membership/Roles to permit (or prohibit) user consume each web method according his role.
Thanks in advance.
Ilan.
You can use certificates to secure the service or send the username and password in the header. You can then add a behavior by implementing IAuthorizationPolicy to the service so that you don't have to implement the security check in every web service method that you expose.
public class CertificateAuthorizationPolicy : IAuthorizationPolicy
{
public bool Evaluate(EvaluationContext evaluationContext, ref object state)
{
IIdentity identity;
object untypedIdentities;
if (!evaluationContext.Properties.TryGetValue("Identities", out untypedIdentities))
{
identity = null;
return false;
}
var identities = (IEnumerable<IIdentity>)untypedIdentities;
identity = identities.Where(item => item.AuthenticationType == "X509").FirstOrDefault();
var claimSet = (X509CertificateClaimSet)evaluationContext.ClaimSets[0];
var certificate = claimSet.X509Certificate;
}
In web.config you tell the service to use the authorization policy
<behavior name="CertificateSecurityServiceBehavior">
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="false" />
<serviceDebug includeExceptionDetailInFaults="true" />
<serviceAuthorization principalPermissionMode="Custom">
<authorizationPolicies>
<add policyType="CertificateAuthorizationPolicy, MyAssembly.Security" />
</authorizationPolicies>
</serviceAuthorization>
<dataContractSerializer maxItemsInObjectGraph="2147483647" />
</behavior>
Another option is to setup SSL on the IIS Server so that it requires SSL and client certificate to connect to any page.
I am trying to create a custom ASP.NET Forms Authentication Service using WCF. I am calling it via a test page that contains only a single line of JS (except for the ScriptManager scripts). The problem is that the server returns response code 500 and the response body is empty. My breakpoints in the service method and in the Application_Error in Global.asax are not being hit.
Sys.Services.AuthenticationService.login('user', 'pass', false, null, null, null, null, null);
I can see the request go to the server in the browser tools with the following request body:
{"userName":"user","password":"pass","createPersistentCookie":false}
Other things on the request side also seem fine.
Here is the configuration service:
<system.serviceModel>
<behaviors>
<endpointBehaviors>
<behavior name="BtxAuthenticationEndpointBehavior">
<webHttp/>
</behavior>
</endpointBehaviors>
<serviceBehaviors>
</serviceBehaviors>
</behaviors>
<services>
<service name="MyNamespace.BtxAuthenticationService">
<endpoint contract="MyNamespace.IBtxAuthenticationService" binding="webHttpBinding" behaviorConfiguration="BtxAuthenticationEndpointBehavior"/>
</service>
</services>
</system.serviceModel>
And the declaration of the interface:
[ServiceContract]
public interface IBtxAuthenticationService
{
[OperationContract]
[WebInvoke]
bool Login(string username, string password, bool createPersistentCookie);
[OperationContract]
[WebInvoke]
void Logout();
}
The implementation:
public class BtxAuthenticationService : IBtxAuthenticationService
{
public bool Login(string username, string password, bool createPersistentCookie)
{
... irrelevant because this is never hit
}
public void Logout()
{
}
}
Can someone tell me how to configure this or point me to a way to debug it. An article about implementing custom Forms Authentication with a WCF service will be welcome too. I've tried experimenting with various other settings including all the exception details settings I could find but could not make any progress (though I was able to make some regress and get different exceptions like missing endpoints and so on).
Thank you for your time.
Not sure if this helps. I have never written such service but your configuration creates WCF service wich is not ASP.NET AJAX ready and works with XML instead of JSON. Try to use this instead of webHttp behavior:
<endpointBehaviors>
<behavior name="BtxAuthenticationEndpointBehavior">
<enableWebScript />
</behavior>
</endpointBehaviors>
I am developing a server application using WCF to expose WebService endpoints for clients. I want to implement authentication through a simple custom provider that will use the username and password passed through the SOAP headers. I know how to set the user name and password to be sent on the client, I just want to know how to pull the username and password out of the SOAP header on the server side. Any help would be greatly appreciated.
You need to specify the username and password validator in the service behavior
<behavior name="MyServiceBehavior">
<serviceCredentials>
<userNameAuthentication userNamePasswordValidationMode="Custom"
customUserNamePasswordValidatorType="MyNamespace.MyUserNamePasswordValidator, MyDll" />
</serviceCredentials>
</behavior>
you can access the user name and password from MyUserNamePasswordValidator class
public class MyUserNamePasswordValidator : UserNamePasswordValidator
{
public override void Validate( string userName, string password )
{
// valid your password here
}
}