<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Geek Scrapbook &#187; How-To</title>
	<atom:link href="http://www.geekscrapbook.com/tag/how-to/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.geekscrapbook.com</link>
	<description>The .Net developer&#039;s everyday how-to guide.</description>
	<lastBuildDate>Sun, 22 May 2011 01:57:14 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.1.2</generator>
		<item>
		<title>How To: Build A Sign On Service Like Windows Live Using ASP.Net</title>
		<link>http://www.geekscrapbook.com/2009/07/05/how-to-build-a-single-sign-on-service-like-windows-live/</link>
		<comments>http://www.geekscrapbook.com/2009/07/05/how-to-build-a-single-sign-on-service-like-windows-live/#comments</comments>
		<pubDate>Sun, 05 Jul 2009 13:17:33 +0000</pubDate>
		<dc:creator>Dave</dc:creator>
				<category><![CDATA[Guides]]></category>
		<category><![CDATA[Sign On Series]]></category>
		<category><![CDATA[How-To]]></category>

		<guid isPermaLink="false">http://www.geekscrapbook.com/?p=25</guid>
		<description><![CDATA[If you run a business that serves a variety of web-enabled products to your clients, the task of implementing sign-on logic for each one can become redundant and hard to maintain. Having a single sign on service can help modularize the sign on process for all of your products as well as add fluidity as [...]]]></description>
			<content:encoded><![CDATA[<p align="left">If you run a business that serves a variety of web-enabled products to your clients, the task of implementing sign-on logic for each one can become redundant and hard to maintain. Having a single sign on service can help modularize the sign on process for all of your products as well as add fluidity as your users move between your services.</p>
<p>First, I would suggest looking into one of the single sign on services already out there such as Windows Live or OpenID. There’s no real point in building your own service if it’s possible to use one of these readily available services. However, if for some reason these services just don’t fit your needs, this article will cover a simple solution.</p>
<p>I’ll be covering, in order, the following pieces:</p>
<ol>
<li>Database </li>
<li>A Simple Sign-in Page </li>
<li>Web Service </li>
<li>Integrating an Application </li>
</ol>
<p>All the code is available for download at the end of this article. You may want to download it in advance and follow along.</p>
<p><strong>Database      <br /></strong>I’ll be working in a database I’ve named SingleSignOn. The following script will create your tables:</p>
<p><a title="SQL File to Create Your Single Sign On Tables" href="http://www.geekscrapbook.com/wp-content/uploads/2009/07/SingleSignOn.txt" target="_blank">Download SQL</a></p>
<p>For this guide we will keep things simple, starting with the database design. We only need 3 tables to do the job:</p>
<ul>
<li>Users </li>
<li>UserSessions </li>
<li>Applications </li>
</ul>
<p>The code in this article is going to assume you’ve already filled up your users table so you may want to fill it with some sample data (remember to <a href="http://md5-hash-online.waraxe.us/" target="_blank">hash the passwords using MD5</a>); a registration screen won’t be difficult to add on later. A test user is included in the downloadable SQL file at the end of the article.</p>
<p>We will explore the tables more fully as we build our service.</p>
<p><strong>A Simple Sign-in Page      <br /></strong>Instead of having users for each of your products log in using yet another log in page, we will create a central page that will handle all login requests and then perform the appropriate redirect.</p>
<p>The sign-in page will do a few things:</p>
<ol>
<li>Identify the requesting application </li>
<li>Authenticate the user </li>
<li>Create a session for the user </li>
<li>Redirect the user </li>
</ol>
<p>Our page will check the query string for the application ID. This will allow us to display to the users what application they are logging into, but more importantly it tells our sign-in page where to send them once we’ve authenticated them.</p>
<p>Before we can start our sign-in page, we need to create an access layer for our database. For the sake of simplicity, I will use LINQ to SQL.</p>
<p><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://www.geekscrapbook.com/wp-content/uploads/2009/07/image5.png" width="400" height="394" /></p>
<p>Now, let’s create a page with a few labels, a couple text-boxes, and a sign-in button.</p>
<p><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://www.geekscrapbook.com/wp-content/uploads/2009/07/image15.png" width="334" height="178" /></p>
<p>On page load, we will check for an application ID in the query string. We don’t really need to do anything with it yet other than set our labels.</p>
<pre class="csharpcode c-sharp"><span class="kwrd">protected</span> <span class="kwrd">void</span> Page_Load(<span class="kwrd">object</span> sender, EventArgs e)
{
    <span class="kwrd">int</span> appID;
    <span class="kwrd">string</span> sAppID = Request.QueryString[<span class="str">&quot;appid&quot;</span>];

    <span class="kwrd">if</span> (!String.IsNullOrEmpty(sAppID) &amp;&amp; <span class="kwrd">int</span>.TryParse(sAppID, <span class="kwrd">out</span> appID))
    {
        SingleSignOn.Database.Context dbCon = <span class="kwrd">new</span> Context(DBSettings.SignOnConnectionString);
        SingleSignOn.Database.Application app = dbCon.Applications.Where(
            a =&gt; a.ApplicationID == appID
            ).FirstOrDefault();

        <span class="kwrd">if</span> (app != <span class="kwrd">null</span>)
        {
            lblApplicationName.Text = app.Name;
            lblPublisher.Text = app.Publisher;
        }
    }
}</pre>
<p>
  </p>
<style type="text/css">
<p>.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }</style>
<p>Now, let’s stub out some helper methods. We will need methods to authenticate a user based on an email address and a password, as well as methods to create a session and redirect the user to the correct place.</p>
<pre class="csharpcode"><span class="kwrd">protected</span> <span class="kwrd">int</span> AuthenticateUser(<span class="kwrd">string</span> username, <span class="kwrd">string</span> passwordhash)
{
    <span class="kwrd">return</span> -1;
}

<span class="kwrd">protected</span> <span class="kwrd">string</span> CreateUserSession(<span class="kwrd">int</span> userID)
{
    <span class="kwrd">return</span> <span class="kwrd">null</span>;
}

<span class="kwrd">protected</span> <span class="kwrd">void</span> RedirectUser(<span class="kwrd">string</span> sessionID)
{

}</pre>
<p>
  </p>
<style type="text/css">
<p>.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }</style>
<p>Let’s add an event to our sign-in button and write the code that will direct the flow.</p>
<pre class="csharpcode"><span class="kwrd">protected</span> <span class="kwrd">void</span> btnSignIn_Click(<span class="kwrd">object</span> sender, EventArgs e)
{
    <span class="kwrd">int</span> userID = AuthenticateUser(txtEmail.Text, txtPassword.Text);
    <span class="kwrd">if</span> (userID == -1)
    {
        lblError.Text = <span class="str">&quot;Sign in failed. Please try again&quot;</span>;
        <span class="kwrd">return</span>;
    }

    <span class="kwrd">string</span> sessionID = CreateUserSession(userID);

    <span class="kwrd">if</span> (String.IsNullOrEmpty(sessionID))
    {
        lblError.Text = <span class="str">&quot;Error during sign in. Please try again.&quot;</span>;
        <span class="kwrd">return</span>;
    }

    RedirectUser(sessionID);
}</pre>
<p>
  </p>
