Created
February 2, 2012 23:45
-
-
Save justincjahn/1726488 to your computer and use it in GitHub Desktop.
AD Authentication
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<%@ Import Namespace="System" %> | |
<%@ Import Namespace="System.Text.RegularExpressions" %> | |
<%@ Import Namespace="System.DirectoryServices" %> | |
<%@ Import Namespace="System.Web" %> | |
<%@ Page Language="C#" %> | |
<script language="c#" runat="server"> | |
// Constants | |
const string AD_SERVER = "10.0.0.0"; | |
const string AD_DOMAIN = "AD"; | |
// A list of possible errors with the login form. | |
Dictionary<String, String> aErrors = new Dictionary<string,string>(); | |
// The return values of the authentication request, if done. | |
bool IsAuthenticated = false; | |
SearchResult oResult; | |
string[] aGroups; | |
/// <summary> | |
/// Occurs when the page loads. | |
/// </summary> | |
/// <param name="sender"></param> | |
/// <param name="e"></param> | |
protected void Page_Load(object sender, EventArgs e) | |
{ | |
if (Page.IsPostBack) { | |
// Initialize variables | |
String sUsername = Request.Form["username"].Trim(); | |
String sPassword = Request.Form["password"]; | |
// Validate username characters | |
Regex oReg = new Regex(@"^[a-zA-Z0-9]{3,}$"); | |
if (!oReg.IsMatch(sUsername)) | |
{ | |
// Add an error to the hashtable | |
aErrors["username"] = "Username contains invalid characters or is too short."; | |
} | |
// Validate password length | |
if (sPassword.Length < 6) { | |
aErrors["password"] = "Password is too short."; | |
} | |
// Check to see if we're clear to send the information to AD | |
if (aErrors.Count == 0) { | |
try { | |
// Attempt the login | |
oResult = Login(sUsername, sPassword); | |
aGroups = Groups(oResult).ToArray(); | |
IsAuthenticated = true; | |
} catch (Exception error) { | |
aErrors["failure"] = "Username or password not found: " + error.Message; | |
} | |
} | |
} | |
} | |
/// <summary> | |
/// Validate a user's credentials via AD. | |
/// </summary> | |
/// <param name="username">The users identity.</param> | |
/// <param name="password">The user's credential.</param> | |
/// <exception cref="Exception">If the connection to AD fails.</exception> | |
/// <returns>The user's path in Active Directory.</returns> | |
protected SearchResult Login(string username, string password) | |
{ | |
// Create the full username from provided username | |
string sDomainUser = AD_DOMAIN + @"\" + username; | |
// Create the DirectoryEntry we will use to query AD | |
DirectoryEntry oEntry = new DirectoryEntry(@"LDAP://" + AD_SERVER, sDomainUser, password); | |
// If the connection to the server fails or the user isn't valid an | |
// exception will be thrown. | |
try { | |
// Force authentication by binding the native object | |
object oNative = oEntry.NativeObject; | |
// Query the user's information | |
DirectorySearcher oSearch = new DirectorySearcher(oEntry); | |
oSearch.Filter = "(SAMAccountName=" + username + ")"; | |
// Add items to return as a result | |
oSearch.PropertiesToLoad.Add("cn"); | |
oSearch.PropertiesToLoad.Add("memberOf"); | |
// Do the query | |
SearchResult oResult = oSearch.FindOne(); | |
// Determine if the user is valid | |
if (oResult == null) { | |
// It isn't, so return an empty string | |
throw new Exception("Username or Password not found."); | |
} else { | |
// It is, return the path to the user within AD | |
return oResult; | |
} | |
} catch (Exception e) { | |
// Something went wrong, throw an exception | |
throw new Exception("Unable to authenticate user: " + e.Message); | |
} | |
} | |
/// <summary> | |
/// Fetch the groups for a specific user. | |
/// </summary> | |
/// <param name="result">The result of an AD/LDAP query.</param> | |
/// <returns>A list of groups.</returns> | |
public List<string> Groups(SearchResult result) | |
{ | |
// Verify the result has a memberOf property | |
if (!result.Properties.Contains("memberOf")) { | |
throw new Exception("No group information provided with result."); | |
} | |
// Create the StringBuilder that will gather the groups together | |
List<string> oGroups = new List<string>(); | |
try { | |
// Loop through each returned memberOf entry and format it properly | |
int iCount = result.Properties["memberOf"].Count; | |
int iEquals, iComma; | |
string dn; | |
for (int i = 0; i < iCount; i++) { | |
// Get the LDAP DN of the entry | |
dn = (string)result.Properties["memberOf"][i]; | |
// Find the location of the equal sign and comman within the DN | |
iEquals = dn.IndexOf("=", 1); | |
iComma = dn.IndexOf(",", 1); | |
// If we don't have an equal sign then we don't have any groups | |
if (iEquals == -1) return oGroups; | |
// Add the substring (and resulting group) to our StringBuilder object | |
oGroups.Add(dn.Substring((iEquals + 1), (iComma - iEquals) - 1)); | |
} | |
} catch (Exception e) { | |
throw new Exception("Error obtaining groups names: " + e.Message); | |
} | |
// Return the group names | |
return oGroups; | |
} | |
</script> | |
<!DOCTYPE html> | |
<html> | |
<head> | |
<title>Hello, World!</title> | |
</head> | |
<body> | |
<h1>Please Login</h1> | |
<% if (IsAuthenticated == true) { %> | |
<h2>Login Success!</h2> | |
<p class="success"> | |
<%=oResult.Path%> | |
</p> | |
<p class="success"> | |
<%=String.Join(", ", aGroups)%> | |
</p> | |
<% } %> | |
<% if (aErrors.ContainsKey("failure")) { %> | |
<h2>Login Failure!</h2> | |
<p class="error"><%=aErrors["failure"]%></p> | |
<% } %> | |
<form action="Default.aspx" method="post" runat="server"> | |
<dl class="login"> | |
<dt><label for="username">Username</label></dt> | |
<dd><input type="text" name="username" id="username" /></dd> | |
<% if (aErrors.ContainsKey("username")) { %> | |
<dd><p class="error"><%=aErrors["username"]%></p></dd> | |
<% } %> | |
<dt><label for="password">Password</label></dt> | |
<dd><input type="password" name="password" id="password" /></dd> | |
<% if (aErrors.ContainsKey("password")) { %> | |
<dd><p class="error"><%=aErrors["password"]%></p></dd> | |
<% } %> | |
<dt> </dt> | |
<dd><input type="submit" name="loginSubmit" id="loginSubmit" value="Login" /></dd> | |
</dl> | |
</form> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment