Last active
May 31, 2018 12:31
-
-
Save zplume/e4244fb9415799a111e5062a23e22d1e to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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; | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
"oauth2AllowImplicitFlow": true |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<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