Skip to content
This repository has been archived by the owner on Jul 16, 2021. It is now read-only.

Commit

Permalink
Cleaned up the code and added the Resource.resx. Also extracted the h…
Browse files Browse the repository at this point in the history
…tmlTemplate into a text file, and correctly configured the error message to display in red.
  • Loading branch information
dscoduc committed Apr 16, 2017
1 parent 8681816 commit 850fd66
Show file tree
Hide file tree
Showing 9 changed files with 337 additions and 99 deletions.
47 changes: 23 additions & 24 deletions YubicoAuthProvider/AdapterPresentation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,48 +5,47 @@ namespace YubicoAuthProvider
{
class AdapterPresentation : IAdapterPresentation, IAdapterPresentationForm
{
private string message = String.Empty;
private bool isPermanentFailure;
private string errorMessage { get; set; }
private bool isPermanentFailure { get; set; }

public AdapterPresentation()
{
this.errorMessage = string.Empty;
this.isPermanentFailure = false;
}

public AdapterPresentation(string message, bool isPermanentFailure)
{
this.errorMessage = message;
this.isPermanentFailure = isPermanentFailure;
}

public string GetPageTitle(int lcid)
{
return "Yubico Authentication";
}

public string GetFormHtml(int lcid)
{
string html = "";
if (!String.IsNullOrEmpty(this.message))
string htmlTemplate = string.Empty;
string errorMessageTemplate = "<div class=\"fieldMargin error smallText\"><label id=\"errorText\">{0}</label></div>";

if (!String.IsNullOrEmpty(this.errorMessage))
{
html += "<p>" + message + "</p>";
htmlTemplate += string.Format(errorMessageTemplate, errorMessage);
}

if (!this.isPermanentFailure)
{
html += "<form method=\"post\" id=\"loginForm\" autocomplete=\"off\">";
html += "<input id=\"authMethod\" type=\"hidden\" name=\"AuthMethod\" value=\"%AuthMethod%\"/>";
html += "<input id=\"context\" type=\"hidden\" name=\"Context\" value=\"%Context%\"/>";
html += "<div class=\"groupMargin\"> Insert the YubiKey into a USB port and tap the button. </div>";
html += "<div class=\"fieldMargin error smallText\"><label id=\"errorText\" for=\"\"></label></div>";
html += "<div><input id=\"pin\" class=\"text fullWidth\" name=\"pin\" value=\"\" placeholder=\"YubiKey\" tabindex=\"1\" autocomplete=\"off\" autofocus=\"\" /></div>";
html += "<div class=\"submitMargin\"><input id=\"continueButton\" type=\"submit\" name=\"Continue\" value=\"Continue\" tabindex=\"2\" /></div>";
html += "</form>";
htmlTemplate += Resource.htmlTemplate;
}
return html;

return htmlTemplate;
}

public string GetFormPreRenderHtml(int lcid)
{
return string.Empty;
}
public AdapterPresentation()
{
this.message = string.Empty;
this.isPermanentFailure = false;
}
public AdapterPresentation(string message, bool isPermanentFailure)
{
this.message = message;
this.isPermanentFailure = isPermanentFailure;
}
}
}
47 changes: 20 additions & 27 deletions YubicoAuthProvider/AuthenticationAdapterMetadata.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,23 +6,24 @@ namespace YubicoAuthProvider
{
class AuthenticationAdapterMetadata : IAuthenticationAdapterMetadata
{
//Returns the name of the provider that will be shown in the AD FS management UI (not visible to end users)
private string providerName = "Yubico Authentication Provider";

public string AdminName
{
get { return "Yubico Authentication Provider"; }
get
{
return this.providerName;
}
}

//Returns an array of strings containing URIs indicating the set of authentication methods implemented by the adapter
/// AD FS requires that, if authentication is successful, the method actually employed will be returned by the
/// final call to TryEndAuthentication(). If no authentication method is returnd, or the method returned is not
/// one of the methods listed in this property, the authentication attempt will fail.
public virtual string[] AuthenticationMethods
{
get { return new string[] { "http://schemas.microsoft.com/ws/2012/12/authmethod/otp" }; }
get
{
return new string[] { "http://schemas.microsoft.com/ws/2012/12/authmethod/otp" };
}
}

/// Returns an array indicating which languages are supported by the provider. AD FS uses this information
/// to determine the best language\locale to display to the user.
public int[] AvailableLcids
{
get
Expand All @@ -31,48 +32,40 @@ public int[] AvailableLcids
}
}

/// Returns a Dictionary containg the set of localized friendy names of the provider, indexed by lcid.
/// These Friendly Names are displayed in the "choice page" offered to the user when there is more than
/// one secondary authentication provider available.
public Dictionary<int, string> FriendlyNames
{
get
{
Dictionary<int, string> _friendlyNames = new Dictionary<int, string>();
_friendlyNames.Add(new CultureInfo("en-us").LCID, "Yubico Authentication Provider");
_friendlyNames.Add(new CultureInfo("en-us").LCID, this.providerName);
return _friendlyNames;
}
}

/// Returns a Dictionary containing the set of localized descriptions (hover over help) of the provider, indexed by lcid.
/// These descriptions are displayed in the "choice page" offered to the user when there is more than one
/// secondary authentication provider available.
public Dictionary<int, string> Descriptions
{
get
{
Dictionary<int, string> _descriptions = new Dictionary<int, string>();
_descriptions.Add(new CultureInfo("en-us").LCID, "Yubico Authentication Provider");
_descriptions.Add(new CultureInfo("en-us").LCID, this.providerName);
return _descriptions;
}
}

/// Returns an array indicating the type of claim that that the adapter uses to identify the user being authenticated.
/// Note that although the property is an array, only the first element is currently used.
/// MUST BE ONE OF THE FOLLOWING
/// "http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsaccountname"
/// "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/upn"
/// "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress"
/// "http://schemas.microsoft.com/ws/2008/06/identity/claims/primarysid"
public string[] IdentityClaims
{
get { return new[] { "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/upn" }; }
get
{
return new[] { "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/upn" };
}
}

//All external providers must return a value of "true" for this property.
public bool RequiresIdentity
{
get { return true; }
get
{
return true;
}
}
}
}
4 changes: 2 additions & 2 deletions YubicoAuthProvider/Properties/AssemblyInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("YubicoAuthProvider")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyDescription("Yubico Yubikey OTP Authenentication Provider for AD FS 3.0")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyCompany("Chris Blankenship")]
[assembly: AssemblyProduct("YubicoAuthProvider")]
[assembly: AssemblyCopyright("Copyright © 2017")]
[assembly: AssemblyTrademark("")]
Expand Down
17 changes: 17 additions & 0 deletions YubicoAuthProvider/Readme.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
Implementation steps:

1. Copy .DLL files into C:\Windows\ADFS
- YubicoAuthProvider.dll
- Yubico.Library.dll

2. Add app.config sections to C:\Windows\ADFS\Microsoft.IdentityServer.Servicehost.exe.config

3. Update config with YubikeyCloud ID and Key

4. Register into AD FS using the following command:

5. Use PowerShell to register provider into AD FS
- $typeName = "YubicoAuthProvider.YubikeyOTP, YubicoAuthProvider, Version=1.0.0.0, Culture=neutral, PublicKeyToken=7649c32bf1339c5d";
- Register-AdfsAuthenticationProvider -TypeName $typeName -Name "YubicoAuthProvider" -Verbose

6. Restart AD FS services
78 changes: 78 additions & 0 deletions YubicoAuthProvider/Resource.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

124 changes: 124 additions & 0 deletions YubicoAuthProvider/Resource.resx
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<data name="htmlTemplate" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>htmlTemplate.txt;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8</value>
</data>
</root>
Loading

0 comments on commit 850fd66

Please sign in to comment.