/// <summary> /// Helper method for creating DirectoryService and adding header /// for subsequent requests for the service. It also adds helper properties for collections of subtypes of DirectoryObject /// such as users, contacts etc. /// </summary> public DirectoryDataService(string tenantName, AADJWTToken token) : this(new Uri(StringConstants.DirectoryServiceURL + tenantName)) { this.authenticationToken = token; // Register the event handler that adds the headers for HTTP requests including the Authorization header. this.BuildingRequest += new EventHandler <BuildingRequestEventArgs>(OnBuildingRequest); }
/// <summary> /// <see cref="MyCompany.Travel.Web.Security.IADGraphApi"/> /// http://code.msdn.microsoft.com/Windows-Azure-AD-Graph-API-a8c72e18 /// </summary> /// <param name="userPrincipalName"><see cref="MyCompany.Travel.Web.Security.IADGraphApi"/></param> /// <param name="groupName"><see cref="MyCompany.Travel.Web.Security.IADGraphApi"/></param> /// <returns><see cref="MyCompany.Travel.Web.Security.IADGraphApi"/></returns> public bool IsInGroup(string userPrincipalName, string groupName) { string clientId = WebConfigurationManager.AppSettings["ida:ClientId"]; string key = WebConfigurationManager.AppSettings["ida:Key"]; string tenant = WebConfigurationManager.AppSettings["ida:Tenant"]; // get a token using the helper AADJWTToken token = DirectoryDataServiceAuthorizationHelper.GetAuthorizationToken(tenant, clientId, key); // initialize a graphService instance using the token acquired from previous step var graphService = new DirectoryDataService(tenant, token); var users = graphService.users; var response = users.Execute() as QueryOperationResponse <User>; List <User> userList = response.Where(u => u.userPrincipalName == userPrincipalName).ToList(); if (userList.Any()) { var user = userList.First(); List <string> _groupMemberships; _groupMemberships = new List <string>(); string queryString = string.Format("https://graph.windows.net/{0}/{1}/{2}/{3}", tenant, "users", user.objectId.ToString(), "memberOf"); var query = graphService.Execute <Group>(new Uri(queryString)); var groups = query.Where(a => a.objectType == "Group" && a.displayName == groupName); var groupList = groups as IList <Group>; if (groupList != null) { var directoryObjects = groups as IList <Group> ?? groups.ToList(); return(directoryObjects.Any()); } } return(false); }
/// <summary> /// Helper method for creating DirectoryService and adding header /// for subsequent requests for the service. It also adds helper properties for collections of subtypes of DirectoryObject /// such as users, contacts etc. /// </summary> public DirectoryDataService(string tenantName, AADJWTToken token) : this(new Uri(StringConstants.DirectoryServiceURL + tenantName)) { this.authenticationToken = token; // Register the event handler that adds the headers for HTTP requests including the Authorization header. this.BuildingRequest += new EventHandler<BuildingRequestEventArgs>(OnBuildingRequest); }
/// <summary> /// Function for getting a token from ACS using Application Service principal Id and Password. /// </summary> public static AADJWTToken GetAuthorizationToken(string tenantName, string appPrincipalId, string password) { HttpWebRequest request = (HttpWebRequest)WebRequest.Create(String.Format(StringConstants.AzureADSTSURL, tenantName)); System.Text.ASCIIEncoding encoding = new System.Text.ASCIIEncoding(); string postData = "grant_type=client_credentials"; postData += "&resource=" + HttpUtility.UrlEncode(StringConstants.GraphPrincipalId); postData += "&client_id=" + HttpUtility.UrlEncode(appPrincipalId); postData += "&client_secret=" + HttpUtility.UrlEncode(password); byte[] data = encoding.GetBytes(postData); request.Method = "POST"; request.ContentType = "application/x-www-form-urlencoded"; request.ContentLength = data.Length; using (Stream stream = request.GetRequestStream()) { stream.Write(data, 0, data.Length); } using (var response = request.GetResponse()) { using (var stream = response.GetResponseStream()) { DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(AADJWTToken)); AADJWTToken token = (AADJWTToken)(ser.ReadObject(stream)); return(token); } } }
public static DirectoryDataService CreateDirectoryDataService(HttpSessionStateBase session) { // AADJWTToken token = null; AuthenticationResult token = null; if (session != null && session["token"] != null) { token = session["token"] as AuthenticationResult; } AuthenticationResult authenticationResult = null; var futureTime = DateTimeOffset.UtcNow.AddMinutes(2); // Fetch a token if it has not been fetched earlier or if the token is about to expire in 2 mins if (token == null || (futureTime.UtcDateTime > token.ExpiresOn.UtcDateTime)) { string authString = System.String.Format(StringConstants.AzureADSTSURL, ConfigurationManager.AppSettings["TenantDomainName"]); AuthenticationContext authenticationContext = new AuthenticationContext(authString); ClientCredential clientCred = new ClientCredential(ConfigurationManager.AppSettings["AppPrincipalId"], ConfigurationManager.AppSettings["Password"]); try { authenticationResult = authenticationContext.AcquireToken(StringConstants.GraphPrincipalId, clientCred); } catch (ActiveDirectoryAuthenticationException ex) { if (ex.InnerException != null) { // You should implement retry and back-off logic per the guidance given here:http://msdn.microsoft.com/en-us/library/dn168916.aspx // InnerException Message will contain the HTTP error status codes mentioned in the link above // Console.WriteLine("Error detail: {0}", ex.InnerException.Message); } } token = authenticationResult; if (session != null) { session["token"] = authenticationResult; } } if (token == null) { return(null); } // Configure a AADJWTToken using the ADAL token var aadToken = new AADJWTToken(); aadToken.AdalToken = token; aadToken.AccessToken = token.AccessToken; aadToken.TokenType = token.AccessTokenType; return(new DirectoryDataService(ConfigurationManager.AppSettings["TenantDomainName"], aadToken)); }
public static DirectoryDataService CreateDirectoryDataService() { AADJWTToken token = null; token = DirectoryDataServiceAuthorizationHelper.GetAuthorizationToken(ConfigurationManager.AppSettings["TenantDomainName"], ConfigurationManager.AppSettings["AppPrincipalId"], ConfigurationManager.AppSettings["Password"]); return(new DirectoryDataService(ConfigurationManager.AppSettings["TenantDomainName"], token)); }
private DirectoryDataService GetAuthenticatedDirectoryDataService(ClaimsPrincipal incomingPrincipal) { //get the tenantName string tenantName = incomingPrincipal.FindFirst("http://schemas.microsoft.com/identity/claims/tenantid").Value; // retrieve the clientId and password values from the Web.config file string clientId = ConfigurationManager.AppSettings["ida:ClientID"]; string password = ConfigurationManager.AppSettings["ida:Password"]; // get a token using the helper AADJWTToken token = DirectoryDataServiceAuthorizationHelper.GetAuthorizationToken(tenantName, clientId, password); // initialize a graphService instance using the token acquired from previous step return(new DirectoryDataService(tenantName, token)); }
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)); }
public static DirectoryDataService CreateDirectoryDataService(HttpSessionStateBase session) { AADJWTToken token = null; if (session != null && session["token"] != null) { token = session["token"] as AADJWTToken; } //Fetch a token if it has not been fetched earlier or if it is 2 minutes from expiration. if (token == null || token.WillExpireIn(2)) { token = DirectoryDataServiceAuthorizationHelper.GetAuthorizationToken(ConfigurationManager.AppSettings["TenantDomainName"], ConfigurationManager.AppSettings["AppPrincipalId"], ConfigurationManager.AppSettings["Password"]); if (session != null) { session["token"] = token; } } return(new DirectoryDataService(ConfigurationManager.AppSettings["TenantDomainName"], token)); }
public List <String> GetCompleteGroupMembership(string tenantId, string objectId, AADJWTToken authenticationToken) { string authHeader = String.Format(CultureInfo.InvariantCulture, "{0}{1}{2}", authenticationToken.TokenType, " ", authenticationToken.AccessToken); String requestUrl = string.Format("https://graph.windows.net/{0}/directoryObjects/{1}/getMemberGroups?api-version=2013-04-05", tenantId, objectId); HttpWebRequest webRequest = WebRequest.Create(requestUrl) as HttpWebRequest; webRequest.Method = "POST"; webRequest.Headers["Authorization"] = authHeader; //webRequest.Headers["x-ms-dirapi-data-contract-version"] = "0.8"; webRequest.ContentType = "application/json"; string postData = "{\"securityEnabledOnly\":false}"; ASCIIEncoding encoding = new ASCIIEncoding(); byte[] byteEncoding = encoding.GetBytes(postData); webRequest.ContentLength = byteEncoding.Length; Stream writeStream = webRequest.GetRequestStream(); writeStream.Write(byteEncoding, 0, byteEncoding.Length); writeStream.Close(); var httpResponse = (HttpWebResponse)webRequest.GetResponse(); StreamReader streamReader = new StreamReader(httpResponse.GetResponseStream()); string jsonText = streamReader.ReadToEnd(); JavaScriptSerializer ser = new JavaScriptSerializer(); List <String> groupMemberships = new List <string>(); foreach (string s in ser.Deserialize <dynamic>(jsonText)["value"]) { groupMemberships.Add(s); } return(groupMemberships); }
public override ClaimsPrincipal Authenticate(string resourceName, ClaimsPrincipal incomingPrincipal) { if (incomingPrincipal != null && incomingPrincipal.Identity.IsAuthenticated == true) { //get the tenantId string tenantId = incomingPrincipal.FindFirst("http://schemas.microsoft.com/identity/claims/tenantid").Value; // Use the DirectoryDataServiceAuthorizationHelper graph helper API // to get a token to access the Windows Azure AD Graph string clientId = ConfigurationManager.AppSettings["ClientId"]; string password = ConfigurationManager.AppSettings["Password"]; AADJWTToken token = DirectoryDataServiceAuthorizationHelper.GetAuthorizationToken(tenantId, clientId, password); // initialize a graphService instance. Use the JWT token acquired in the previous step. DirectoryDataService graphService = new DirectoryDataService(tenantId, token); // get the user's ObjectId String currentUserObjectId = incomingPrincipal.FindFirst("http://schemas.microsoft.com/identity/claims/objectidentifier").Value; // Get the User object by querying Windows Azure AD Graph User currentUser = new WebRetryHelper <User>(() => graphService.directoryObjects.OfType <User>().Where(it => (it.objectId == currentUserObjectId)).SingleOrDefault()).Value; /* * TaskTracker defines four roles that are specific to this app: * "Admin", "Observer", "Writer", "Approver". These app roles are * different from the roles that are built into Windows Azure AD, * e.g. "Company Administrator", "User Account Administrator". * * This code uses the memberOf property of the User object to get * the user's built-in roles. If the user has the "Company Administrator" * built-in role, the app assigns the user to the "Admin" app role. */ // get the user's built-in roles new WebRetryHelper <object>(() => graphService.LoadProperty(currentUser, "memberOf")); List <Role> currentRoles = currentUser.memberOf.OfType <Role>().ToList(); //if the user is a Company Administrator (Global Administrator), // assign them the "Admin" role in the app. foreach (Role role in currentRoles) { if (role.displayName.Equals("Company Administrator")) { ((ClaimsIdentity)incomingPrincipal.Identity).AddClaim(new Claim(ClaimTypes.Role, "Admin", ClaimValueTypes.String, "TaskTrackerSampleApplication")); } } /* * To determine the user's group membership, TaskTracker uses * the getCompleteGroupMembership function, which calls the getMemberGroups * function, which returns the transitive group membership of the user. */ // Now, query transitive group membership of the user List <string> completeGroupMembership = new WebRetryHelper <List <String> >(() => graphService.GetCompleteGroupMembership(tenantId, currentUserObjectId, token)).Value; //Store the user's groups as claims of type "Group" foreach (string groupId in completeGroupMembership) { Debug.WriteLine("adding " + groupId); ((ClaimsIdentity)incomingPrincipal.Identity).AddClaim(new Claim("Group", groupId, ClaimValueTypes.String, "WindowsAzureADGraph")); } //Get role assignments foreach (string role in getRoles(currentUserObjectId, completeGroupMembership)) { //Store the user's application roles as claims of type Role ((ClaimsIdentity)incomingPrincipal.Identity).AddClaim(new Claim(ClaimTypes.Role, role, ClaimValueTypes.String, "TaskTrackerSampleApplication")); } } return(incomingPrincipal); }
public ActionResult Users() { //get the user's objectID Boolean onACL = false; String userObjectId = ((ClaimsIdentity)User.Identity).FindFirst("http://schemas.microsoft.com/identity/claims/objectidentifier").Value; List <ACLElem> ACLElems = XmlHelper.GetACLElemsFromXml(); foreach (ACLElem elem in ACLElems) { //is user's objectId in the ACL? if (elem.ObjectId.Equals(userObjectId)) { onACL = true; } else { foreach (Claim groupClaim in ((ClaimsIdentity)User.Identity).FindAll("Group")) { //is a group the user belongs to in the ACL? if (elem.ObjectId.Equals(groupClaim.Value)) { onACL = true; break; } } } // exit as soon as you find the user or a group in the ACL if (onACL) { break; } } //if user is not in ACL - do not grant permission if (!onACL) { return(RedirectToAction("Error", "Home", new { errorMessage = "Access Denied. To view this resource, have an admin add you or your group to the ACL." })); } //get the tenantName string tenantName = ClaimsPrincipal.Current.FindFirst("http://schemas.microsoft.com/identity/claims/tenantid").Value; // get the clientId and password values from the Web.config file string clientId = ConfigurationManager.AppSettings["ClientId"]; string password = ConfigurationManager.AppSettings["Password"]; // use the Graph help to get a token AADJWTToken token = DirectoryDataServiceAuthorizationHelper.GetAuthorizationToken(tenantName, clientId, password); // use the token to initialize a graphService instance DirectoryDataService graphService = new DirectoryDataService(tenantName, token); // get Users // var users = graphService.users; QueryOperationResponse <User> response; response = users.Execute() as QueryOperationResponse <User>; List <User> userList = response.ToList(); ViewBag.userList = userList; // Use the token for subsequent Graph calls. // Is the existing token expire or about to expire in 2 mins? // if true, get a new token and refresh the graph service // int tokenMins = 2; if (token.IsExpired || token.WillExpireIn(tokenMins)) { AADJWTToken newToken = DirectoryDataServiceAuthorizationHelper.GetAuthorizationToken(tenantName, clientId, password); token = newToken; graphService = new DirectoryDataService(tenantName, token); } // get tenant information // var tenant = graphService.tenantDetails; QueryOperationResponse <TenantDetail> responseTenantQuery; responseTenantQuery = tenant.Execute() as QueryOperationResponse <TenantDetail>; List <TenantDetail> tenantInfo = responseTenantQuery.ToList(); ViewBag.OtherMessage = "User List from tenant: " + tenantInfo[0].displayName; return(View(userList)); }