Introduction
Typical use cases
- Modify a site after it has been created
- Push notification to users when a noticeboard item has been created
- React on changes to project roles and metadata
Authentication
Wizdom Webhooks are not authenticated so be aware a webhook URL defined in the Wizdom Configuration Center can access the SharePoint resource on behalf of the user/app. The configured URL will receive the following header to be able to impersonate current user/app.
- “WizdomSPToken”, “[SharePoint access token]”
If webhooks need to call back to the Wizdom API it needs to be authenticated. To call back to SharePoint using CSOM, the WizdomSPToken can be used. The Wizdom API uses OAuth 2.0 to handle authentication and authorization. Before using the Wizdom API an Azure Active Directory application with correct permission scope needs to be created. This app will provide the authentication service for accessing the Wizdom API.
Visual Studio 2017 / .NET web application sample
This section will provide a sample on how to use the Wizdom Webhooks. In about ten minutes you’ll have a simple .NET web application that receives a HTTP POST payload from Wizdom. The application is then able to read information from the newly created site. The application is also able to makes requests to the Wizdom API and retrieve comment details from the Wizdom Noticeboard service.
The sample uses WizdomSPToken to execute queries against SharePoint. It uses resource owner password credentials grant type, where the user provides their service credentials (username and password) to access the Wizdom services. This type uses the credentials to obtain an access token from the service. This grant type should only be enabled on the authorization server if other flows are not viable. Also, it should only be used if the application is trusted by the user (e.g. it is owned by the service, or the user’s desktop OS).
Prerequisites:
- Visual Studio 2017
- Office 365 site collection with Wizdom installed
Step 1: Create a .NET web application
1. Create ASP.NET (Web Application) and choose WebAPI, no authentication
This is needed for the azurewebsite to reach your local dev environment.
ex. ./ngrok.exe http 51191 -host-header=”localhost:51191″
Step 2: Setup the Azure Active Directory Application
1. Navigate to the Azure Portal (https://aad.portal.azure.com) logged in as your tenant admin.
2. Navigate to Azure Active Directory > App Registrations
3. Add app (new application registration).
4. Give it a name and choose Application Type: Web app / API
5. Enter the url of your previously created ngrok url
ex. https://98697d65.ngrok.io
6. Assign required permissions (delegated and application)
Azure AD: Read Directory data
SharePoint: Read Items in all site collections + Read user profiles
Yammer: Read and Write
7. Create Key and save/copy it.
8. Press the “Grant Permissions” button.
Step 3: Setup the sample
Add app settings to the web.config. Replace the values in brackets.
<add key="tenant" value="[your tenant].onmicrosoft.com" />
<add key="client_id" value="[azure directory app application id]" />
<add key="client_secret" value="[azure directory app key]" />
<add key="resource" value="https://[your tenant].sharepoint.com/"/>
<add key="username" value="[tenant account username]"/>
<add key="password" value="[tenant account password]"/>
public class SiteItem
{
public string ParentWebUrl { get; set; }
public string SiteUrl { get; set; }
public string CreatorLoginName { get; set; }
public string TemplateName { get; set; }
}
public class CommentItem
{
public int CommentID { get; set; }
public int AuthorID { get; set; }
public string TargetID { get; set; }
public string TargetType { get; set; }
public DateTime DatePosted { get; set; }
}
5. Install nuget package: Install-Package Microsoft.SharePointOnline.CSOM -Version 16.1.6906.1200
6. Replace the class with this code and resolve the missing references.
[RoutePrefix("api/webhook")]
public class WebhookController : ApiController
{
[HttpPost]
[Route("webcreated")]
public void WebCreated(
[FromUri]string SPHostUrl, [FromBody]SiteItem siteItem)
{
var token = Request.Headers.GetValues("WizdomSPToken").FirstOrDefault();
var appUrl = Request.Headers.GetValues("x-wizdom-appurl").FirstOrDefault();
ClientContext clientContext = new ClientContext(siteItem.SiteUrl);
clientContext.AuthenticationMode = ClientAuthenticationMode.Anonymous;
clientContext.FormDigestHandlingEnabled = false;
clientContext.ExecutingWebRequest +=
delegate (object oSender, WebRequestEventArgs webRequestEventArgs)
{
webRequestEventArgs.WebRequestExecutor.RequestHeaders["Authorization"] =
"Bearer " + token;
};
Uri url = new Uri(siteItem.SiteUrl);
Web web = clientContext.Site.OpenWeb(url.PathAndQuery);
clientContext.Load(web, x => x.Title);
clientContext.ExecuteQuery();
var title = web.Title;
}
[HttpPost]
[Route("commentupdated")]
public async void CommentUpdated(
[FromUri]string SPHostUrl, [FromBody]CommentItem commentItem)
{
var wizdomToken = Request.Headers.GetValues("WizdomSPToken").FirstOrDefault();
var appUrl = Request.Headers.GetValues("x-wizdom-appurl").FirstOrDefault();
Dictionary<string, string> post = null;
post = new Dictionary<string, string>
{
{"client_id", ConfigurationManager.AppSettings["client_id"]}
,{"client_secret", ConfigurationManager.AppSettings["client_secret"]}
,{"grant_type", "password"}
,{"resource", ConfigurationManager.AppSettings["resource"]}
,{"username", ConfigurationManager.AppSettings["username"]}
,{"password", ConfigurationManager.AppSettings["password"]}
};
var client = new HttpClient();
var postContent = new FormUrlEncodedContent(post);
var response = await client.PostAsync($"https://login.microsoftonline.com/{ConfigurationManager.AppSettings["tenant"]}/oauth2/token", postContent);
var content = await response.Content.ReadAsStringAsync();
var json = JObject.Parse(content);
var accessToken = json["access_token"].ToString();
var client2 = new HttpClient();
client2.DefaultRequestHeaders.Add("Authorization", $"Bearer {accessToken}");
client2.DefaultRequestHeaders.Add("x-wizdom-rest", "app01");
var response2 = await client2.GetAsync($"{appUrl}api/wizdom/noticeboard/1/items/{commentItem.TargetID}/comments/{commentItem.CommentID}");
var content2 = await response2.Content.ReadAsStringAsync();
var json2 = JObject.Parse(content2);
var comment = json2["primaryResult"]["content"].ToString();
}
}
CommentUpdated : https://266830b2.ngrok.io/api/webhook/commentupdated
WizdomSiteCreated : https://266830b2.ngrok.io/api/webhook/webcreated
8. Start your application and set a breakpoint in each Method.
9. Create a noticeboard news item. Create a comment and edit that comment. Verify you breakpoint is hit.
10. Create a new Wizdom site. Verify that your breakpoint is hit.
This concludes this sample application.
Comments
0 comments
Please sign in to leave a comment.