Archive for February, 2013

Office 365 Road Warrior’s guide to quick and dirty ADFS web-auth page customization

Beautiful it is not, the out-of-the-box ADFS logon page that is. Unless you are late 90s minimalist and don’t care for any kind of web adornments. (I am thinking of an example of white background page with minimum number of controls… Hmm)
Anyhow, every time I am deploying ADFS to authenticate to Office 365 I am being ask to tweak a few things. This posting, is an abridged collection of webpage quick “tweaks” that I’ve accumulated throughout last couple of years. I want to note that this is by no means “pretty” looking tweaks. I don’t go for pretty here. The key words here are: quick and useful. You should talk with your web-designer to get yourself fabulously looking ADFS logon page; However if you are looking for quick and dirty tricks you can deploy in a few minutes without signing SOW, keep reading.

ADFS-Example-Mod

This collection of “beatifications” will satisfy few common requests that I’ve heard from many system admins. Let’s start with obvious and easiest one:

Adding Logo to your ADFS SignIn page:

This is the most basic and most common of all requests. To brand your page with company logo, you will need to:
Place your logo image file (jpg, png or gif) into the root of the ADFS web-site [by default] C:\inetpub\adfs\ls\ In the web.config file (located in the same location) remove comments (like htis one: <!--) around and modify the file name referenced in the web.config to reflect name of your logo file

<!--
<add key=”logo” value=”logo.png” />
-->

While you are in the web.config file

Adding legal disclaimer:

Take a look at the legal disclaimer section of the web.config. Uncommenting that section will provide you with out-of-the-box functionality requiring users to acknowledge terms of use/legal agreement before proceeding with authentication.

Removing <%EndPointName%> URL from from SignIn page:

Your published federation end-point might not be something you would like to expose to your end-users. sts.contoso.com might look cool to a system admin, but it will likely to confuse your end-user and could complicate troubleshooting for your helpdesk folks. To remove that URL “label” form your ADFS logon page you’ll need to do following:
We’ll be modifying master.cs page to comment out line STSLabel.Text = FriendlyName;

This is how it should look like:

using System;
using System.Web.UI;


public partial class MyMasterPage : Microsoft.IdentityServer.Web.UI.MasterPage
{
protected void Page_Load( object sender, EventArgs e )
{
PageTitleLabel.Text = Page.Title;
//STSLabel.Text = FriendlyName;
}
}

Adding server name:

While installing multiple ADFS nodes/proxy servers behind network load-balancers you might want to display name of the server user is currently connected to. It might not be important to the end-user, but might help you with troubleshooting effort.

in FormsSignIs.aspx :
Insert following above this line </asp:Content>:


<div>
<asp:Label Text="DisplayYourServerNameHere" runat="server" />
</div>

Don’t forget to do IISRESET after your changes are done

Changing Log-Out “landing” page experience

As a result of federation authentication redirection “ping-pong” your users will land onto default Office 365 login page after they have click log-off button. The reason for it is pretty simple:
a) User askes to log-off in the UI of Office 365
b) O365 knows that user is coming from federated environment and redirects user to the on-prem ADFS server to process that request
c) You on-prem ADFS server receives the request and knows that it came from the Office 365 federated partner. It processes user request to log-off and
d) Faithfully forwarding user back to the originator of the request – the office365
e) Since user is no longer authenticated or technically “known” to Office 365, it present user with default login page in attemt to authenticate him/her
It’s hard to dispute machine logic here, yet in some cases this is not desirable behavior, especially if you are trying to create “walled” experience for your users, such as promoting use of the web-portal(s) to login/access your Office 365 resources, or communicating specific redirection URLs to your user community. Therefore to modify default log-out behavior I’ve came up with this tweak:

a) Locate your default OOTB ADFS sing-out page (default location should be: C:\inetpub\adfs\ls\SignOut.aspx)
b) Edit it with your favorite text editor and insert following JaveScript snippet right above/before the closing tag </asp:Content>. (Which is at the very end of the document) Don’t forget to actually insert your URL into the script

<script type="text/javascript">
window.location = 'http://YourLandingPage';web
</script>

c) In command-prompt run IISRESET

Note:
JavaScript is very touchy about quotes, single quotes, spaces etc. Cut/Paste from this page might come through with HTML artifacts. Verify your text before inserting into your logout page, and (of course) keep a backup of your original page version.

Modifying “hint” label [domain\username] next to the textbox user name textbox

