/// <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);
                }
            }
        }
Пример #5
0
        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));
        }
Пример #6
0
        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));
        }
Пример #7
0
        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);
        }
Пример #12
0
        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));
        }