<style type="text/css">
<p>.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }</style>
<p>Now, we just need to implement our methods.</p>
<p>AuthenticateUser will need to find the user trying to log in, test the hash of the entered password against the one stored in our database, and, on a successful match, return the user’s ID. On failure, we’re going to return –1.</p>
<pre class="csharpcode"><span class="kwrd">protected</span> <span class="kwrd">int</span> AuthenticateUser(<span class="kwrd">string</span> email, <span class="kwrd">string</span> password)
{
    <span class="kwrd">string</span> passwordHash = GetMd5Sum(password);
    SingleSignOn.Database.Context dbCon = <span class="kwrd">new</span> Context(DBSettings.SignOnConnectionString);
    SingleSignOn.Database.User user = dbCon.Users.Where(
        u =&gt; u.Email.ToLower() == email.ToLower() &amp;&amp; u.Password == passwordHash
        ).FirstOrDefault();

    <span class="kwrd">if</span> (user != <span class="kwrd">null</span>)
    {
        <span class="kwrd">return</span> user.UserID;
    }

    <span class="kwrd">return</span> -1;
}</pre>
<p>
  </p>
<style type="text/css">
<p>.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }</style>
<p>CreateUserSession takes the user ID we retrieved and initializes a session. It then returns the session ID.</p>
<pre class="csharpcode"><span class="kwrd">protected</span> <span class="kwrd">string</span> CreateUserSession(<span class="kwrd">int</span> userID)
{
    <span class="kwrd">try</span>
    {
        SingleSignOn.Database.Context dbCon = <span class="kwrd">new</span> Context(DBSettings.SignOnConnectionString);
        SingleSignOn.Database.UserSession newSession = <span class="kwrd">new</span> UserSession();
        newSession.Created = DateTime.Now;
        newSession.SessionID = Guid.NewGuid();
        newSession.UserID = userID;
        newSession.Expires = DateTime.Now.AddMinutes(1.0);
        dbCon.UserSessions.InsertOnSubmit(newSession);
        dbCon.SubmitChanges();
        <span class="kwrd">return</span> newSession.SessionID.ToString();
    }
    <span class="kwrd">catch</span>
    {
        <span class="kwrd">return</span> <span class="kwrd">null</span>;
    }
}</pre>
<p>
  </p>
<style type="text/css">
<p>.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }</style>
<p>We’ve set the session to expire after a minute, which is more than enough time to redirect the user back to the application they are logging into. We’re using the “Expires” column to determine how long the user has to complete the sign-in handshake before this session is declared “dead”.</p>
<p>RedirectUser will determine where to send the user based on the application ID found in the query string. You may wish to handle the case where there is no application ID by dictating a default application ID. We’ll place the session ID in the query string so the application can handle the handshake with our web service.</p>
<pre class="csharpcode"><span class="kwrd">protected</span> <span class="kwrd">void</span> RedirectUser(<span class="kwrd">string</span> sessionID)
{
    <span class="kwrd">int</span> appID;
    <span class="kwrd">string</span> sAppID = Request.QueryString[<span class="str">&quot;appid&quot;</span>];

    <span class="kwrd">if</span> (!String.IsNullOrEmpty(sAppID) &amp;&amp; <span class="kwrd">int</span>.TryParse(sAppID, <span class="kwrd">out</span> appID))
    {
        SingleSignOn.Database.Context dbCon = <span class="kwrd">new</span> Context(DBSettings.SignOnConnectionString);
        SingleSignOn.Database.Application app = dbCon.Applications.Where(
            a =&gt; a.ApplicationID == appID
            ).FirstOrDefault();

        <span class="kwrd">if</span> (app != <span class="kwrd">null</span>)
        {
            Response.Redirect(app.RedirectUrl + <span class="str">&quot;?sid=&quot;</span> + sessionID);
        }
    }
}</pre>
<p>
  </p>
<style type="text/css">
<p>.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }</style>
<p>Our sign-in page is now functional enough to perform its duties. Let’s move on to our web service.</p>
<p><strong>Web Service</strong></p>
<p>The web service really only needs a single method: GetUserSessionInfo. This web method will examine our session ID, make sure it is valid, and return a class (that we will also create) containing the user’s ID, email, and display name.</p>
<pre class="csharpcode">[WebMethod]
<span class="kwrd">public</span> UserInfo GetUserSessionInfo(<span class="kwrd">string</span> sessionId)
{
    SingleSignOn.Database.Context dbCon = <span class="kwrd">new</span> Context(DBSettings.SignOnConnectionString);

    UserSession theSession = dbCon.UserSessions.Where(
        us =&gt; us.SessionID == <span class="kwrd">new</span> Guid(sessionId)
        ).FirstOrDefault();

    <span class="kwrd">if</span> (theSession != <span class="kwrd">null</span> &amp;&amp; theSession.Expires &gt; DateTime.Now &amp;&amp; theSession.Serviced == <span class="kwrd">null</span>)
    {
        theSession.Serviced = DateTime.Now;
        dbCon.SubmitChanges();
        <span class="kwrd">return</span> <span class="kwrd">new</span> UserInfo(
            theSession.User.UserID,
            theSession.User.Email,
            theSession.User.DisplayName);
    }

    <span class="kwrd">return</span> <span class="kwrd">null</span>;
}

