Create Yammer group as another user

We have a use-case in which we’re provisioning Office365 site collections, on behalf of a user request (via a SQL database – don’t worry about that bit, it’s kinda inconsequential).

We’re using some Azure C# website/webjob magic to put it all together.

BUT – the problem we were facing was this :

  • Cannot create a Yammer group ‘as another user’
  • Cannot add a user TO a group
  • Cannot add an admin to a group

We could create a group as an “farm-admin” user, but when creating a private group, the requesting user couldn’t access it – and needed the god-mode user to grant access !!

So much for a self-service site creation + Yammer – which was our goal.

Long post ahead, but the short story is that you need to ‘impersonate’ another user, when you attempt to create a new Yammer group  :

  • Call a Yammer REST endpoint to get all users
  • Loop through the users to find the requesting user (eg. Jodie)
  • Call a Yammer REST endpoint to get the user by email address – rather than get ALL users
  • Call a Yammer REST endpoint to get the security token for that user
  • Call a Yammer REST endpoint to create a group – passing the user’s access token

This does EXACTLY what we need it to do – and creates a group ‘as the user’ – and as a by-product, the user is made an admin – perfect !

A fair chunk of this approach was sourced from a blog post from Paul Matthews (cannonfodder) who helped me on the right track…

And also Steve Peschka (samlman)’s blogpost about Using Impersonation with the Yammer APIs.

Here’s the details of what *I* implemented – and the outcome achieved…….

Register a Yammer App – get client Id/Secret/Token

Before you begin, you need to get a client id / secret – much like a SharePoint app.

Refer to my previous post which covers this – and describes the group creation – which was our initial approach.

NB.  I have a helper method to GET/POST to Yammer :

private static string CallYammerJson(string url, string accessToken, string method)
{
    //make the request
    string json = null;
    HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest;
    request.Method = method;
    request.Headers.Add('Authorization', 'Bearer' + ' ' + accessToken);
    using (HttpWebResponse response = request.GetResponse() as HttpWebResponse)
    {
        Encoding encode = Encoding.GetEncoding('utf-8');
        StreamReader reader = new StreamReader(response.GetResponseStream(), encode);
        json = reader.ReadToEnd();
    }
    return json;
}

This method can be used when you craft a URL – and just pass a token, and a GET or POST as the method.

Get Yammer Users

This code then retrieves a set of the users within Yammer – as a JSON structure.   I’m using a YammerUser class – you can grab this from the PnP example.

string yammerUserAccountEmail = 'i:0#.f|membership|jodie@whatever.com.au';
int yamUserId = 0;

//get all users - and find the yammer user id
string url = 'https://www.yammer.com/api/v1/users.json';
var response = CallYammerJson(url, YAMMER_API_TOKEN, 'GET');
List[YammerUser] users = JsonUtility.Deserialize[List[YammerUser]](response);

foreach (YammerUser u in users)
{
    string yamEmail = u.contact.email_addresses[0].address.ToLower();

    if (yammerUserAccountEmail.ToLower().Contains(yamEmail) )
    {
        yamUserId = u.id;
        break;
    }
}

UPDATE > Change to [users/by_email.json]

We’ve since discovered that you can get the user details ‘by email address’ – rather than needing to get *ALL* users, which could be many thousands…    (a big concern)

Instead, we can call the REST endpoint with an email address parameter.  This gets us the ONE user, in the same JSON chunk.    This is much MUCH more elegant.

//yammerUserAccountEmail  >>  i:0#.f|membership|999999@domain.com.au
string[] emailArray = yammerUserAccountEmail.Split('|');

//0 > i:0#.f
//1 > membership
//2 > 999999@domain.com.au
string emailO365 = emailArray[2];

const string YAMMER_USERS_BY_EMAIL_URL = 'https://www.yammer.com/api/v1/users/by_email.json?email={0}';
string url = string.Format(YAMMER_USERS_BY_EMAIL_URL, emailO365);

//get the user - and find the yammer user id
var response = GetYammerJson(url, YAMMER_API_TOKEN);
List[YammerUser] users = JsonUtility.Deserialize[List[YammerUser]](response);

//found the users collection - will only have ONE user 
if (users.Count > 0)
{
    //get the token and return it
    YammerUser u = users[0];
    yamUserId = u.id;
}

Get user auth token

After you have an Yammer “ID” of the person (eg. Jodie) – you can then call another REST endpoint, to determine their access token.

You need to include the CLIENT ID in the url – from when you registered your App – as well as the ID of the user.   The token is the same ‘admin’ token (at this stage).

//get the user token
string userToken = string.Empty;
string tokenUrl = 'https://www.yammer.com/api/v1/oauth/tokens.json?consumer_key={0}&user_id={1}';
string url = string.Format(tokenUrl, YAMMER_CLIENT_ID, yammerUserId.ToString());

var response = GetYammerJson(url, YAMMER_API_TOKEN);
List[YammerUser] users = JsonUtility.Deserialize[List[YammerUser]](response);

if (users.Count != 0)
{
    YammerUser u = users[0];
    userToken = u.token;
}

Create group, impersonating another user

bool privateYammerGroup = true;    // or false - if you want a public group
string privateYammerGroup = 'Hunting and Fishing';

string url = 'https://www.yammer.com/api/v1/groups.json?name={0}&private={1}';
string urlCreateGroup = String.Format(url, yammerGroupName, privateYammerGroup.ToString().ToLower());

string jsonCreateGroup = CallYammerJson(urlCreateGroup, userToken, 'POST');

That’s about it !

It’s not actually TOO bad – it took us a lot longer to determine the approach, than to actual do it.

We’d initially tried to create a group, and then assign an admin user – after watching the HTTP traffic via Fiddler, and some emails with the product team, it was clear that we were barking up the wrong tree.

The above solution works nicely – we’re now rolling this into a production tenant with Azure/O365.

Users can simply enter the name of a ‘site’ and get a new site collection, and yammer group also – nice !

🙂

UPDATE : Missing Code :

Sorry – had skipped this function – I used it for GET and POST – just by passing the word as ‘method’.

Eg.  PostYammerJson(“http://url”, “lskdjshdfkjhs”, “GET”)

==================

private static string PostYammerJson(string url, string accessToken, string method)
{
//make the request
string json = null;
HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest;
request.Method = method;
request.Headers.Add(“Authorization”, “Bearer” + ” ” + accessToken);

try
{
using (HttpWebResponse response = request.GetResponse() as HttpWebResponse)
{
Encoding encode = Encoding.GetEncoding(“utf-8”);
StreamReader reader = new StreamReader(response.GetResponseStream(), encode);
json = reader.ReadToEnd();
}
}
catch(Exception ex)
{
json = ex.Message;
}

return json;
}

Advertisements