Web Development »
Web Security »
Security
Intermediate
Pass-Through Security Authentication (Single Sign-on) using ASP.NET
By Jayakanthan
The Pass-Through authentication enables a user to sign-on to their intranet and access other web applications without being asked for login again.
|
XML, C#, VC7, VC7.1, VC8.0, C++, .NET CF, Mobile, Windows, .NET, .NET 1.0, .NET 1.1, NT4, Win2K, WinXP, Win2003, ASP.NET, VS.NET2002, VS.NET2003, Visual Studio, Dev
Posted: 9 Sep 2004
Updated: 9 Sep 2004
Views: 59,535
Bookmarked: 41 times
|
|
|
|
|
Introduction
The necessity came in when we had a Web Application that is intended to be used by Client's users (customers). They have logged into their network and are authenticated by their network. The Client’s intranet will have a link to access the Web application. When they click the link, they might be asked for User Name and Password. The web application has its own Login/password page, if you are not authenticated by this application network domain (Active Directory roles). But the Client would not like that as they need to remember four or five different username/passwords for every provider application that they need to use from their intranet. They want to access the application when they click a link from their intranet. When they access the same website from outside their intranet, it should prompt for the login.
Available Solutions:
- Use Passport Authentication (again the client users should be creating a passport account) and the web application should be registered in passport to use their service.
- Use SAML based Authentication Modules that allow Federated Security Authentication. This requires lot of work.
- Use a Security Key provider module that generates a Ticket to send it along with the user credentials from the client side. The Web application will use the same provider module to validate the Key and authenticate the login.
- Use a HTTP POST to send Identity values along with a Hash Value (credentials + private key) to the Web application. The application creates the Hash value using the credentials and private key, matches the passed Hash value, and authenticates the login attempt.
Solution:
I am going for the fourth solution, as it is the cheapest method. It may not be the best but it is good over SSL connections. However, the solution needs some work at the client side to pass the values. The client code will pass four parameters using POST to the application Pass-Through Page: Client ID, Username, Timeline, and Key Hash. The Client ID is a number to identify a client (valid in the Web application), the Username may be the user’s network login username, Timeline is a date time in “yyyymmddHHss” GMT/UTC time format, and Key Hash is the hashed (SHA1) value of Client ID + User Name + Time line + Private Key. The private key will be the same key on both sides and there is a small compromise on this – keys will be securely stored in both applications (database or a secured file location on network) in encrypted form.
The POST values are received in the web application, validates if the Timeline is within the allowable window (+/- 2 minutes) and the application gets the copy of Private Key from the database, uses that key to create a Hash value of the Client ID, user name, timeline and the private key. This hash value is compared to the Hash key POSTed. If both values match, it allows the user to access the application by setting the over-ride login.
The important thing to remember is this works only if it is accessed over SSL. If not, anyone could sniff the Key hash and hack the session. However, they may not be able to get any other user’s data by getting the Hash Value. SHA1 is very hard to decrypt. Also, at the client side POST code, it should not take more time to create the POST URL and re-direct – otherwise it allows the user to use 'View Source' and get the Hash value. This may not be useful anyways but it is a possibility to find the Hashed value.
Source Code:
Most of the code is self explanatory and I have given the purpose of each project code.
- WebConfig:
<appSettings>
<add key="PassThroughAccountId" value="1"/>
<add key="URLForward"
value="https://localhost/passthroughapp/PassThrough.aspx"/>
<add key="Key" value="WAga1weKy7Tcbonly1Af76jbj7jbb"/>
</appSettings>
- Create Pass-through Values.
In the project TestPassThrough, PassthroughTest.aspx.cs contains the code to generate the Hash values based on the credentials that is entered in the textboxes. Basically, I have used this method just to test the application. In production application, you might have to get the user details from the Network login credentials. private void Page_Load(object sender, System.EventArgs e)
{
KeyToHash = ConfigurationSettings.AppSettings.Get("Key");
TextBoxKey.Text=KeyToHash.ToString();
if (!Page.IsPostBack)
{
txtTimeline.Text = DateTime.UtcNow.ToString("yyyyMMddHHmmss");
Submit.Disabled = true;
}
}
private void Submit_ServerClick(object sender, System.EventArgs e)
{
string toSend;
toSend = "PostToAppl.aspx" + "?var1=" + txtUsername.Text +
"&var2=" + txtTimeline.Text + "&var3=" +
TextBoxKey.Text + "&var4=" + txtClientId.Text;
Submit.Disabled = true;
HttpContext.Current.Response.Redirect(toSend);
}
private void GenHash_Click(object sender, System.EventArgs e)
{
string Username = txtUsername.Text;
string Timeline = txtTimeline.Text;
string SentHash = Username + Timeline + txtClientId.Text + KeyToHash;
string base64HashValue =
FormsAuthentication.HashPasswordForStoringInConfigFile(SentHash,
"SHA1");
TextBoxKey.Text = base64HashValue;
Submit.Disabled = false;
}
private void GetUTCTime_Click(object sender, System.EventArgs e)
{
txtTimeline.Text = DateTime.UtcNow.ToString("yyyyMMddHHmmss");
}
- Post to the application:
I have sent the values in Query string to another aspx page (which automatically POSTs the values to the application). I did this to verify the values being sent. You can avoid by doing in a single step. private void Page_Load(object sender, System.EventArgs e)
{
Username_Form = Request.QueryString.Get(0);
Timeline_Form = Request.QueryString.Get(1);
Hash_Form = Request.QueryString.Get(2);
ClientId = Request.QueryString.Get(3);
URLForward = ConfigurationSettings.AppSettings.Get("URLForward");
}//Code Behind :
<%@ Page language="c#" Codebehind="PostToAppl.aspx.cs"
AutoEventWireup="false" Inherits="Passthrough.UI.Web.PostToAppl" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" >
<HTML>
<HEAD>
<title>TestPostForm</title>
<meta name="GENERATOR" Content="Microsoft Visual Studio .NET 7.1">
<meta name="CODE_LANGUAGE" Content="C#">
<meta name="vs_defaultClientScript" content="JavaScript">
<meta name="vs_targetSchema"
content="http://schemas.microsoft.com/intellisense/ie5">
</HEAD>
<body MS_POSITIONING="GridLayout" onload="Redirect();">
<form action='<%=URLForward%>' method='post'
Target='_blank' name='frmLogon'>
<table border='1'>
<tr>
<td class='bold'>UserName</td>
<td> </td>
<td><input type='text' name='Username' value='<%=Username_Form%>'
size='30' MAXLENGTH='30' readOnly>
</td>
</tr>
<tr>
<td class='bold'>Timeline</td>
<td> </td>
<td><input type='text' name='Request Time'
value='<%=Timeline_Form%>'
size='14' MAXLENGTH='14' readOnly></td>
</tr>
<tr>
<td class='bold'>Hash</td>
<td> </td>
<td><input type='text' name='Hashed Value'
value='<%=Hash_Form%>' size='50'
MAXLENGTH='50' readOnly></td>
</tr>
<tr>
<td class='bold'>ClientId</td>
<td> </td>
<td><input type='text' name='Hashed Value'
value='<%=CleintId%>' size='50'
MAXLENGTH='50' readOnly></td>
</tr>
<tr>
<td colspan='3'></td>
</tr>
</table>
<script language="JavaScript">
function Redirect()
{
document.frmLogon.submit();
}
</script>
</form>
</body>
</HTML>
- Application:
Application code receives the posted values and gets the private key from the database or Web.config (for now, I have hard coded the key in the code itself), generates the HASH value, and compares it with the supplied value. If it is a match, set the User Object in the Session and allow the application to proceed.
Happy Coding.
Conclusion
Any suggestions are welcome, this is a part of an edited application. It may contain some incomplete or commented code as my intention was to explain and give an outline of the Pass-Through authentication. Any other better methods may be available. So use it with caution and explore all possibilities to prevent the sessions hacked.
| You must Sign In to use this message board. |
|
| | Msgs 1 to 12 of 12 (Total in Forum: 12) (Refresh) | FirstPrevNext |
|
|
 |
