People's profile in arrows

Using Yammer as log-in and commenting feature

Is it possible to integrate Yammer with your own ASP.NET MVC application, and if so, how should one go about doing it? Ole Henrik Hellenes finds out.

The idea

If I say “Yammer integration”, you say “What?” Well, while that might not hold true, that is the general impression I have gotten when trying to find information regarding this topic after being tasked with integrating Yammer with an ASP.NET MVC application. So, let me try to shed some light on the topic.

Let us start with some background. We had created an ASP.Net MVC web application hosted in Azure. The application would be used to hold a comprehensive design library for an organization (let’s call them Company A).

The task at our hand was to integrate this ASP.NET MVC application with Yammer, so that the users of this application would authenticate themselves using  their Yammer login, and be able to comment on the designs. The comments should actually be sent to a Yammer group where the users where already members.  Therefore, our service should provide the authentication service and comment section integration between the two. This would allow users in Company A’s home network to access the application using their Yammer credentials. This was the (relatively) easy part.

However, we also wanted to allow external consultants from say – Company B – to be able to authenticate using their own Yammer credentials, as long as they were invited to this Yammer network and group. The group would reside in an external Yammer network in the Company A’s Yammer. This part was harder. We’ll get to that.

There were several factors to consider here, for instance OAuth2.0, Yammer networks, Yammer groups, Yammer conversations and Yammer topics.

This post will look at the authentication part that has to do with OAuth2.0 and the Yammer app-model and -network structure. Comments, topics and conversations will have to wait for another post.
So let’s get started and see how it was done.

The Yammer App
To make users of your Yammer-network able to authenticate to your application, one first needs to have some kind of footing to authenticate against inside that Yammer network. This is required by the OAuth2.0 procedure one needs to go through, which we will take a closer look at in the next section. To accomplish this we create a Yammer App inside of the home-network of Company A. The Yammer App can be created by anyone, but preferably by an admin or a mock-account to ensure company ownership. The app does not have any functionality in itself, but rather acts as your applications representative inside of Yammer. This app contains information regarding the OAuth2.0 authentication flow. More specifically, it contains a client ID, a client secret, and a redirect URI.

Authenticate and use the app in your Yammer home network

The OAuth2.0-dance
When implementing a Yammer log-in service in your application, since ASP.NET MVC 4 does not contain a pre-configured OAuth client for Yammer, we will have to register one, less you are doing it from JavaScript – but that’s a different matter.

To achieve this, one must configure the AuthConfig class in the MVC application like below.

As seen above, there are already preconfigured classes for OAuth2.0 authentication for Microsoft-, Twitter-, Facebook, and Google-accounts. To create the Yammer client class, use the DotNetOpenOAuth-framework. It contains a class for OAuth2Client, which you will derive from and implement the methods you need. You need the ones below.

These are the ones mainly responsible for the authentication dance, which is required to authenticate with Yammer, or rather the App inside the Yammer-network of interest. The process infrastructure details itself is not in the scope of this post, but can be read about here https://msdn.microsoft.com/en-us/library/office/dn631818.aspx

Let us look at the implementation of the GetServiceLogin-method:

