WCF and Forms authentication

This is about flowing ASP.NET Forms authentication to WCF service. Once successfully authenticated, forms authentication data is stored as an encrypted cookie. And since the encryption is machine dependent its important to have the validationKey and decryptionKey same in both the web.configs(web app and WCF app).

Check this MSDN link to know more about configuring machineKey for asp.net forms authentication.

http://msdn.microsoft.com/en-us/library/ms998288.aspx

1.)

Create a validationkey and decryptionkey. Run the below program two times. The value generated first time can be used as the validationKey and the second one machineKey in the web.configs.



static void Main(string[] args)
{
int len = 48;

byte[] buff = new byte[len / 2];
RNGCryptoServiceProvider rng = new
RNGCryptoServiceProvider();
rng.GetBytes(buff);
StringBuilder sb = new StringBuilder(len);
for (int i = 0; i < buff.Length; i++)
sb.Append(string.Format("{0:X2}", buff[i]));
Console.WriteLine(sb);

}

2.)

Configure the web.configs(wcf and web app) to use the generated keys as follows.



<system.web/>
<machineKey validationKey="D4E763ABFD89DAAD50620E89E11FFAB7AD94AF9EDE264526" decryptionKey="5F0A4D7396E35CF534F0B404F481CA70C2C5A43071729BE4" decryption="3DES"/>
</span>

3.)

Configure the WCF service to run in ASP NET compatibility mode.


This is to be done in two place. One in wcf service web.config as follows

<serviceHostingEnvironment aspNetCompatibilityEnabled="true"/>

And

in the service behaviour


[AspNetCompatibilityRequirements(RequirementsMode=AspNetCompatibilityRequirementsMode.Allowed)]
public class Service1 : IService1
{


4.)

Configure forms authentication in asp.net config



<authentication mode="Forms">
<forms name="appNameAuth" path="/" loginUrl="login.aspx" protection="All" timeout="30">
<credentials passwordFormat="Clear">
<user name="jeff" password="test" />
<user name="mike" password="test" />
</credentials>
</forms>
</authentication>
<authorization>
<deny users="?" />
</authorization>


5.)

In login.aspx




if (FormsAuthentication.Authenticate(txtUser.Text, txtPassword.Text))
FormsAuthentication.RedirectFromLoginPage(txtUser.Text, chkPersistLogin.Checked);
else
ErrorMessage.InnerHtml = "Something went wrong... please re-enter your credentials...";


This sets the authentication cookie on successful login.

6.)

Now send the cookie in WCF request http header




HttpRequestMessageProperty httpRequestProperty = new HttpRequestMessageProperty();
httpRequestProperty.Headers.Add(HttpRequestHeader.Cookie, FormsAuthentication.GetAuthCookie(User.Identity.Name, false).Value);

ServiceReference1.Service1Client serviceClient = new WebApplication1.ServiceReference1.Service1Client();

using (OperationContextScope scope = new OperationContextScope(serviceClient.InnerChannel))
{
OperationContext.Current.OutgoingMessageProperties[HttpRequestMessageProperty.Name] = httpRequestProperty;
string s =serviceClient.GetData(2);
}


7.)

At the service side you can read the cookie inside the operation as follows




HttpRequestMessageProperty g = OperationContext.Current.IncomingMessageProperties[HttpRequestMessageProperty.Name] as HttpRequestMessageProperty;
string s = g.Headers.Get(HttpRequestHeader.Cookie.ToString());
FormsAuthenticationTicket tick = FormsAuthentication.Decrypt(s);


Working Sample

http://cid-05c2e50f2c5140c1.skydrive.live.com/self.aspx/.Public/WCFFormsAuthentication.rar

This article is taken from my blog

Reference: http://thoughtorientedarchitecture.blogspot.com/


Comments

Author: Lavanya12 May 2011 Member Level: Bronze   Points : 1

Hi Hari,
This article was a great help to me.
I exactly needed the same info!!
Thanks a ton!!:)

Regards,
Lavanya

Guest Author: Champ13 Jan 2012

Tip top stuff. I'll except more now.



  • Do not include your name, "with regards" etc in the comment. Write detailed comment, relevant to the topic.
  • No HTML formatting and links to other web sites are allowed.
  • This is a strictly moderated site. Absolutely no spam allowed.
  • Name:
    Email: