Custom Authentication

Overview

The majority of WorkflowGen clients use the Windows Integrated Authentication in IIS, although several other modes are supported. By using Integrated Authentication, users are seamlessly authenticated to WorkflowGen by using the Windows local session (network password) of the user.

WorkflowGen also supports .NET web form-based authentication and Custom HTTP modules for SSO integration.

SSO using a .NET custom HTTP module

The advantage of the custom HTTP module solution is that it secures all WorkflowGen HTTP requests, including web services. It also provides more customization possibilities than the form authentication-based solution.

This section focuses on the custom authentication module solution.

We recommend securing the WorkflowGen website with SSL and using encryption to secure the token. The code provided below is a basic sample, so you may have to customize it to enforce security and hide detailed error messages.

WorkflowGen Custom module authentication configuration

  1. Configure WorkflowGen to use Custom authentication module. Download CustomAuthModuleSSO.zip, unzip it, and copy the CustomAuthModuleSSO.dll file into the following folders:

    • \wfgen\bin

    • \wfgen\ws\bin

    • \wfgen\wfapps\webapp\eformaspx\bin

    • \wfgen\wfapps\webforms\bin

    • All other \bin folders under \wfgen

    Alternately, you can install the DLL in the GAC to avoid DLL duplication in the \bin subfolders. In this case, you must also install its dependencies (Advantys.My.dll and Advantys.Security.dll) in the GAC.

  2. In IIS, change the Authentication configuration. Enable "anonymous" on all IIS applications in the WorkflowGen website:

    • \wfgen

    • \wfgen\ws

    • \wfgen\wfapps\webforms

    • \wfgen\wfapps\webapps\eformaspx

    • \wfgen\wfapps\webapps

    • All other web applications you use in your processes

    ✏️ Note: The subfolders in the \wfgen\wfapps\webservices folder must use basic authentication.

  3. Create a Visual Studio project to edit the CustomAuthModuleSSO.cs file. In the Authentication function, change the following variables according to your tier app:

    • Cookie or Url param name where the username is base64 encoded or encrypted: string tokenName="token";

    • Your tier app Login URL to use when an authentication is required: string ssoLoginUrl="/remotesso.aspx";

    • The encryption key used to decrypt the token: string privateKey="mykey";

    • Activate encryption (true) or use base64 encoding (false) bool decryptUsername=false;

Tier application configuration

  1. Call WorkflowGen with the token. Your tier app has to encode (or encrypt) the username.

  2. Put the encoded username into a cookie (set to a parent domain), a URL parameter (the token value has to be URL encoded) or an HTTP header (for web service calls).

    • If a cookie:

      http://www.yourwfgwebsite.yourdomain.com/wfgen
    • If a URL parameter:

      http://www.yourwfgwebsite.yourdomain.com/wfgen/?token=........
    • If you have to call WorkflowGen web services, you must add an HTTP header with the token value.

  3. Manage the authentication request from WorkflowGen.

    • WorkflowGen calls your tier app login URL when authentication is required (session timeout, sign out, direct access to WorkflowGen).

    • WorkflowGen adds the ReturnUrl parameter to the URL. You must resend it to the login URL you use to call WorkflowGen following authentication.

📌 Examples

  • WorkflowGen calls your tier app login:

    http://www.yourwebsite.yourdomain.com/yourlogin?ReturnUrl=%2fwfgen%2fshow.aspx%3fQUERY%3dCONTEXT
  • Your tier app login calls WorkflowGen login URL:

    http://www.yourwfgwebsite.yourdomain.com/wfgen/loginsso.aspx?token=YXJuYXVk&ReturnUrl=%2fwfgen%2fshow.aspx%3fQUERY%3dCONTEXT

Manage the sign out request done by the tier app to log out the user in WorkflowGen.

  • Your tier app login calls WorkflowGen login URL with the signout=true querystring parameter:

    http://www.yourwfgwebsite.yourdomain.com/wfgen/loginsso.aspx?signout=true
  • You can customize the loginsso.aspx source to manage the redirection the way you want in this case.