So, simple enough! We have the authorization endpoint (https://www.yammer.com/dialog/oauth), and we append the client ID and redirect URI. Next, we need to fetch the access token:

There is a bit more going on here. Firstly, we build the endpoint, which consists of the token endpoint (https://www.yammer.com/oauth2/access_token.json). Then we have to run the request and deserialize the result JSON. I did the deserialization using the Postman rest-client Chrome extension to launch an identical request, and then using that JSON response in a nifty tool over at json2csharp.com! Big thanks to Jonathan Keith who is the creator of that one. Saved me a few hours of manually writing up the JSON responses I were going to deserialize.

Lastly, we have the GetUserData-method:

Pretty straightforward as well, we – as usual – build the request, this time by using the endpoint for current user (https://www.yammer.com/api/v1/users/current.json). We deserialize the user as shown in the previous step, only this time with a model correlating with the JSON response for a user. Then we use that users data to create a response with the desired data. Now, this takes care of the basic OAuth authentication with Yammer. Good work, the users in Company A has now authenticated to the application by using their Yammer credentials, using the Yammer home network! They will now be able to connect and run GET, POST etc. towards their home network. Oh, one more thing; the new version of the Yammer API requires that the access token be sent in the header as a Bearer, rather than as a query parameter! However, you might be wondering; what about interacting with an external network? Why I thought you would never ask!

Authenticate and use the app in your Yammer external network

Now the Yammer-network I worked with were going to have an external network that the MVC application were going to work with. This was to be able to govern users that had access to the MVC application. However, this raised some questions when I started testing it, because all I got was a fantastic “403 Forbidden” response. Why? I had my access token, so why didn’t it work? Well, it seems that Yammer uses different access tokens for each network! Every access token is unique per network. As a consequence, somewhere in my authentication process I had to switch out my original access token (belonging to the Yammer home-network), for the correct one (belonging to the external network). After some digging, I found the VerifyAuthentication-method in the OAuth flow. Let’s jump right into the implementation of it:

What we’re doing here is to basically hands-on control, on our own terms, when the user is either granted or denied access. The case we are interested in is when the user is a member of the external network the MVC application is going to use! If the user is, in fact, a member; then he will gain access and we switch out the access token for the home network with the access token for the external network. If the user it not a part of that network, then AuthenticationResult.Failed is returned, and it gets handled appropriately by the MVC framework.

To check if a user is part of a network, we have to check if the current users’ networks contains the same network we are trying to connect to. Using the Yammer API endpoint https://www.yammer.com/api/v1/networks/current.json, we can compare those network ID’s to the one we are interested in. When that’s done, we need to make sure we have the correct access token. The access token varies from network to network; no one user has the same access token for several networks. To accomplish this we can use the https://www.yammer.com/api/v1/oauth/tokens.json API endpoint, compare our network ID to each token’s network ID.

Remember, this is a way around the issue that the App does not really allow using external networks out-of-the-box. We manually have to get the access token to the external network, which calls for a custom code solution. An example of implementation can be something like this:

 

Here we first use the “default” authentication token, which is the one affiliated with the logged in user’s home network. We have to use this token to get the user’s networks and tokens.

Now, if all this went well, the users in Company A has authenticated to the application using their own Yammer credentials, but this time, using the Yammer external network! You should now be able to connect and run GET, POST etc. towards your external network.

Letting external users authenticate and use the app in your Yammer external network

As initially described, we wanted to make users from another company say – Company B –able to authenticate to the application with their own Yammer credentials. As they originate from a different home network, they would have to be invited into Company A’s Yammer external network as external users. They should then be able to interact with the external network as described in the section above.

However, this does not work as we thought it would.

The problem lies within the deployment model of Yammer. More specifically, the scope of the directories of where Yammer apps can be deployed to. Let’s get some background on the “state” or “directory” a Yammer-app can be in:

  • Undeployed is not exactly a directory, but at least self-explanatory. This is the default state the app will be in, after it is created. It contains all the necessary information used in the OAuth authentication flow, and so can be used when developing for testing in one’s home network. However, if we try to access the external network from our MVC application when the app is in this state, it will not work due because the app does not have the necessary access token – because it is not deployed.
  • Local App Directory is the directory that scopes the home network, as well as all external networks under that home network. This allows our MVC application to interact with all networks the logged in user is member of. The deployment of a Yammer app requires some more information, for instance URLs to Terms of service and Privacy policy, along with images, banners, and icons for the app.
  • Global App Directory is, not surprisingly, the global directory where all global apps reside. These apps must be sent in for review by Yammer/Microsoft before being allowed in the Global App Directory. An app deployed to this directory is available for all Yammer users across all networks.

Now, let’s go back to the question as to why users from outside the Yammer App’s home network isn’t allowed in, even though they are a part of an external network derived from the home network.

It seems we have two possible options for deployment; Local App directory or Global App directory.

Say we deploy to the local app directory. We can then configure our MVC application to connect to an external network. The external user from Company B tries to authenticate with the correct client ID, but is denied access. Why? Because the OAuth flow is trying to find a Yammer app in the Company B’s home network, not the network that the app resides in; Company A’s home network. Therefore, it doesn’t find any app by that ID, and hence cannot authenticate.

The way to solve this is by globally deploying the app. Then the external user from Company B can install this in his network. When he then tries to log in, the app with the corresponding client ID is found in his home network, and he can successfully log in.

However, this also raises the question of how you are now going to govern your users, because this was the point of being able to log in with Yammer in the first place; being able to govern user access from Yammer, instead of in your local Active Directory.

For our need, it seems like a more controlled published app directory is missing in the Yammer app deployment scheme.

We contacted Microsoft to see if they could assist in our deployment approach. Is global deployment the only option? How do we go about to test such a deployment? And how do we control user access?  The indications we got was that  Yammer is  moving in the direction a close integration with of Azure apps and Azure AD, and making an integration process easier by utilizing these products. The fact that Yammer is about to move into Microsoft managed data center in May 2015 makes this even more likely.

My guess is that either the network and token structure will change in the near future, or the app deployment scheme will change into something more “Azure-ish”.

Either way, I can see companies being interested in having external consultants work and collaborate in their business applications, and governing them and following the progress from Yammer, so this really should be possible.

Yammer is fairly new in terms of APIs and understanding the structure it works with, so a lot may change in the time to come. However, one thing is certain; it is a fun product to work with and can be, if incorporated and integrated properly into a company, a great way to achieve seamless workflow and comunication support ,both internally and externally.

Finally {

To sum it all up; you have now seen one way to integrate Yammer with an MVC application using the OAuth-model and the APIs. However, to integrate your own application with Yammer you need to be aware of the limitations set by the directory framework in Yammer. Not all companies will be willing to take their app to the global app directory in the case of wanting to allow external users.But the Yammer APIs work great as a central communication hub for all kinds of applications – but currently limited to internal users.

I hope that this post shone a little light into the world of Yammer both in regards to authentication and integration, and wish you the best of luck on your endeavors!.

Now, go play with those APIs! Happy coding!

}

Resources & further reading

Published