Skip to content

Commit

Permalink
refactoring chunks to smaller methods
Browse files Browse the repository at this point in the history
  • Loading branch information
Nicholas Switzer committed Sep 23, 2019
1 parent d0d3dcf commit d7fc0d4
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 27 deletions.
1 change: 0 additions & 1 deletion Handler.Auth/ITokenHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ public interface ITokenHandler<in T>
/// Current token cache is in memory and will need to be updated to an external store before production worthy
/// </summary>
/// <param name="allTokenNeededData">All needed parameters to obtain an access token</param>
/// <returns></returns>
Task StoreAccessToken(T allTokenNeededData);

/// <summary>
Expand Down
59 changes: 41 additions & 18 deletions ModernAuth_API/Controllers/ValuesController.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
using System;
using System.Collections.Generic;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Security.Claims;
using System.Threading.Tasks;
using Handler.Auth;
using Microsoft.AspNetCore.Authentication;
Expand All @@ -12,7 +9,6 @@
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Graph;
using Newtonsoft.Json;

namespace ModernAuth_API.Controllers
{
Expand All @@ -38,24 +34,52 @@ public ValuesController(IConfiguration configuration,
[HttpGet("{username}")]
public async Task<ActionResult> Get(string username)
{
var dictionary = _configuration.GetSection("AzureAd").GetChildren()
var tokenData = await GetTokenData();

var graphAccessToken = await _tokenHandler.GetAccessTokenOnBehalfOf(tokenData);

var user = await GetUserInfo(tokenData["userName"], graphAccessToken);

return new ObjectResult(user);
}


/// <summary>
/// Returns data needed to acquire a new token on behalf of the signed in user that targets the Microsoft Graph API
/// </summary>
/// <returns></returns>
private async Task<IDictionary<string, string>> GetTokenData()
{
var tokenData = _configuration.GetSection("AzureAd").GetChildren()
.Select(item => new KeyValuePair<string, string>(item.Key, item.Value))
.ToDictionary(x => x.Key, x => x.Value);

//adding accessToken used to call this api to dictionary of token data
dictionary["accessToken"] = await _httpContextAccessor.HttpContext.GetTokenAsync("access_token");
tokenData["accessToken"] = await _httpContextAccessor.HttpContext.GetTokenAsync("access_token");

tokenData["resource"] = _configuration["resource"];
tokenData["userName"] = _httpContextAccessor.HttpContext.User.Identity.Name;
tokenData["RedirectURI"] = _configuration["RedirectURI"];

dictionary["resource"] = _configuration["resource"];
dictionary["userName"] = _httpContextAccessor.HttpContext.User.Identity.Name;
dictionary["RedirectURI"] = _configuration["RedirectURI"];

var accessToken = await _tokenHandler.GetAccessTokenOnBehalfOf(dictionary);
return tokenData;
}

//this initiates a graph service client using ADAL. Using MSAL is documented here https://docs.microsoft.com/en-us/graph/sdks/create-client?context=graph%2Fapi%2F1.0&view=graph-rest-1.0&tabs=CS
var graphServiceClient = new GraphServiceClient(new DelegateAuthenticationProvider((requestMessage) => {
/// <summary>
/// Returns user's basic profile from the Microsoft Graph API
/// </summary>
/// <param name="userName">user to query basic profile for</param>
/// <param name="graphAccessToken">access token for calling the Microsoft Graph APi</param>
/// <returns></returns>
private static async Task<User> GetUserInfo(string userName, string graphAccessToken)
{
//this initiates a graph service client using a DelegateAuthenticationProvider https://github.com/microsoftgraph/msgraph-sdk-dotnet/blob/dev/docs/overview.md#delegateauthenticationprovider
//Using an MSAL based auth provider is documented here https://docs.microsoft.com/en-us/graph/sdks/create-client?context=graph%2Fapi%2F1.0&view=graph-rest-1.0&tabs=CS
var graphServiceClient = new GraphServiceClient(new DelegateAuthenticationProvider((requestMessage) =>
{
requestMessage
.Headers
.Authorization = new AuthenticationHeaderValue("bearer", accessToken);
.Authorization = new AuthenticationHeaderValue("bearer", graphAccessToken);

return Task.FromResult(0);
}));
Expand All @@ -64,16 +88,15 @@ public async Task<ActionResult> Get(string username)
//query options allow passing in OData queries to the api request
List<QueryOption> options = new List<QueryOption>
{
new QueryOption("$filter", $"userPrincipalName eq '{username}'")
new QueryOption("$filter", $"userPrincipalName eq '{ userName }'")
};

//user will be of type array which is why FirstOrDefault is used to obtain the actual user model
//user will be an array which is why FirstOrDefault is used to obtain the actual user model
var user = await graphServiceClient.Users
.Request(options)
.GetAsync();

return new ObjectResult(user.FirstOrDefault());
return user.FirstOrDefault();
}

}
}
25 changes: 17 additions & 8 deletions ModernAuth_UI/Extensions/AzureAdAuthenticationBuilderExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -73,18 +73,12 @@ public void Configure(OpenIdConnectOptions options)
//Used to handle when an authCode has been received. Not added by configuration wizard
private async Task OnAuthorizationCodeReceived(AuthorizationCodeReceivedContext context)
{

var dictionary = _configuration.GetSection("AzureAd").GetChildren()
.Select(item => new KeyValuePair<string, string>(item.Key, item.Value))
.ToDictionary(x => x.Key, x => x.Value);

dictionary["Code"] = context.TokenEndpointRequest.Code;
dictionary["userName"] = context.Principal.Identity.Name;
var tokenData = GetTokenData(context);

//used to exchange the authCode for an access and refresh token and then store those tokens in the token cache.
//Current token cache is in memory and will need to be updated to an external store before production worthy
//Not added by configuration wizard
await _tokenHandler.StoreAccessToken(dictionary);
await _tokenHandler.StoreAccessToken(tokenData);

//used to obtain the idToken passed in on the signin request
var idToken = context.ProtocolMessage.IdToken;
Expand All @@ -102,6 +96,21 @@ private Task OnAuthenticationFailed(AuthenticationFailedContext context)
return Task.FromResult(0);
}

/// <summary>
/// Returns data needed to acquire a new token on behalf of the signed in user that targets the Microsoft Graph API
/// </summary>
/// <returns></returns>
private IDictionary<string, string> GetTokenData(AuthorizationCodeReceivedContext context)
{
var dictionary = _configuration.GetSection("AzureAd").GetChildren()
.Select(item => new KeyValuePair<string, string>(item.Key, item.Value))
.ToDictionary(x => x.Key, x => x.Value);

dictionary["Code"] = context.TokenEndpointRequest.Code;
dictionary["userName"] = context.Principal.Identity.Name;
return dictionary;
}

}
}
}

0 comments on commit d7fc0d4

Please sign in to comment.