[Serializable()]
<span class="kwrd">public</span> <span class="kwrd">class</span> UserInfo
{
    <span class="kwrd">public</span> <span class="kwrd">int</span> UserID { get; set; }
    <span class="kwrd">public</span> <span class="kwrd">string</span> Email { get; set; }
    <span class="kwrd">public</span> <span class="kwrd">string</span> DisplayName { get; set; }

    <span class="kwrd">public</span> UserInfo()
    {
    }

    <span class="kwrd">public</span> UserInfo(<span class="kwrd">int</span> userID, <span class="kwrd">string</span> email, <span class="kwrd">string</span> displayName)
    {
        <span class="kwrd">this</span>.UserID = userID;
        <span class="kwrd">this</span>.Email = email;
        <span class="kwrd">this</span>.DisplayName = displayName;
    }
}</pre>
<p>
  </p>
<style type="text/css">
<p>.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }</style>
<p>Notice that once the Serviced time is set, the session is considered “used” and won’t be valid again. This is a security measure that prevents the user’s session from being re-used. Now, let’s see how everything pieces together by integrating an application into our new architecture.</p>
<p><strong>Integrating an Application</strong></p>
<p>For our first application, we will build a simple profile viewer site. First, let’s add the information for the application into our applications table (we are going to assume everything is running on a local IIS server):</p>
<pre class="csharpcode">INSERT <span class="kwrd">INTO</span> Applications (Name, Publisher, IntegrationDate, RedirectUrl)
<span class="kwrd">VALUES</span> (<span class="str">'My Profile'</span>, <span class="str">'www.geekscrapbook.com'</span>, GetDate(), <span class="str">'http://localhost/myprofile'</span>)</pre>
<p>
  </p>
