Yammer and SharePoint Online are becoming more and more integrated. Recently, with the Yammer Embed widget supporting SSO from Office 365 to Yammer, we are in a situation where we can perform actions against Yammer from SharePoint Online without requiring further authentication.
This opens up opportunities for utilising the Yammer SDK and Yammer REST API to build all kinds of Yammer interactions directly into your SharePoint pages. It also allows us to start implementing some of those anti-patterns that customers want but Yammer doesn’t want to support as they’re against ‘social freedom’. A prime example of this is forcing users into groups. In some scenarios it may be rather practical. I won’t discuss the pros and cons of this further but do consider that Microsoft would rather you coerce users socially to make their own decision to join the ‘correct’ groups rather than programmatically deciding for them.
Regardless of that, I’m going to provide an example which, upon page load, joins the current O365 user’s Yammer identity to a Yammer group based upon their SharePoint user profile.I’d like to point out that if Yammer Embed is present on the page and is enabled with Single Sign On, then the authentication piece can be hidden entirely from the user. I am currently unaware how to achieve SSO with Yammer from SharePoint Online without pigging-backing Yammer Embed, although I haven’t looked in earnest so I suspect it’s achievable without too much effort.
A few notes on the code:
Add the first code snippet to a page with a Script Editor web part. It calls the initiation code and any configurations can be provided here, and modified when live
The second code snippet contains all the logic. This can be included to the page in any manner you wish but you must ensure it has loaded prior to running the init function
In order to use the Yammer SDK you must register a Yammer app on the target network and provide the client ID as the data-app-id attribute on the script element which includes it
Each user must authorise the Yammer app, just once, before it can act in their behalf. I have implemented this as a status message, an example of which can be seen in the image below
Each user must authorise the Yammer App to act on their behalf
The code references ‘hut Id’ which is just a value stored in user’s profile and which is used to map a user to a Yammer group
I use local storage to prevent the code executing more often than every 24 hours. This has been commented out for clarity, however I would recommend functionality such as this is re-implemented
The experience of signing into Yammer from SharePoint is different if SharePoint is hosted on-premise or online. Only when online is the same identity used and can an SSO experience be achieved. In contrast, on-prem, the disconnect between O365 and Yammer credentials allows users to to provide credentials for any Yammer user in any Yammer network rather than being restricted to the associated identity
And finally, the code:
Finally, for completeness, here is a the settings object which I pass to Yammer Embed to achieve SSO with Yammer from SharePoint Online. I find that in practice anywhere I would want to run the above code I also have a feed of some sort that is appropriate to display. If this is not the case for you, hiding the feed with display:none will achieve the same result as long as the width of the Yammer Embed is equal to or greater than 400px. Note that this is *not* required, however without it the user may be prompted to provide their Yammer credentials.
I recently had some trouble trying to update a user’s profile properties via the SharePoint Online Admin console. I would provide values for the fields but when I pressed the save button either the page would refresh, with no validation messages, or I would be redirected as if the save had persisted. However, upon revisiting the user’s profile properties page it was clear that my changes had been discarded.
I was chasing a red herring for a while with the assumption that this issue was related the Kiosk licence of the user I was attempting to update. The issue is not related to licence type but appears to be a validation bug with page.
Although I had provided values for the user profile properties which are marked with a star, the issue persisted. These properties are not required when updated the user profile from the Admin console. The issue in fact lies with the time zone settings.
I found that I could not persist update if the ‘Always use regional settings defined by site administrators‘ radio box was checked.
By changing this to ‘Always use my personal settings‘ I was then able save and persist updates to the user’s profile.
Programmatically updating user profile properties (specifically Email) for inactive users may cause you grief.
Background
In SharePoint a user’s email address (along with some other key properties including name, login etc. ) are stored in three distinct locations. There are:
User Store (this could be AD, SQL for FBA etc.)
User Profile Database (specifically the ‘UserProfile_Full‘ table)
SharePoint Content Database(s) (specifically the ‘UserInfo‘ table)
For the sake of this article I am making the presumption that User Profiles have been configured.
The data stored across these locations needs to be keep synchronised for obvious reasons and this done in different ways depending on the source being updated. For FBA updating the User Store will almost certainly only occur via User Profiles if it is allowed at all (depending on what properties you decide to store there), so sync’ing TO the User Profile Database will not be considered. In the case of an update occurring in AD, the User Profile Synchronisation timer job will periodically check for updates and persist them to the User Profile Database. You find more on this here.
User Profile Synchronisation
A scheduled process will then sync’ the User Profile Database with the SharePoint content database.
Gotcha!
It is this part of the process which has inspired me to write this post; there is an important caveat to previous sentence. It should be as such: A scheduled process will then sync’ the User Profile Database with the SharePoint content database for all active users (in this case an active user is one that has saved his/her user profile). The impact of this is that if you programmatically update the email user profile property for an inactive user (e.g. from a@b.com to c@d.com) the property value will not be sync’ed and an action such as:
will send an email to a@b.com rather than c@d.com whereas:
would correctly send the email to c@d.com (Note: Mailer is a fictitious class in these examples).
For FBA scenarios this follows on what may be a more significant issue. If you have your users login using their email address then most likely the FBA login name includes this email address (e.g. for user with email a@b.com, their login name is i:0#.f|membership|a@b.com). If your custom developed components include code that relies on this relationship, such as web.EnsureUser(TOKEN + email), then this code may start failing for these inactive users. It’s unlikely that this will affect the inactive users themselves (as they aren’t using the system) but it may affect other users which are attempting to interact with these users that exist in the system before they have begun using the system.
Solution
I believe that the goal is to update the tp_Email column in the SharePoint content database UserInfo table. I have been unable to find an API which does this. Set-SPUser does not achieve this, and nor does SPFarm.MigrateUserAccount. I don’t dare break best-practice and update the table directly as in my case knowledge of this issue was enough. This is because the only time we attempt to update inactive user profiles is when obfuscating production email addresses upon restoring production database backups to our test environments. Having said that I would be very interested to hear of a good solution to this issue if anyone has found one.