Programmatic User Registration

Programmatic User Registration

FIM 2010 R2 Self-Service Password Reset provides a way for administrators to programmatically register users for password reset workflows. This is done with the use of PowerShell cmdlets. These cmdlets can be used to set required data for all the FIM 2010 R2 interactive authentication gates: QA gate, one-time-password Email gate, and the one-time-password SMS gate. These cmdlets will allow administrators to populate the QA gates and set user data for the OTP Email and OTP SMS gates

The following four new cmdlets have been added to accomplish these tasks.

Required SNapIn

These new cmdlets have been added to the FIM Automation SNapIn. In order to use the cmdlets you must add the FIMAutomation SnapIn in PowerShell. This can be done by entering the following in PowerShell before using one of the cmdlets:

PS C:\> Add-PSSNapIn FIMAutomation

Required Management Policy Rules

The following Management Policy Rules must be created before an administrator can use the programmatic user registration functionality that is provided by the PowerShell cmdlets. The first policy allows the creation and deletion of gate registration objects. The second policy allows modification of user attributes for the case of OTP gates:One-Time Password Email Address (msidmOneTimePasswordEmailAddress) and One-Time Password Mobile Phone (msidmOneTimePasswordMobilePhone). The settings for these MPRs are:

Policy 1

Create and Delete Gate Registration Objects

Type:

Request

Requestors:

Administrators

Operation:

  • Delete resource

  • Create resource

Permissions:

Grant

Target Resource Definition Before Request:

All Gate Registration

Target Resource Definition After Request:

All Gate Registration

Resource Attributes:

All Attributes

Policy 2

Modify OTP Gate Attributes

Type:

Request

Requestors:

Administrators

Operation:

  • Add a value to multivalue attribute

  • Remove a value from a multivalue attribute

  • Modify a single-valued attribute

Permissions:

Grant

Target Resource Definition Before Request:

All People

Target Resource Definition After Request:

All People

Resource Attributes:

  • AuthN Workflow Locked Out

  • AuthN Workflow Registered

  • One-Time Password Email Address

  • One-Time Password Mobile Phone

The following example shows how one might use programmatic registration. It is code that creates a C# console application which pulls data from a fictional HR text file.

The following is a copy of the text file:

EmployeeId, SSN, DomainName, Department, AccountName, AlternateEmail, FirstName, LastName
10120, 123-20-5555, Contoso, Identity, bsimon, bsimon@corp.contoso.com, Britta, Simon
10121, 123-21-5555, Contoso, Identity, ljacobson, ljacobson@corp.contoso.com, Lola, Jacobson

This code is provided as an example of how one might programmatically register large numbers of users with data from authoritative data sources.

//********************************************************
//*                                                      *
//*   Copyright (C) Microsoft. All rights reserved.      *
//*                                                      *
//********************************************************
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace PowerShellAutomation
{
    using System.Collections.ObjectModel;
    using System.Data;
    using System.IO;
    using System.Management.Automation;
    using System.Management.Automation.Runspaces;

    class Program
    {
        static void Main(string[] args)
        {
            // Get Users Data 
            DataSet dataSource = Program.GetDataSource(@"C:\demo\datasource.txt");

            // Create Runspace Configuration and add the FIMAutomation snapin
            RunspaceConfiguration rc = RunspaceConfiguration.Create();
            PSSnapInException warning;
            PSSnapInInfo info = rc.AddPSSnapIn("FIMAutomation", out warning);
            if (warning != null)
            {
                Console.WriteLine(warning.Message);
                return;
            }

            using (Runspace runspace = RunspaceFactory.CreateRunspace(rc))
            {
                runspace.Open();

                Console.WriteLine("Getting the registration template...");
                Pipeline pipeline1 = runspace.CreatePipeline();
                pipeline1.Commands.AddScript("$wftemplate = Get-AuthenticationWorkflowRegistrationTemplate -AuthenticationWorkflowName \"Password Reset AuthN Workflow\" ");
                Collection<PSObject> results1 = pipeline1.Invoke();

                foreach (DataRow userRow in dataSource.Tables["users"].Rows)
                {
                    string registerScript = CreateRegistrationScript(userRow);
                    Console.WriteLine("Registering user... ");
                    RunPowrShellScript(runspace, registerScript);
                }
                runspace.Close();
            }
        }

        private static string CreateRegistrationScript(DataRow userRow)
        {
            string domainName = userRow[2].ToString();
            string accountName = userRow[4].ToString();
            string lastName = userRow[7].ToString();
            string employeeId = userRow[0].ToString();
            string socialSecurityNumber = userRow[1].ToString();
            string alternateEmail = userRow[5].ToString();

            StringBuilder scriptText = new StringBuilder();
            scriptText.AppendLine("$usertemplate = $wftemplate.Clone()");
            scriptText.AppendLine("$usertemplate.GateRegistrationTemplates[0].Data[0].Value=\"" + lastName + "\"");
            scriptText.AppendLine("$usertemplate.GateRegistrationTemplates[0].Data[1].Value=\"" + employeeId + "\"");
            scriptText.AppendLine("$usertemplate.GateRegistrationTemplates[0].Data[2].Value=\"" + socialSecurityNumber + "\"");
            scriptText.AppendLine("$usertemplate.GateRegistrationTemplates[1].Data[0].Value=\"" + alternateEmail + "\"");
            scriptText.AppendLine("Register-AuthenticationWorkflow -UserName \"" + domainName + "\\" + accountName + "\"  -AuthenticationWorkflowRegistrationTemplate $userTemplate");

            return scriptText.ToString();
        }

        private static void RunPowrShellScript(Runspace runspace, string script)
        {
            try
            {
                Pipeline pipeline = runspace.CreatePipeline();
                pipeline.Commands.AddScript(script);
                Collection<PSObject> results = pipeline.Invoke();
                Console.WriteLine("Operation Completed");
            }
            catch(Exception exception)
            {
                Console.WriteLine("Error Encountered");
                File.AppendAllText("ErrorLog.txt", DateTime.Now.ToString() + exception.ToString());
            }
        }

        private static DataSet GetDataSource(string csvFileName)
        {
            DataSet dataSource = new DataSet();
            DataTable usersTable = new DataTable("users");
            bool firstline = true;

            foreach (string line in File.ReadAllLines(csvFileName))
            {
                if (firstline)
                {
                    foreach (string columnName in line.Split(','))
                    {
                        usersTable.Columns.Add(columnName);
                    }
                    firstline = false;
                }
                else
                {
                    DataRow row = usersTable.NewRow();

                    string[] dataItems = line.Split(',');
                    for (int i = 0; i <= dataItems.GetUpperBound(0); i++)
                    {
                        row[i] = dataItems[i].Trim();
                    }

                    if (row.ItemArray.Length > 0)
                    {
                        usersTable.Rows.Add(row);
                    }
                }
            }

            dataSource.Tables.Add(usersTable);
            return dataSource;
        }
    }
}