Encryption method

The example provided supports base64 encoding or encryption. For the encryption option, loginsso.aspx uses 3DES mode ECB with MD5 to hash the private key by default. You can customize the loginsso.aspx code according to your requirements.

📌 PHP code example

$key = 'mykey';
$string = 'string to be encrypted';
$encrypted = base64_encode(mcrypt_encrypt(MCRYPT_3DES, md5($key), $string, MCRYPT_MODE_ECB);

Sample code for an HTTP module

Overview

This sample is an HTTP module that uses HTTP authentication. You must insert your own method to authenticate users.

For more information, see Custom HTTP Basic authentication in the WorkflowGen Technical Guide.

Source code

//*********************************************************************
// Copyright ©.
//
// Purpose:
// Sample code for an HTTP module
//
//*********************************************************************
using System;
using System.Web;
using System.Security.Principal;
using System.Text;
using System.Diagnostics;
namespace MyCompany.Hosting.Samples
{
/// <summary>
/// Summary description for CustomAuthModule
/// </summary>
public class CustomAuthModule : IHttpModule
{
/// <summary>
/// Constructor
/// </summary>
public CustomAuthModule()
{
}
#region IHttpModule Members
/// <summary>
/// Release any resources
/// </summary>
public void Dispose()
{
}
/// <summary>
/// Initialization of module
/// </summary>
/// <param name="context"></param>
public void Init(HttpApplication application)
{
application.AuthenticateRequest += new EventHandler(application_AuthenticateRequest);
}
/// <summary>
/// Delegate for authenticating a request
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void application_AuthenticateRequest(object sender, EventArgs e)
{
HttpApplication application = sender as HttpApplication;
Debug.Assert(application != null);
// Has the client sent Authorization information
//
if (application.Context.Request.ServerVariables["HTTP_AUTHORIZATION"] == null)
{
// Redirects client to send HTTP Basic credentials
//
application.Response.StatusCode = 401;
application.Response.AddHeader("WWW-Authenticate", "Basic");
application.Response.End();
}
else
{
// Retrieve authentication string
//
string authString = application.Request.ServerVariables["HTTP_AUTHORIZATION"];
// If the authentication method is basic
//
if (authString.StartsWith("basic", StringComparison.InvariantCultureIgnoreCase))
{
string[] credentials;
bool isValidUser = false;
// Decode credentials
//
credentials = DecodeBase64String(authString.Substring(6)).Split(':');
// Credentials should have two cells
//
// credentials[0] is the username
// credentials[1] is the password
Debug.Assert(credentials.Length == 2);
//
// ****************************
// Perform your check here
// ****************************
//
// isValidUser = YourAuthenticationMethod(credentials[0], credentials[1]);
if (isValidUser)
{
// Create a user
//
GenericPrincipal user =
new GenericPrincipal(
new GenericIdentity(credentials[0], authString),
new string[] { "role_name" });
// Set this user for the session
//
application.Context.User = user;
}
}
}
}
/// <summary>
/// Decodes a Base64-encoded string
/// </summary>
/// <param name="base64EncodedString"> </param>
/// <returns></returns>
private string DecodeBase64String(string base64EncodedString)
{
try
{
UTF-8Encoding encoder = new UTF-8Encoding();
Decoder decoder = encoder.GetDecoder();
byte[] bytesToDecode = Convert.FromBase64String(base64EncodedString);
int charCount = decoder.GetCharCount(bytesToDecode, 0, bytesToDecode.Length);
char[] decodedChars = new char[charCount];
decoder.GetChars(bytesToDecode, 0,
bytesToDecode.Length, decodedChars, 0);
return new String(decodedChars);
}
catch (Exception e)
{
throw new Exception("Error in DecodeBase64String: " + e.Message);
}
}
#endregion
}
}