This repository has been archived by the owner on Jun 19, 2022. It is now read-only.
/
GraphRoleClaimsAuthenticationManager.cs
82 lines (74 loc) · 3.98 KB
/
GraphRoleClaimsAuthenticationManager.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security;
using System.Security.Claims;
using AccidentalFish.AspNet.Identity.Azure.GraphAPIHelper;
using Microsoft.Azure;
using Microsoft.WindowsAzure.ActiveDirectory;
using Microsoft.WindowsAzure.ActiveDirectory.GraphHelper;
namespace AccidentalFish.AspNet.Identity.Azure
{
/// <summary>
/// This specialization of the ClaimsAuthenticationManager class uses the Azure AD Graph API to
/// find the AD groups that a user is a member of and transforms them into role claims.
///
/// These claims can then be used with the Authorize(Roles="A Role") authorization attribute in
/// an MVC application.
/// </summary>
public class GraphRoleClaimsAuthenticationManager : ClaimsAuthenticationManager
{
private const string TenantIdClaim = "http://schemas.microsoft.com/identity/claims/tenantid";
private const string ObjectIdentifierClaim = "http://schemas.microsoft.com/identity/claims/objectidentifier";
private readonly string _clientId;
private readonly string _password;
private readonly string _issuer;
public GraphRoleClaimsAuthenticationManager()
{
_clientId = CloudConfigurationManager.GetSetting("ida:ClientID");
_password = CloudConfigurationManager.GetSetting("ida:Password");
_issuer = CloudConfigurationManager.GetSetting("ida:RoleClaimIssuer");
if (String.IsNullOrWhiteSpace(_issuer))
{
_issuer = "DefaultRoleIssuer";
}
}
public override ClaimsPrincipal Authenticate(string resourceName, ClaimsPrincipal incomingPrincipal)
{
if (incomingPrincipal != null && incomingPrincipal.Identity.IsAuthenticated)
{
// Get the claims required to make further Graph API enquiries about the user
Claim tenantClaim = incomingPrincipal.FindFirst(TenantIdClaim);
if (tenantClaim == null)
{
throw new NotSupportedException("Tenant claim not available, role authentication is not supported");
}
Claim objectIdentifierClaim = incomingPrincipal.FindFirst(ObjectIdentifierClaim);
if (objectIdentifierClaim == null)
{
throw new NotSupportedException("Object identifier claim not available, role authentication is not supported");
}
string tenantId = tenantClaim.Value;
string currentUserObjectId = objectIdentifierClaim.Value;
// Connect to the graph service
AADJWTToken token = DirectoryDataServiceAuthorizationHelper.GetAuthorizationToken(tenantId, _clientId, _password);
DirectoryDataService graphService = new DirectoryDataService(tenantId, token);
// Find the user in the graph
// ReSharper disable once ReplaceWithSingleCallToSingleOrDefault - SingleOrDefault not supported on directory service directly
User currentUser = graphService.directoryObjects.OfType<User>().Where(it => (it.objectId == currentUserObjectId)).SingleOrDefault();
if (currentUser == null)
{
throw new SecurityException("User cannot be found in graph");
}
// Find the groups the user is a member of and add them as role claims
graphService.LoadProperty(currentUser, "memberOf");
List<Group> currentRoles = currentUser.memberOf.OfType<Group>().ToList();
foreach (Group role in currentRoles)
{
((ClaimsIdentity) incomingPrincipal.Identity).AddClaim(new Claim(ClaimTypes.Role, role.displayName, ClaimValueTypes.String, _issuer));
}
}
return base.Authenticate(resourceName, incomingPrincipal);
}
}
}