by Martin Laukkanen | Mar 13, 2013 | Development, How to
One of the great features of Claims authentication in SharePoint (2010 or 2013) is the ability to use external authentication providers such as ADFS, Microsoft LiveID (Hotmail, Outlook.com etc) or even Google among others. Better yet, using Microsoft Azure ACS makes setting up and managing this for extranet sites or Cloud applications simple!
The Catch!
However there’s one catch (isn’t there always?) Microsoft Live ID doesn’t give the email address in the claim. This sounds obscure but in effect what it means is that once you configure all of this this is what you get:
What a nice and friendly username!
(If you want instructions on configuring all this, I highly recommend Wictor Wilén’s indispensible series of articles on the topic: http://www.wictorwilen.se/Post/Visual-guide-to-Azure-Access-Controls-Services-authentication-with-SharePoint-2010-part-1.aspx)
Solutions?
Most people suggest using something like Google to authenticate instead to avoid this, however with SharePoint Online, Project Online, EPMonDemand (ahem – excuse the blatant plug!) and Office365 all tied to my LiveID, I personally don’t think that’s an option!
So basically we need to populate that information, sure we could ask users to do it manually, but better yet let’s find out how to do this the Microsoft way.
Live Connect API
In order to support Windows 8 apps, Web apps and all manner of mobile devices MS have this great resource available, head over to the Live Connect Developer Center to see more information. Once you’ve registered then you can follow my steps below to get you setup to auto-populate SharePoint user information via Javascript!
Getting this going
Note: Getting to the business end here; you’ll Visual Studio, some JavaScript, SharePoint Object Model and WebPart development experience to continue. (Or just skip to the end and download my example, like everyone else!)
Firstly you’ll need to create yourself an ‘application’ on Live Connect, something like the following:
The important thing is to note your Client ID, and then enter the correct URL under Redirect domain.
All done, easy!
If you want to see how all this works, the Interactive Live SDK is one of the best SDK implementations I’ve seen from MS, have a look at what kind of options are available to you.
For example, the following JavaScript will return the basic user information for the currently logged in user including name, email addresses and more;
WL.init({
client_id: “***********”,
redirect_uri: “callback.aspx”,
response_type: “token”
});
WL.login({ “scope”: “wl.emails” }).then(
function (response) {
updateUserData();
},
function (response) {}
);
function updateUserData() {
WL.api({ path: “/me”, method: “GET” }).then(
function (response) {
// Do something here!
},
function (response) {}
);
}
Neat hey?
Bring it all together
Okay not quite done yet, lets put this into a nice simple SharePoint webpart and then using the good old Object Model update the current users’ details.
What you need to do:
- Open Visual Studio and create a new SharePoint – Visual Web Part Project
- Create some ASP controls for your webpart, I won’t bore you with all the details here, get the full solution below in which I created the following:
- AccountTextBox
- NameTextBox
- EmailTextBox1
- UpdateButton
- Plus a bunch of labels to make things neat.
- We need a link to the Live Connect http://js.live.net/v5.0/wl.jsfile, to make this easier I have saved a copy in a Layouts folder in my solution, so my ScriptLink looks like this:
<SharePoint:ScriptLink ID="LiveIdscript" runat="server" Name="UpdateUserWebPart/wl.js"></SharePoint:ScriptLink>
- Also for the Live ID bit to work we need a callback.aspx file in our solution, which is referenced in the “redirect_uri” parameter passed to to WL.init in the JavaScript, this file should look something like the following;
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Authentication Complete</title>
</head>
<body>
<!--
The script will handle passing oauth/authorize response back to the calling page.
-->
<script src="/_layouts/15/UpdateFromLiveID/js/wl.js" type="text/javascript">
</script>
<p>This window can be closed.</p>
</body>
</html>
- Now for the JavaScript, first we need to initialise and try to login to Windows Live.
<SharePoint:ScriptBlock ID="ScriptBlock1" runat="server">
WL.init({
client_id: "*************",
redirect_uri: "<%=SPContext.Current.Web.Url %>/_layouts/15/UpdateUserWebPart/callback.aspx",
response_type: "token"
});
if (document.getElementById("<%=EmailTextBox1.ClientID %>").value == '') {
WL.login({ "scope": "wl.emails" }).then(
function (response) {
updateUserData();
},
function (response) {}
);
}
Above I’ve included an IF that checks for an existing Email address, if none is found then it automatically tries to login. (Pop-up blockers hate this, so you’ll need to do something nicer)
- Next here’s my updateUserData() function which is called on successful login;
function updateUserData() {
WL.api({ path: "/me", method: "GET" }).then(
function (response) {
document.getElementById("<%=EmailTextBox1.ClientID %>").value = response.emails.preferred;
if (!response.name) {
document.getElementById("<%=NameTextBox.ClientID %>").value = response.emails.preferred;
}
else {
document.getElementById("<%=NameTextBox.ClientID %>").value = response.name;
}
document.getElementById("<%=UpdateButton.ClientID %>").click();
},
function (response) {}
);
}
</SharePoint:ScriptBlock>
So once we have the user data we update our ASP controls created previously so we can use those in the code behind.
- Lastly we need some code behind to get the details and update our SPUser object.
protected void Page_Load(object sender, EventArgs e)
{
if (string.IsNullOrEmpty(AccountTextBox.Text))
{
AccountTextBox.Text = SPContext.Current.Web.CurrentUser.LoginName;
NameTextBox.Text = SPContext.Current.Web.CurrentUser.Name;
EmailTextBox1.Text = SPContext.Current.Web.CurrentUser.Email;
}
UpdateButton.Click += UpdateButton_Click;
}
- Here I’m updating the controls on Page_Load but only once, then creating an event for our Button.
- For the button I basically do the following:
void UpdateButton_Click(object sender, EventArgs e)
{
[...]
SPUser currentUser =
elevatedWeb.SiteUsers.GetByID(SPContext.Current.Web.CurrentUser.ID);
currentUser.Name = NameTextBox.Text;
currentUser.Email = EmailTextBox1.Text;
currentUser.Update();
[...]
}
To keep this short(er) I have cut out the RunWithElevatedPrivileges bits and such, you actually might not need to have that depending on your user permissions, but if you leave it in then I suggest reading this.
Are we done yet?
Now lets deploy and have a look;
That’s what we see initially, but once we allow that popup:
Make sure you select Yes.
Nice.
Now if everything’s working, clicking Update should do just that!
Hurrah!
Get my full example solution here built for Visual Studio 2012 in SharePoint 2012, just make sure you update it with your Client ID from Live Connect.
Conclusion
It’s not perfect, in fact it’s a way off (think application pages, modal dialogs, mmm), but hopefully this will get you started.
Any questions, post below, but I strongly recommend you play with the Interactive SDK on Live Connect and read the Getting started documentation there if you have any problems with the JavaScript. It took me quite a bit to get all that working together the first time!
Update: See my latest post on this topic for a better approach: http://nearbaseline.azurewebsites.net/blog/2013/07/sharepoint-hosted-apps-with-saml-authentication/
by Martin Laukkanen | Nov 24, 2011 | How to, Project 2010
One thing I always have to search for when creating a new EPT is the appropriate icon to use. I have previously found and used some of the out-of-the-box icons that can be found in any default Project Server 2010 installation and thought that I might share them here.
There is in fact a long list which I have included below (forgive me copyright gods in MS!), to use one of these icons, just update the image URL under Server Settings –> Enterprise Project Types, for example to update the default Sample Proposal with any of the icons below, simply modify the image URL under:
For a Master Project icon (taken from the image below), replace the URL above with the following:
/_layouts/inc/pwa/images/CenterMasterProject.png
Full list of icons (16×16 size only):
Enjoy!
by Martin Laukkanen | Jun 3, 2011 | How to, Project 2010, SharePoint 2010
A common requirement for many SharePoint and Project Server deployments is to have an external facing interface using an alternate Forms based authentication method, the most common is using an ASP.NET SQL provider which since the 2007 version is the one of the simplest options. With 2010 however and Claims authentication this requires that you convert your existing Windows authenticated Web Applications to Claims based NTLM authentication, this process is well documented online for SharePoint 2010, however I have recently found that with Project Server 2010 a number of problems can be encountered.
Here is a typical error with the Project Details webpart after conversion:
[Hi Google: (An unknown error has occurred)]
In this blog I’m not going to cover the whole process of setting up Extranet access, I’ll leave it to you to read some of the other excellent blogs on the topic linked below. What I will cover is how to do the not-so-well documented parts.
To Start With: Procedure to Setup Extranet Access
The general procedure for extending a Project Server application for extranet users is something like this:
- Provision a ASP.NET SQL membership Provider.
- Extend the Web Application to add an Extranet zone.
- Configure the Claims membership providers in the web.config files.
References for these steps:
- MMohanty: http://blogs.technet.com/b/mahesm/archive/2010/04/07/configure-forms-based-authentication-fba-with-sharepoint-2010.aspx
- Geoff Varosky: http://gvaro.wordpress.com/2011/03/28/planning-and-configuring-extranets-in-sharepoint-2010part-1/
- Geoff Varosky: http://gvaro.wordpress.com/2011/04/01/planning-and-configuring-extranets-in-sharepoint-2010part-2/
If you have followed those steps discussed in the links, then when you will likely have found that you are seeing all sorts of security issues after changing your Classic Web App to Claims.
In short the error above originates from the procedure used to migrate the application to Claims:
(WARNING: Don’t use the above commands!)
Unfortunately this does not fully migrate the SharePoint application and from my experience will lead to errors such as the first one above.
Migrating the Web Application to Claims Without Issues
Fortunately Microsoft has a well documented procedure: http://technet.microsoft.com/en-us/library/gg251985.aspx
$WebAppName = "http:// yourWebAppUrl"
$account = "yourDomainyourUser"
$wa = get-SPWebApplication $WebAppName
Set-SPwebApplication $wa -AuthenticationProvider `
(New-SPAuthenticationProvider) -Zone Default
Note: that the above commands migrate ALL Web Applications sharing that URL, it is not possible to only migrate your Extended application!
That command will migrate the web application fully and prepare it for Claims authentication, and don’t forget the TechNet article discusses the need to update your portalsuperreaderaccount and portalsuperuseraccount accounts if they have been set, which can be done easily using the following commands:
$wa.Properties["portalsuperuseraccount"] = "i:0#.w|domainapppool"
$wa.Properties["portalsuperreaderaccount"] = "i:0#.w|domainapppool"
$wa.Update()
Migrating Users to Re-enable Login
Once your Web App is in Claims mode then you will still need to migrate your AD users, this part is not so well documented.
Essentially you need to use the PowerShell command Move-SPUser to move all of your existing “DOMAINusername” users to the new Claims-NTLM identity “i0#.w|domainusername”.
Before you can do this you need to ensure that your admin user has permissions to access this site, this can be done from Central Admin by updating the Web Application Policy:
Add or re-add your user account (DOMAINadminuser) with Full Control to the web application in question, before proceeding with the following steps. (Note: the above Policy should now show your Admin user with the User Name like so; “i:0#.w|domainadminuser”)
Next, here is the command to migrate a single user:
Get-SPUser -web http://server/pwa -identity "DOMAINuser" | Move-SPUser -NewAlias "i:0#.w|domainuser" –IgnoreSID
The command will actually give the following error:
However if you then use Get-SPUser you will note that the account has actually been migrated.
So for my purposes I wrote the following script which will migrate all users without the claims prefix “i:0#.w|” (Yep ignore those errors!):
$UsersToMigrate = Get-SPUser -web http://server/pwa | `
where {$_.UserLogin –like ‘DOMAIN*’ }
ForEach ($user in $UsersToMigrate)
{
Get-SPUser -web http://server/pwa -identity $user | Move-SPUser `
-NewAlias ("i:0#.w|"+$user.UserLogin.toLower()) -IgnoreSID
}
After running the above, users should now be able to login to your migrated Web Application with any AD user!
If you see other errors running either that script or the above command by itself, make certain that you can do the following without errors:
Get-SPUser –web http://server/pwa
If not check your web policy again as above.
Finally Adding Your Claims Users to PWA
Now we have a fully migrated Claims-NTLM Web Application in addition to a newly created Extranet Claims Web Application which is attempting to use a Forms membership provider (SQL-MembershipProvider if you following the steps linked above).
The next steps are again well documented in the links above, configure your web.config files and then setup your SQL users.
The final problem you may face when attempting to add your new forms users to PWA, assuming (if using SQL that your ASPNETDB database permissions are correctly set) then adding the users to SharePoint will be easy using Site Actions – Site Permissions – Grant Permission, however what you will may see when attempting to add to Users to PWA is an error like the following:
(Error Message: The NT account specified is invalid. …)
This is because the user has not yet been added to the SharePoint site collection which fortunately is easy enough to fix, just add the user to SharePoint from Site Permissions first!
From Site Actions –> Site Permissions:
As long as SharePoint can find the user (make sure to use the full username!) then once you hit Ok the user identity will be added to the Site Collection, and then you will be able to add the user to PWA!
FYI if like me you like doing things in bulk here’s the PowerShell command to do the above:
New-SPUser -UserAlias "i:0#.f|SQLMembershipProvider|JaneDoe" -Web http://server/pwa -DisplayName "Jane Doe" -Email [email protected]
All done, enjoy your forms membership provider!
by Martin Laukkanen | Apr 16, 2011 | Development, How to, Project 2010
A very frequent request I get is how to change the default permissions assigned by Project Server to Project Workspace Sites for all projects, unfortunately this is not something that is configurable in Project Server so the only option out of the box is to disable the permissions sync and manage those permissions manually. Of course if you don’t want Administrators to manage every user manually this is not an option.
This is made more annoying if you want PM’s to be able to manage the site, as by default they only have Contribute like access.
There are a few options that exist out there, notably this one; Adjust the Default Project Web Access Permission Levels, which uses a SharePoint timer job to manage the default Permission Levels. However I have had need for something simpler, and so recently for a customer I implemented the following:
Modifying Basic Site Permissions using Project Events:
My solution is by intent extremely simple, so simple that I will include the main piece of code below (as well as having the full solution attached), in short what this code does is the following:
On Publish of any project does the following;
- Retrieves the OWNER of the Project
- Retrieves the Workspace Site of the Project
- Adds the Owner to the default SharePoint role SPRoleType.Administrator
So as you can see it only updates one user’s permissions, however it would be trivial to update the code to do more based on the Project Team and other requirements.
Here is the bulk of the code:
if (wssData.ProjWssInfo.Count == 0)
{
LogEventEntry(String.Format("No workspace site found for project: {0}",
projectData.Project.First().PROJ_NAME), EventLogEntryType.Warning);
}
else {
// Open the SPSite and web
using (SPSite pwsSite = new SPSite(wssData.ProjWssInfo[0].PROJECT_WORKSPACE_URL))
{
using (SPWeb pwsWeb = pwsSite.OpenWeb())
{
// Handle Null Email Address
String ownerEmail;
if (resourceData.Resources.First().IsWRES_EMAILNull()) ownerEmail = "";
else ownerEmail = resourceData.Resources.First().WRES_EMAIL;
// Add the new role assignment to the Owner
SPRoleAssignment roleAssn =
new SPRoleAssignment(resourceData.Resources.First().WRES_ACCOUNT,
ownerEmail,
resourceData.Resources.First().RES_NAME,
"Project Owner");
SPRoleDefinition roleDefn =
pwsWeb.RoleDefinitions.GetByType(SPRoleType.Administrator);
roleAssn.RoleDefinitionBindings.Add(roleDefn);
pwsWeb.RoleAssignments.Add(roleAssn);
}
}
}
The code is bound to both OnPublished and OnSummaryPublished (to get the Save from PWA also), and ensures that the Owner will always have Admin rights, and if not all the PM has to do is republish.
Download only the WSP package here with – basic – instructions.
Download the full source package here.
Notes:
- As an Event the solution runs under the security context of the Project Server Event Service account, and so this user must be a user in PWA with appropriate access, I use administrator however it could get by with less.
- This completely ignores the WssSync jobs created by Project Server, as such some actions such as AD sync and group membership changes can apply permissions outside of typical Publish events. However in my experience with 2010 this will not remove existing SharePoint permissions (see one of my previous blogs on this).
- The solution is built with Visual Studio 2010 and packaged as a WSP allowing for simple installation using typical SharePoint means.
- The solution uses Project Server 2010 WCF methods to access the PSI, and so without modification it will not work on Project Server 2007.
- The solution logs error information to the Event Log and not the ULS, this is because I’m lazy. However it means that on Windows Server 2008 if the user (Event Service Account) is not a local admin it will fail and log nothing.
Post comments with any questions or additions even, but please note that I can’t provide support for the standalone WSP package.
by Martin Laukkanen | Dec 4, 2010 | How to, SharePoint 2010
It seems SharePoint 2010 gives a nice new way to say exactly what versions of the binaries are installed on any given server in your farm, this is a great enhancement from 2007 which effectively required a Windows Explorer properties check at times to be absolutely sure that all the servers had been updated!
Find it in Central Admin by;
- Open Central Admin go to Upgrade and Migration
- Select Check product and path installation status
You should see something like the following:
Specifically if you scroll down you will see the project server section under each server in the farm, and in my case you can see the RTM version number plus the KB2394322 (October 2010 CU).
Nice.
FYI that SQL method still can come in handy (when migrating for instance) so if you’re not familiar with it here it is:
USE ProjectServer_Reporting
SELECT * FROM dbo.Versions
Not exactly as much detail as the above method, but it does confirm what version server your databases should belong to.
by Martin Laukkanen | Aug 7, 2010 | How to, Project 2010, Reporting
One of the biggest areas of advancement in Project Server 2010 is reporting, with Project now utilising; Excel Services, SQL Analysis Services, SQL Reporting Services and PerformancePoint the options are almost endless.
However most people I encounter look at that list and say; “What on earth is PerformancePoint?”, so lately I had another opportunity to flex my PPS skills and thought I might share my experience to give you a taste of how powerful yet simple to use this new thing can be.
Creating a Dynamic Resource Utilisation Graph using PerformancePoint
I’m going to keep this very simple, as I find PPS to be very often quite mind-boggling, so to give you a taste of it what I’ll describe here is how to create a simple equivalent to the old typical Data Analysis Resource Utilisation view.
So before you begin, make sure you have your Cube setup and built, the PerformancePoint service application setup and running in your SharePoint installation and some data to play with.
First step you need to get to the PerformancePoint Dashboard Designer, this is a nifty little web application (independent from the Office Web Apps) that is automatically installed and made available when you provision a PWA site.
To find it, open up the Business Intelligence site, and from there the quickest way to get to it is by hovering over any of the landing page images (Create Dashboards, etc) and selecting the ‘Start using PerformancePoint Services’ link.
You then have the icon to run Dashboard Designer:
This should download and install the designer for you, and assuming that you have all the correct permissions (and that PWA is in your Internet Explorer trusted sites), you will end up with a mostly empty designer window looking something like the image below.
Now you’re ready to start creating those reports, first step setup your Data Connections by selecting the Create tab on the ribbon and selecting Data Source:
Select Analysis Services as the connection type, and populate the connection details and properties as required:
For Analysis Services datasources you should populate the Time tab to ensure that your Time dimensions are correct, something like this;
Finally when you are done, select save from above the ribbon to continue.
Note: This is something you will get used to with the Dashboard Designer, everything is automatically saved to the PWA BI site in their respective locations (dataconnections, reports or dashboards), with just one exception being the ‘Workspace’ which is effectively your configuration of Dashboard Designer (something I don’t usually bother saving).
Now lets move on and create our report, select PerformancePoint Content and then from the Create ribbon lets select ‘Analytic Chart’;
Then select your datasource just created and hit finish, then your report will open in the designer;
Give it a name and then lets start adding content:
- First add some measures to the Series; Work and Actual Work.
- Now add your Resource List dimension to the Bottom Axis.
It should look something like this;
If you want to expand members of a dimension select the chevron (Down arrow next to the X), and select the members in the dialog.
Here for dynamic dimensions like the Resource list you are better off right-clicking and selecting one of the Autoselect Members, such as All Children, like so;
Which now looks like:
Finally we need our Time dimension, add it to the Bottom Axis from the right list and use the chevron to select the desired time periods (I’m selecting months by name here, however you can use something called Named Set’s to do this dynamically for you – another blog article maybe). Finally I think it’s best to move the Resource List to the top of the series Series list and apply some filters to filter out the blanks, to give us something like:
Don’t forget the Edit tab on the Ribbon which has a number of settings that you’ll find handy getting your report right.
Almost there now..
Okay so now we’re ready to save and see this thing for real, so hit the save button, and lets minimise the designer and go back to our BI site in Internet Explorer.
If you open the default ‘PerformancePoint Content’ link, you should see your new report listed, select the drop-down to Display the report:
Final product:
Now this report is ready to add to any where in SharePoint using the PerformancePoint viewer web part, and the best thing is that all of the dynamic functions will be available to all users, so if someone wants to view this report in terms of Cost / Actual Cost, it’s just a few clicks away:
Or maybe you want to see the breakdown of a particular person’s activities using the Decomposition Tree?
I’d say this beats those old Data Analysis views!
That’s it for this how-to, hopefully this scratching of the surface has shown you some of the potential of PPS, keep experimenting and you’ll see very quickly how easy it is to replace those old Data Analysis views that are so 1990!
In the future I might come back and write a Part II to this one on creating your first KPI Scorecard in PPS, stay tuned..