|
|
 |
|
|
 |
|
|
I see this is an old article; however I still have to correct this item:
" 4. Use a HTTP POST to send Identity values along with a Hash Value (credentials + private key) to the Web application. The application creates the Hash value using the credentials and private key, matches the passed Hash value, and authenticates the login attempt. "
This definition of a hash is wrong. The very definition of a private/public key pair is such that the private key always remains private.
A Hash value is a one-way function. PKI is a two-way function - think about PGP - if I send you an encrypted email, I must first have your PUBLIC key to encrypt it and send it to you. You (holding your private key, which you access with your own passphrase) are the only person who can decrypt said message.
The difference is if I choose to sign the email before I send it - THEN I sign it by calling my private key (using my own passphrase) and a hash is written that is included with the message. You get my signed email and use MY public key to perform your own hash and compare the two to make sure they match (and hence, insuring the integrity of the email). You never, ever receive my private key - otherwise you could pretend to be ME.
HTH.
Thanks Bob Smith for the account - I hate signing up for access.
|
| Sign In·View Thread·PermaLink | 5.00/5 (1 vote) |
|
|
|
 |
|
|
Sorry to reply to my own fake self, but I should have included this in the first post:
Perhaps what you meant to describe was the hash digest process that utilizes a shared PASSWORD. I found the details of it on msdn here:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnnetsec/html/THCMCh12.asp?frame=true&hidetoc=true
"User Name and Password Digest with Nonce and Timestamp
With this approach the digest is a SHA1 hash of a nonce value, a creation timestamp, and the password as follows.
digest = SHA1(nonce + creation timestamp + password)
With this approach, the Web service must maintain a table of nonce values and reject any message that contains a duplicate nonce value. While the approach helps protect the password and offers a basis for preventing replay attacks, it suffers from clock synchronization issues between the consumer and provider when calculating an expiration time, and it does not prevent an attacker capturing a message, modifying the nonce value, and then replaying the message to the Web service. To address this threat, the message must be digitally signed. With the WSE, you can sign a message using a custom token or an X.509 certificate. This provides tamperproofing and authentication, based on a public, private key pair."
And since I am not an ASP.NET guru, I'm open to reading whichever source you found the "+ private key" bit on...
|
| Sign In·View Thread·PermaLink | 1.91/5 (4 votes) |
|
|
|
 |