<style type="text/css">
<p>.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }</style>
<p>Let’s add a class to our project called IntegratedPage. This will handle all the sign-on logic. On each request, we will make sure the Asp.Net session variable “UserInfo” is set. If it isn’t, we will check to see if there is a session ID in the query string. If there is one, we will call the web service method and set the session information. Otherwise, we will redirect the user to the single sign on site.</p>
<pre class="csharpcode"><span class="kwrd">public</span> <span class="kwrd">class</span> IntegratedPage : System.Web.UI.Page
{
    <span class="kwrd">protected</span> <span class="kwrd">override</span> <span class="kwrd">void</span> OnPreInit(EventArgs e)
    {
        <span class="kwrd">if</span> (UserInfo == <span class="kwrd">null</span>)
        {

            <span class="kwrd">string</span> s = Request.QueryString[<span class="str">&quot;sid&quot;</span>];

            <span class="kwrd">if</span> (!String.IsNullOrEmpty(s))
            {

                localhost.SignOnService webService = <span class="kwrd">new</span> localhost.SignOnService();
                UserInfo = webService.GetUserSessionInfo(s);
            }
        }

        <span class="kwrd">if</span> (UserInfo == <span class="kwrd">null</span>)
        {
            Response.Redirect(<span class="str">&quot;http://localhost/signonsite/default.aspx?appid=1&quot;</span>);
        }

        <span class="kwrd">base</span>.OnPreInit(e);
    }

    <span class="kwrd">public</span> localhost.UserInfo UserInfo
    {
        get
        {
            <span class="kwrd">return</span> (localhost.UserInfo)Session[<span class="str">&quot;UserInfo&quot;</span>];
        }
        set
        {
            Session[<span class="str">&quot;UserInfo&quot;</span>] = <span class="kwrd">value</span>;
        }
    }

}</pre>
<p>
  </p>
<style type="text/css">
<p>.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }</style>
<p>Now all we have to do to require sign-in for a page is derive it from our new IntegratedPage:</p>
<pre class="csharpcode"><span class="kwrd">public</span> <span class="kwrd">partial</span> <span class="kwrd">class</span> _Default : IntegratedPage
{
    <span class="kwrd">protected</span> <span class="kwrd">void</span> Page_Load(<span class="kwrd">object</span> sender, EventArgs e)
    {
        lblEmail.Text = UserInfo.Email;
        lblDisplayName.Text = UserInfo.DisplayName;
    }
}</pre>
<p>So, let’s put it all together. I simply added each of the three web projects as applications to my machine’s IIS server, allowing me to test locally:</p>
<p align="center"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; margin-left: 0px; border-left-width: 0px; margin-right: 0px" title="image" border="0" alt="image" src="http://www.geekscrapbook.com/wp-content/uploads/2009/07/image4.png" width="300" height="331" />&#160;&#160;&#160;&#160;&#160; <img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; margin-left: 0px; border-left-width: 0px; margin-right: 0px" title="image" border="0" alt="image" src="http://www.geekscrapbook.com/wp-content/uploads/2009/07/image6.png" width="300" height="332" />&#160;</p>
<p>And there you have it: sign on handled independently from a central location.</p>
<p><strong>Download the Solution </p>
<p></strong>You can download a zip file of the solution by clicking the link below.</p>
<p><a href="http://www.geekscrapbook.com/wp-content/uploads/2009/07/SingleSignOn.zip">SingleSignOn.zip</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.geekscrapbook.com/2009/07/05/how-to-build-a-single-sign-on-service-like-windows-live/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Multiple WordPress Sites on GoDaddy&#8217;s Windows Hosting</title>
		<link>http://www.geekscrapbook.com/2009/07/03/how-to-install-multiple-wordpress-blogs-using-godaddys-windows-hosting/</link>
		<comments>http://www.geekscrapbook.com/2009/07/03/how-to-install-multiple-wordpress-blogs-using-godaddys-windows-hosting/#comments</comments>
		<pubDate>Fri, 03 Jul 2009 19:00:47 +0000</pubDate>
		<dc:creator>Dave</dc:creator>
				<category><![CDATA[Guides]]></category>
		<category><![CDATA[How-To]]></category>

		<guid isPermaLink="false">http://www.geekscrapbook.com/?p=5</guid>
		<description><![CDATA[UPDATE: This post is now obsolete since GoDaddy now allows multiple installations of wordpress. I’ll call that a bug fixed! This is a fitting first post, since this site exists thanks to the solution. As referenced in some other spots, GoDaddy&#8217;s Windows hosting isn&#8217;t really WordPress-friendly. Being a .Net developer, I can&#8217;t live without the [...]]]></description>
			<content:encoded><![CDATA[<p><strong>UPDATE: </strong>This post is now obsolete since GoDaddy now allows multiple installations of wordpress. I’ll call that a bug fixed!</p>
<p>This is a fitting first post, since this site exists thanks to the solution. As referenced in some other spots, GoDaddy&#8217;s Windows hosting isn&#8217;t really WordPress-friendly. Being a .Net developer, I can&#8217;t live without the Windows hosting, but let&#8217;s face it: WordPress is pretty neat. Copying up my locally WORKING test blog just wasn&#8217;t enough, unfortunately. I found the only way to install WordPress was to go through GoDaddy&#8217;s &#8220;Hosting Connection&#8221; and have them set it up for me. The Hostinng Connection is just a big library of web applications you can one-click-install, and GoDaddy will do all the work for you in setting them up. So, I went through the install for my wife&#8217;s blog, no problem. Ten minutes later the blog was up and running (<a href="http://www.mommybug.com">http://www.mommybug.com</a>). I thought, &#8220;Hey, that was easy! Let&#8217;s add another.&#8221;</p>
<p>Wait. Now when I check the Hosting Connection, I only have the option to UNINSTALL WordPress? Come on! You let me install it in a subfolder, but you&#8217;re not going to let me install more than one copy? Eventually after talking with support and getting nowhere, I was frustrated enough to try uninstalling the first blog, so I clicked the &#8220;Uninstall&#8221; link. To my surprise it asked me if I wanted to delete the files and drop the database.</p>
<p>I said, &#8220;&#8230;. NO! I&#8217;ll keep them!&#8221;</p>
<p>After &#8220;uninstalling,&#8221; The very next thing I did was visit my wife&#8217;s blog. It was still there. I went back to the Hosting Connection and hit &#8220;Install&#8221; to install WordPress again, but pointed it at the &#8220;geekscrapbook&#8221; subfolder. 10 minutes later, I&#8217;ve got two&#8211;COUNT &#8216;EM, TWO&#8211;WordPress blogs on the same GoDaddy hosting account.</p>
<p>All this after 3-4 days of talking to support. Sometimes it&#8217;s just best to do things yourself.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.geekscrapbook.com/2009/07/03/how-to-install-multiple-wordpress-blogs-using-godaddys-windows-hosting/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

