Skip to main content

Allowing someone to update their own Active Directory Contact details via OWA

Modifying your own user details via GALMOD or one of it derivates has been around for sometime. I wrote this little app a few years ago at the bequest of a secretary to allow users with non admin rights to modify other people’s details using a WSC Com object. A question came up last week about being able to do this in OWA via a public folder for those users that might be outside your network that may only have access to OWA though a front backend setup etc. Exchange does give you the ability in OWA to register and run your own custom forms (do a search on WSS.forms in the Exchange SDK for more details). So one way of achieving what this person asked to do was to register a custom ASP WSS form and include some ADSI to do the work of modifying the user’s account and phone details. If you’re not running Exchange on a Domain controller (which should be the case for most people bar SBS users) you have to consider delegation issues when your page is going to request the changes be made on behalf of the user. A couple a ways to work around this is to specify alternate credentials in your code to make the changes with. Or use a COM+ wrapper and a com object (or a WSC com object like I did here). Security wise it’s usually better to use a COM+ wrapper to store your username and password instead of storing it as clear text in the asp file if your going to be storing your asp file in the Exchange store where someone may be able to get easy access to the source. I decided to put together a real simple example of a WSS.From that could be used to change a user’s phone number detail’s using ADSI and some hard coded credentials.

The code itself is pretty simple installing it and getting it to work can be a little challenging for the uninitiated. I’ve used the method that is prescribed in the Exchange SDK which involves a few steps.

Before you start you need to make sure that you enable scripts for ASP pages on the Exchange server or you will receive a 403 permissions error when you try and view the folder. To enabled scripts you use Exchange System Manager go to Servers-Protocols-HTTP-Exchange Virtual Directory. Select the Public virtual directory and then right click and select properties. Go to the access table under execute permission select scripts then save and exit.

Hard coded script bits the following script has 2 hardcoded bits you need to change to use it the first is the servername of a Domain controller where the changes are going to be made. The second is the username and password of a user with rights to make changes to the properties that you are modifying. Both these setting are in the following line

Set oUser = Dirobj.OpenDSObject("LDAP://servername/"& sysinfo.UserName, "domain\user", "password", 0)

Installation I’ve created a script call forminst.vbs and included it in the download of this post that performs the following steps for you it will prompt you for the name of the root folder to create and it will also upload the asp page from d:\ into the public folder

The first step is to create the folder you want the form to be registered on.
The next step is to create a hidden folder that will contain the form registration and the ASP page itself.
The next step is to set the urn:schemas-microsoft-com:exch-data:schema-collection-ref property on the parent folder to point to the folder that was created in step two.
The next step is to create the default form registration on the child folder that will tell exchange to display the ASP page for any requests made for the parent folder in OWA.
The last step is then to upload the asp page to the child folder.

That’s it if you receive a 403 error when you try and view the folder in OWA make sure you have set scripting rights in Exchange System Manager (the rights should also be reflected in IIS admin). From a security point of view you should consider building a com object and using a COM+ wrapper if you where going to use this in production.

I’ve put a downloadable copy of the code from this post here the Form itself looks like

<%
Set oForm = Server.CreateObject("WSS.Form")
dim sysinfo
dim oUser
Set sysinfo = CreateObject("ADSystemInfo")
set Dirobj = GetObject("LDAP:")
Set oUser = Dirobj.OpenDSObject("LDAP://DCservername/"& sysinfo.UserName,
"domain\user", "password", 0)
If Request.ServerVariables("REQUEST_METHOD") = "GET" Then
oForm.fields("FName").value = oUser.GivenName
oForm.fields("LName").value = oUser.sn
oForm.fields("Bphone").value = oUser.TelephoneNumber
oForm.fields("Mphone").value = oUser.mobile
oForm.fields("Hphone").value = oUser.homephone
oForm.fields.update
oForm.Render
else
If Request.ServerVariables("REQUEST_METHOD") = "POST" Then
if oForm.Fields("FName").Value = "" then
oForm.Elements("FName").ErrorString = "<span style=""COLOR:red"">First Name
Required<span>"
oForm.Render
elseif oForm.Fields("LName").Value = "" then
oForm.Elements("LName").ErrorString = "<span style=""COLOR:red"">Last Name
Required<span>"
oForm.Render
else
oUser.GivenName = oForm.Fields("FName").Value
oUser.sn = oForm.Fields("LName").Value
oUser.TelephoneNumber = oForm.Fields("BPhone").Value
if oForm.Fields("BPhone").Value = "" then
oUser.putex 1,"TelephoneNumber", vbNull
else
oUser.TelephoneNumber = oForm.Fields("BPhone").Value
end if
if oForm.Fields("MPhone").Value = "" then
oUser.putex 1,"mobile", vbNull
else
oUser.mobile = oForm.Fields("MPhone").Value
end if
if oForm.Fields("HPhone").Value = "" then
oUser.putex 1,"homephone", vbNull
else
oUser.homephone = oForm.Fields("HPhone").Value
end if
oUser.setinfo
oForm.Elements("Result").ErrorString = "<span style=""COLOR:red"">Updated<span>"

oForm.Render
end if
else
end if
end if
%>

<HTML>
<HEAD>
<BASE TARGET="_top">

</HEAD>

<BODY><!The Data URL macro is expanded at runtime by
the renderer so that the Submit
button will post back to the item itself.>
<FORM action="" id=FORM1 method=post name="FORM1"
target="_self">

<H1> Phone Number Details
<INPUT class="field" name="result"
style="HEIGHT: 25px; WIDTH: 0px"></H1>
<br><br>

<b>First Name:</b> <INPUT class="field" name="FName"
style="HEIGHT: 25px; WIDTH: 200px"> <br><br>
<b>Last Name:</b> <INPUT class="field" name="LName"
style="HEIGHT: 25px; WIDTH: 200px"> <br><br>
<b>Business PhoneNumber:</b> <INPUT class="field"
name="Bphone" style="HEIGHT: 23px; WIDTH: 200px">
<br><br>
<b>Mobile PhoneNumber:</b><INPUT class="field"
name="Mphone" style="HEIGHT: 23px; WIDTH: 200px">
<br><br>
<b>Home Phone:</b> <INPUT class="field" name="Hphone"
style="HEIGHT: 25px; WIDTH: 200px"> <br>
<br><br>
&nbsp;<INPUT id=submit1 name=submit1 type=submit
value=Submit>

</FORM>

</BODY>
</HTML>
 

Popular posts from this blog

The MailboxConcurrency limit and using Batching in the Microsoft Graph API

If your getting an error such as Application is over its MailboxConcurrency limit while using the Microsoft Graph API this post may help you understand why. Background   The Mailbox  concurrency limit when your using the Graph API is 4 as per https://docs.microsoft.com/en-us/graph/throttling#outlook-service-limits . This is evaluated for each app ID and mailbox combination so this means you can have different apps running under the same credentials and the poor behavior of one won't cause the other to be throttled. If you compared that to EWS you could have up to 27 concurrent connections but they are shared across all apps on a first come first served basis. Batching Batching in the Graph API is a way of combining multiple requests into a single HTTP request. Batching in the Exchange Mail API's EWS and MAPI has been around for a long time and its common, for email Apps to process large numbers of smaller items for a variety of reasons.  Batching in the Gr...

Exporting and Uploading Mailbox Items using Exchange Web Services using the new ExportItems and UploadItems operations in Exchange 2010 SP1

Two new EWS Operations ExportItems and UploadItems where introduced in Exchange 2010 SP1 that allowed you to do a number of useful things that where previously not possible using Exchange Web Services. Any object that Exchange stores is basically a collection of properties for example a message object is a collection of Message properties, Recipient properties and Attachment properties with a few meta properties that describe the underlying storage thrown in. Normally when using EWS you can access these properties in a number of a ways eg one example is using the strongly type objects such as emailmessage that presents the underlying properties in an intuitive way that's easy to use. Another way is using Extended Properties to access the underlying properties directly. However previously in EWS there was no method to access every property of a message hence there is no way to export or import an item and maintain full fidelity of every property on that item (you could export the...

Sending a Message in Exchange Online via REST from an Arduino MKR1000

This is part 2 of my MKR1000 article, in this previous post  I looked at sending a Message via EWS using Basic Authentication.  In this Post I'll look at using the new Outlook REST API  which requires using OAuth authentication to get an Access Token. The prerequisites for this sketch are the same as in the other post with the addition of the ArduinoJson library  https://github.com/bblanchon/ArduinoJson  which is used to parse the Authentication Results to extract the Access Token. Also the SSL certificates for the login.windows.net  and outlook.office365.com need to be uploaded to the devices using the wifi101 Firmware updater. To use Token Authentication you need to register an Application in Azure https://msdn.microsoft.com/en-us/office/office365/howto/add-common-consent-manually  with the Mail.Send permission. The application should be a Native Client app that use the Out of Band Callback urn:ietf:wg:oauth:2.0:oob. You ...
All sample scripts and source code is provided by for illustrative purposes only. All examples are untested in different environments and therefore, I cannot guarantee or imply reliability, serviceability, or function of these programs.

All code contained herein is provided to you "AS IS" without any warranties of any kind. The implied warranties of non-infringement, merchantability and fitness for a particular purpose are expressly disclaimed.