Skip to content

Instantly share code, notes, and snippets.

@zplume
Last active May 31, 2018 12:31
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save zplume/e4244fb9415799a111e5062a23e22d1e to your computer and use it in GitHub Desktop.
Save zplume/e4244fb9415799a111e5062a23e22d1e to your computer and use it in GitHub Desktop.
// make calls against SPO using a user access token passed from ADAL.js
// credit to Kirk Evans: https://blogs.msdn.microsoft.com/kaevans/2014/04/15/calling-o365-apis-from-your-web-api-on-behalf-of-a-user/
using System;
using System.Web.Http;
using System.Configuration;
using System.Threading.Tasks;
using Microsoft.IdentityModel.Clients.ActiveDirectory;
using System.Globalization;
using System.Net.Http;
using System.Web;
using System.Security.Claims;
using System.Linq;
namespace zplume
{
// routing + convention = prefix "api/action"
[Authorize]
public class ActionController : ApiController
{
// using default routing, methods are accessible via [prefix]/[methodname], e.g. "/api/action/documents"
[HttpGet]
public async Task<string> Documents(string siteURL)
{
string accessToken = await GetAccessToken();
return GetListTitleWithCSOM(siteURL, accessToken);
//return await GetListTitleWithREST(siteURL, accessToken);
}
private static string GetListTitleWithCSOM(string siteURL, string accessToken)
{
var authMgr = new OfficeDevPnP.Core.AuthenticationManager();
using (var ctx = authMgr.GetAzureADAccessTokenAuthenticatedContext(siteURL, accessToken))
{
var list = ctx.Web.Lists.GetByTitle("Documents");
ctx.Load(list, l => l.Title);
ctx.ExecuteQuery();
return list.Title;
}
}
private static async Task<string> GetListTitleWithREST(string siteURL, string accessToken)
{
string requestUrl = siteURL + "/_api/Web/Lists/GetByTitle('Documents')/Items?$select=Title";
HttpClient client = new HttpClient();
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, requestUrl);
request.Headers.Add("Accept", "application/atom+xml");
request.Headers.Add("Authorization", $"Bearer {accessToken}");
HttpResponseMessage response = await client.SendAsync(request);
if (response.IsSuccessStatusCode)
{
string responseString = await response.Content.ReadAsStringAsync();
return responseString;
}
// TODO: log this value as an error, throw
return await response.Content.ReadAsStringAsync();
}
private async Task<string> GetAccessToken()
{
string clientId = ConfigurationManager.AppSettings["ida:ClientId"];
string appKey = ConfigurationManager.AppSettings["ida:AppKey"];
string aadInstance = ConfigurationManager.AppSettings["ida:AADInstance"];
string tenant = ConfigurationManager.AppSettings["ida:TenantId"];
string domain = ConfigurationManager.AppSettings["ida:Domain"];
string resource = ConfigurationManager.AppSettings["ida:Resource"];
AuthenticationResult result = null;
ClientCredential clientCred = new ClientCredential(clientId, appKey);
string authHeader = HttpContext.Current.Request.Headers["Authorization"];
string userAccessToken = authHeader.Substring(authHeader.LastIndexOf(' ')).Trim();
UserAssertion userAssertion = new UserAssertion(userAccessToken);
string authority = aadInstance + domain;
AuthenticationContext authContext = new AuthenticationContext(authority);
//result = await authContext.AcquireTokenAsync(resource, clientCred); // auth without user assertion (fails, app only not allowed)
result = await authContext.AcquireTokenAsync(resource, clientCred, userAssertion); // clientCred and userAssertion params have swapped places since Kirk's blog
return result.AccessToken;
}
}
}
// Access an Azure hosted WebAPI using ADAL.js to authenticate and get user token
// requires jQuery for ajax (could be swapped out with fetch + polyfill)
// credit to the following samples/blogs:
// https://github.com/Azure-Samples/active-directory-javascript-singlepageapp-dotnet-webapi/blob/master/TodoSPA/App/Scripts/app.js
// https://blogs.msdn.microsoft.com/kaevans/2014/04/15/calling-o365-apis-from-your-web-api-on-behalf-of-a-user/
// https://www.itunity.com/article/calling-office-365-apis-jquery-adaljs-2758
(function ($) {
var config = {
instance: 'https://login.microsoftonline.com/',
tenant: '[tenant_name].onmicrosoft.com',
clientId: '[app_guid]',
postLogoutRedirectUri: window.location.origin,
cacheLocation: 'localStorage'
};
function callWebApi(token) {
// url with trailing forward-slash removed + endpoint
var baseUrl = window.location.href.replace(/\/$/, "");
var url = baseUrl + "/api/action/documents?siteUrl=" + encodeURIComponent("https://[tenant_name].sharepoint.com/[site_url]");
$.ajax({
type: 'GET',
url: url,
headers: {
'Accept': 'application/json',
'Authorization': 'Bearer ' + token,
}
}).done(function (data) {
// TODO: do something with the data
console.log(data);
}).fail(function () {
// TODO: let the user know the request failed
console.log("Error", arguments[2]);
});
}
function getToken(callback) {
var authContext = new AuthenticationContext(config);
// save tokens if this is a return from AAD
authContext.handleWindowCallback();
var user = authContext.getCachedUser();
// attempt callback
if (user) {
// acquire user token
authContext.acquireToken(authContext.config.clientId, function (error, token) {
if (error || !token) {
console.log(error);
return;
}
// execute callback function with user token as a parameter
callback(token);
});
}
else if (authContext.getLoginError()) {
// error logging in
console.log("Error logging in", authContext.getLoginError());
}
else {
// not logged in
console.log("Logging in");
authContext.login();
}
}
// get user token, call webapi endpoint
getToken(callWebApi);
})(jQuery);
"oauth2AllowImplicitFlow": true
<appSettings>
<add key="webpages:Version" value="3.0.0.0" />
<add key="webpages:Enabled" value="false" />
<add key="ClientValidationEnabled" value="true" />
<add key="UnobtrusiveJavaScriptEnabled" value="true" />
<add key="ida:ClientId" value="[app_guid]" />
<add key="ida:AADInstance" value="https://login.microsoftonline.com/" />
<add key="ida:Domain" value="[tenant_name].onmicrosoft.com" />
<add key="ida:TenantId" value="[tenant_id]" />
<add key="ida:PostLogoutRedirectUri" value="https://localhost:44300/" />
<add key="ida:AppKey" value="[app_key]" />
<add key="ida:Resource" value="https://[tenant_name].sharepoint.com/" />
</appSettings>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment