I have this WCF service and I'm trying to apply authentication and authorization mechanism in it.
It's my first time to do this, what I have is this web.config serviceModel
tag for the service:
<system.serviceModel>
<services>
<service name="RoleBasedServices.SecureServiceExternal" behaviorConfiguration="externalServiceBehavior">
<endpoint contract="AuthService.IService1" binding="wsHttpBinding" bindingConfiguration="wsHttpUsername" />
</service>
</services>
<bindings>
<wsHttpBinding>
<binding name="wsHttpUsername">
<security mode="Message">
<message clientCredentialType="UserName" negotiateServiceCredential="false" establishSecurityContext="false" />
</security>
</binding>
</wsHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior>
<!--To avoid disclosing metadata information, set the values below to false before deployment-->
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/>
<!--To receive exception details in faults for debugging purposes, set the value below to true. Set to false before deployment to avoid disclosing exception information-->
<serviceDebug includeExceptionDetailInFaults="false"/>
</behavior>
<behavior name="externalServiceBehavior">
<serviceAuthorization principalPermissionMode="UseAspNetRoles" />
<serviceCredentials>
<userNameAuthentication userNamePasswordValidationMode="MembershipProvider" />
<serviceCertificate findValue="RPKey" x509FindType="FindBySubjectName" storeLocation="LocalMachine" storeName="My"/>
</serviceCredentials>
</behavior>
</serviceBehaviors>
</behaviors>
<protocolMapping>
<add binding="basicHttpsBinding" scheme="https" />
</protocolMapping>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
What I want to do is very simple, I don't know if I need all this tags I'm just trying.
What I want to do is from the client side to add reference for the service and first call the MyLogin
:
AuthService.Service1Client s = new AuthService.Service1Client();
s.Login();
Then call the other restricted method and let it be GetData
:
s.GetData()
At service side in Login
method, and only for test purposes, I'm doing this:
public void Login()
{
Thread.CurrentPrincipal = new GenericPrincipal(new GenericIdentity("Bob"), new[] { "Admin" });
FormsAuthentication.SetAuthCookie("BobUserName", false);
}
An the restricted method will be:
[PrincipalPermission(SecurityAction.Demand, Role = "Admin")]
public void GetData()
{
return "Hello";
}
That all I have in service and client, what I'm missing?
Every time ,in debug, I check Thread.CurrentPrincipal
in Login
method I found Thread.CurrentPrincipal.Identity.IsAuthenticated
equals true
but even though when the client calls the GetData()
method it's Access Denied
.
PS: I'm using console application to do my tests does it make any difference ?
Thanks
Here is a very nice article that could possibly lead to a solution.
The general idea is that you have 2 object for the Principal.
HttpContext.Current.User
andThread.CurrentPrincipal
. You are setting theThread.CurrentPrincipal
at the timeHttpContext.Current.User
is already instantiated and the role of it is left to default.You may want to try something like: