I wanted to set up a site for external users. The site needed a public area with anonymous access and then secured areas for users authenticated via Form Based Authentication (FBA). As I have never done this before I was happy to see the wealth of posts out there detailing the various approaches.
I did some reading and decided on the following approach:
- Claims based web application
- Top level site collection with anonymous access enabled (instructions, again one of many examples)
- Sub-sites with anonymous access enabled
Here are some instructions to do this. One of many examples; Easy enough.
What I struggled with was the authentication method. By default the authentication goes to a new page, a page that would need its own styling (AFAIK). There are some examples out there of webparts that do the job but they all seemed a bit overly complicated to me. Here is my approach.
1. Create a new Visual Webpart in Visual Studio
2. Stick this in the WebPart class
[WebBrowsable(true),
Category(“Common”),
WebDisplayName(“Redirect Page”),
WebDescription(“The page to redirect user to once logged in”),
Personalizable(PersonalizationScope.Shared)]
public string RedirectPage{ get; set; }
// Visual Studio might automatically update this path when you change the Visual Web Part project item.
private const string _ascxPath = @”~/_CONTROLTEMPLATES/<FeatureName>/ExternalLogin/ExternalLoginUserControl.ascx”;
protected override void CreateChildControls()
{
var control = Page.LoadControl(_ascxPath) as ExternalLoginUserControl;
if (control != null)
{
control.RedirectPage = RedirectPage;
Controls.Add(control);
}
}
3. Fire this into the user control ascx
<table>
<tr>
<td>User Name</td>
<td><asp:TextBox ID=”UserName” runat=”server”></asp:TextBox></td>
</tr>
<tr>
<td>Password</td>
<td><asp:TextBox ID=”Password” runat=”server” TextMode=”Password”></asp:TextBox></td>
</tr>
</table>
<asp:Button ID=”Login” runat=”server” Text=”Login” OnClick=”PerformLogin” />
<asp:Label runat=”server” ID=”ErrorMessage” style=”color:Red;”></asp:Label>
4. Shove this up the gullet of the ascx.cs file
public partial class ExternalLoginUserControl : UserControl
{
public string RedirectPage { get; set; }
private static string ErrorText = “Incorrect Username or Password.”;
protected void Page_Load(object sender, EventArgs e)
{
if ((SPContext.Current.Web.CurrentUser != null) &&
(SPClaimProviderManager.IsEncodedClaim(SPContext.Current.Web.CurrentUser.LoginName)))
{
RedirectUser();
}
}
protected void PerformLogin(object sender, EventArgs e)
{
try
{
if (SPClaimsUtility.AuthenticateFormsUser(new Uri(SPContext.Current.Web.Url), UserName.Text, Password.Text))
{
RedirectUser();
}
else
{
ReturnError();
}
}
catch
{
ReturnError();
}
}
private void RedirectUser()
{
Response.Redirect(RedirectPage);
}
private void ReturnError()
{
ErrorMessage.Text = ErrorText;
}
}
5. Deploy
6. Add Webpart to page in the top level site.
There we go; extranet site with user login form without having to go to a seperate site.
P.S Sorry for the lack of comments in the code but it sort of speaks for itself.