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: |
|
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: |
|
Permissions: |
Grant |
Target Resource Definition Before Request: |
All People |
Target Resource Definition After Request: |
All People |
Resource Attributes: |
|
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;
}
}
}