I have wrote an article explaining the UPN vs. email story. This is somewhat extending on previous story and show you how to change default label on ADFS logon page prompting user to login with UPN. Note that this “tweak” is targeting English language page. Being politically correct and properly written web-site, the default landing page for ADFS is coming with dozens of localizations. Please locate corresponding language resource to make change for every language you wish to support.

In <%drive%>:\inetpub\adfs\ls\App_GlobalResources\CommonResources.en.resx

locate following line:

<data name="UsernameExample" xml:space="preserve">
<value>Example: username@contoso.com</value>
</data>

Note: Do not make a copy/backup of *.resx file into the same folder. If you need to make a copy of original file, move it outside of \App_GlobalResources folder

Happy tweaking!

Advertisements

Permanently deleting Office 365 accounts from the Recycle Bin

After long pause in my posts, I want to return with this simple Office 365 script I found to be useful.

Since introduction of soft-delete functionality the “Microsoft Online Services Module for Windows PowerShell” was updated with new switch. Namely –RemoveFromRecycleBin switch was added to Remove-MsolUser cmdlet.

Soft-delete is a great failsafe feature allowing an administrator some time to reconcile accidental deletes. Let’s say you’ve accidently deleted or moved out of Dirsync’s scope AD user; your best friend DirSync faithfully synchronized your change (delete) into the office 365. Shortly thereafter, your favorite user calls you and reports that his mailbox is no longer there. Oops! Good news is that you can restore the account and move on to your next cup of coffee.

However, while you are testing and setting things up, soft-delete can be a little bit of an annoyance. When you really really want to kill those test accounts and recreate them again (and again). Or whatever the reason is, but you want those accounts gone for good. DirSync will NOT help you there, all deletes form current version of DirSync are “soft-deletes” therefore you have to connect with Powershell and remove your deleted accounts from the recycle bin. When you are dealing with more than handful of those deletes, you will probably want to have some automation to the process, unless you are enjoying typing too much.

I want to add this EXPLICIT DISCLAIMER to the post:
Neither the author of this script and article nor his employer, are responsible for any action(s), operation(s) or consequences of those action(s) and/or operation(s) or any loss of data, productivity, profits or other kind of  event(s). By using it you are taking full responsibility for whatever this script is about to do with your data, and all consequences of those modification. After all, we are talking about killing perfectly good user account. Please think twice before just running this script.
Thank you!

<#

. [COPYRIGHT]
. © 2011-2012 Dmitry Kazantsev, Microsoft. All rights reserved.
.
. [DISCLAIMER]
. This sample script is not supported under any Microsoft standard support
. program or service. The sample scripts are provided AS IS without warranty of
. any kind. Microsoft disclaims all implied warranties including, without
. limitation, any implied warranties of merchantability or of fitness for a
. particular purpose. The entire risk arising out of the use or performance of
. the sample scripts and documentation remains with you. In no event shall
. Microsoft, its authors, or anyone else involved in the creation, production,
. or delivery of the scripts be liable for any damages whatsoever (including,
. without limitation, damages for loss of business profits, business
. interruption, loss of business information, or other pecuniary loss) arising
. out of the use of or inability to use the sample scripts or documentation,
. even if Microsoft has been advised of the possibility of such damages.
#>


Import-Module MSOnline;
Write-Host ("Collecting admin credential");
$cred = Get-Credential;


Write-Host ("Connecting to your Office 365 tenent");
Connect-MsolService -Credential $cred;



Write-Host ("Enumerating users in the Recycle Bin");
$users = Get-MsolUser -ReturnDeletedUsers -All;


Write-Host ("Total number of accounts found: " + $users.Count);
[int]$index = 1;
[System.String]$message = "You are permanently deleting " + $users.Count + " user(s). Do you want to proceed? [Y] or [N]";
$responce = Read-Host -Prompt $message;


if ([System.String]::Equals("Y", $responce, [System.StringComparison]::OrdinalIgnoreCase))
{
Write-Host ("License to kill has been granted...")
foreach ($user in $users)
{
Write-Host ("Removing user " + $index + " of " + $users.Count + " | with UPN:'" + $user.UserPrincipalName + "' from the Recycle Bin");
#
# TODO: You will need to uncomment following line, to confirm that that you are dead-certain about killing all those innocent user accounts
#
#Remove-MsolUser –RemoveFromRecycleBin –UserPrincipalName $user.UserPrincipalName -Force -Verbose;
$index++;
}
}
else
{
Write-Host ("Ufff... I thought that you were kidding");
}

Once again. Dont hurt yourself accidently.