|
|
I am a newb at coding but i was given the task of creating a Pass-Through authentication. we are told to create a form post to your url (http://x.x.com/userlogin.aspx). Include two form fields that are "Username" and "Password". We recommend that you load this in a few browser window as shown below in an example:
<script language="javascript"> function LoadWindow(){ var strURL
strURL='x.htm'; xWindow-window.open (strURL,'NewWindow,'titlebar=yes,toolbar=yes,directories=yes,status=yes,scrollbars=yes,resizeable=yes,width=800,height=520,left=10,top=10');
window.xWindow.focus(); } </script>
Set the new domain to point to IP address 69.0.xxx.xx
so far I have this:
<html> <head> <title>New Page 1</title> <script language="javascript"> function LoadWindow() { var strURL strURL = 'log.htm'; xWindow = window.open (strURL,'NewWindow,'titlebar=yes,toolbar=yes,location=yes,directories=yes,status=yes,menubar=yes,scrollbars =yes,resizable=yes,width=800,height=520,left=10,top=10'); window.xWindow.focus(); } </script>
</head> <body> <form method="POST" action="http://xxx.xxx.com/userlogin.aspx"> <p>Username: <input type="text" name="Username" size="20"></p> <p>Password: <input type="text" name="Password" size="20"></p> <p><input type="submit" value="Submit" name="B1"><input type="reset" value="Reset" name="B2"></p> </form> </body> </html>
Any ideas where i can get more help, anything you can help me with would be greatly appreciated
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Nice article. If the PassThrough authentication was a WSE secure web service, it would be much cooler.
If we pick, do we not bleed!
|
| Sign In·View Thread·PermaLink | 2.00/5 (1 vote) |
|
|
|
 |
 | Nice. |  | Anonymous | 5:05 10 Sep '04 |
|
|
Looks like a simple way to implement. Yeah, Passport is not that much appreciated & I read about an article that talks about pitfalls of passport. Also, if you need the client users to connect to your application only after logging into their intranet, this method works. Another important thing is it needs SSL. Otherwise, anyone could hack the parameters and try to send it within the timeline. Well, it is a very slim possibility. However, the Application provider and the Client should be agreeing on the Private key - that should be stored very securily.
Well, good if this works for you! -Megan.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
 |
|
|
I have developed this for a Production application that is live now in our company. The method is proven to work. But, the code that I have provided here may have some more additional work to make it for Production. However, my intention is to write about the alternative way to use instead of Passport or SAML Federated Identity products.
Thanks for the comments.
Jay.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
As it stands, article is not fit to read (it requires excessive horizontal scrolling).
You're one microscopic cog in his catastrophic plan...
|
| Sign In·View Thread·PermaLink | 2.00/5 (1 vote) |
|
|
|
 |
|
|
this is the first time I posted anything using the Wizard. The preview was Ok. Hope it looks ok now..
thanks
Jay.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
<pre> blocks won't automatically wrap. Thus, the extremely long lines in your first code listing make the page very wide.
You're one microscopic cog in his catastrophic plan...
|
| Sign In·View Thread·PermaLink | 3.50/5 (2 votes) |
|
|
|
 |
|
|
General News Question Answer Joke Rant Admin
|