During a recent consulting, I helped a client to resolve his authentication issues with his existing Web application and Windows Phone application.
Using the existing MembershipProvider
If you have already an existing Web application and you want to extend it throughout a Windows Phone application you can use the existing System.Web.ApplicationServices for the authentication.
You can do this by creating a new WCF service file and expose the built-in AuthenticationService.
<%@ ServiceHost Language="C#" Service="System.Web.ApplicationServices.AuthenticationService" %>
In the web.config of the Asp.net Web application you have to add following sections:
<system.web.extensions> <scripting> <webServices> <authenticationService enabled="true" requireSSL="false"/> </webServices> </scripting> </system.web.extensions>
<system.serviceModel> <behaviors> <serviceBehaviors> <behavior name=" "> <serviceMetadata httpGetEnabled="true" /> <serviceDebug includeExceptionDetailInFaults="false" /> </behavior> <behavior name="AuthenticationServiceBehaviors"> <serviceMetadata httpGetEnabled="true" /> </behavior> </serviceBehaviors> </behaviors> <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" /> <services> <service name="System.Web.ApplicationServices.AuthenticationService" behaviorConfiguration="AuthenticationServiceBehaviors"> <endpoint contract="System.Web.ApplicationServices.AuthenticationService" binding="basicHttpBinding" /> </service> </services> </system.serviceModel>
You also need to configure the WCF service itself by using the AspNetCompatibilityRequirements attribute.
[ServiceContract(Namespace = "LieberLieber.Mobile")] [SilverlightFaultBehavior] [AspNetCompatibilityRequirements( RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)] public class CompanyService
After you have added a service reference to the AuthenticationService.svc and CompanyService.svc you have to enable cookies for the Windows Phone application.
Add following attribute enableHttpCockieContainer and set the value to true.
<bindings> <basicHttpBinding> <binding enableHttpCookieContainer="true" name="BasicHttpBinding_AuthenticationService" maxBufferSize="2147483647 maxReceivedMessageSize="2147483647"> <security mode="None" /> </binding> <binding enableHttpCookieContainer="true" name="BasicHttpBinding_CompanyService" maxBufferSize="2147483647" maxReceivedMessageSize="2147483647"> <security mode="None" /> </binding> </basicHttpBinding> </bindings>
One important notice:
If you need to update the service reference you will get following Microsoft Visual Studio error: “The configuration for the service reference could not be updated due to the following issue: Unrecognized attribute ‘enableHttpCockieContainer’.
To resolve this issue just remove the attribute. Update the service reference and add the attribute again.
Within the Windows Phone application you can now use the AuthenticationService’s method LoginAsync.
readonly CookieContainer _coockieContainer = new CookieContainer();
private void Authenticate(string userName,string password) { var authService = new AuthenticationService.AuthenticationServiceClient(); authService.CookieContainer = _coockieContainer; authService.LoginCompleted += authService_LoginCompleted; authService.LoginAsync(userName,password,"",true); }
If you make now a method service call, you have to set the same CookieContainer.
private void GetCompanyName() { var client = new CompanyServiceClient(); client.CookieContainer = _coockieContainer; client.GetCompanyNameCompleted += client_GetCompanyNameCompleted; client.GetCompanyNameAsync(); }
Authentication without MembershipProvider
If you are using your own authentication method you have to set the authentication cookie by yourself.
public bool Authenticate(string userName, string password) { if (userName == "lieberlieber" && password == "ll%123") { System.Web.Security.FormsAuthentication.SetAuthCookie(userName, false); return true; } return false; }
One important thing to remember
If you are using Basic Authentication the username and password are sent in plaintext. That means you should definitely use SSL.
Here you can find a running solution.
Nice post and good example… but when I try it out, it works fine in the emulator, but not on the phone.
Any ideas? I get Not authenticated exception on the phone.
Hi Depechie,
did you change the client – endpoint – adress from http://localhost to http://YourComputername in the ServiceReference.ClientConfig?
Hey Simon, yes I did and the binding enableHttpCookieContainer=”true”
Maybe another approach? If you have a test wp7 app, could you config it to reference my service?
Or the other way around can I reference to your test authentication service?
Ok… I don’t know why, but I removed all config settings and service references, set everything back and now it works…………. No idea why!
Thanks for the tip though…
Hi,
I loved your sample. Without sample it would be impossible for me to get the security working for WP7 with my WCF service. Thanks a lot for posting this. Lot of people suggested many solutions but no one explained it fully, you did.
After 4 days of no sucess looking at other sites , i tried this and things worked like a charm.
We are glad when people like our work!
I can’t get it to work. I don’t get the authentication cookie. After calling the authentication service the cookie container should be filled I assume bit it isn’t (cc, should have 1 item I assume but it’s 0).
According to the following article it isn’t possible: http://social.msdn.microsoft.com/Forums/is/wcf/thread/09e95c12-ffc2-48ce-99ce-e4181d6c6156
Note: I did set enableHttpCookieContainer=”true”
The message I get Unauthenticated
I did use your example, so I didn’t do anything wrong. I use localhost:, that doesn’t matter, does it?
I am authenticated using LoggedInAsyn ,but I am not getting any cookies back.
Followed all steps specified.