How to use EWS on hosted Exchange with Impersonation? - c#

I want to create a service which to crawl all inboxes of all users on a hosted exchange server (“myclient.onmicrosoft.com”) via EWS.
This already works well when I connect to on-premise exchange servers in the same domain. But when I try to connect this service to a hosted exchange, it throws 401 (wrong authorization) errors. Of course, this is a different domain as the hosted exchange server.
My service runs on an on-premise server and uses a “god-mode” user to impersonalise to all active directory users. My question is: How to connect the users of my on-premise system correctly to the hosted exchange in a different domain?
Note: It works when I use the credentials directly and the impersonation way does work on on-premise installations.
What I did so far (and I wonder of this is the right way to do it): On our on-premise server I created a domain “myclient.onmicrosoft.com” just like on the hosted server and an AD user with the same name and password as on the hosted exchange (called “mytest#myclient.onmicrosoft.com”).
On my crawler service I did:
I got all AD users in our on premise server
var allUsers = SearchAllActiveDirectoryUsers();
foreach (DataRow user in allUsers.Rows)
{
String domainName = (String)user["DomainName"];
String samAccountName = (String)user["SamAccountName"];
String principalName = (String)user["PrincipalName"];
String principalDomainName = (String)user["PrincipalDomainName"];
String mail = (String)user["Mail"];
}
Then for each AD user I connected the user with the exchange service like this:
ExchangeService ex = new ExchangeService(version);
ex.Url = new Uri(“https://outlook.office365.com/EWS/Exchange.asmx”);
ex.Credentials = new WebCredentials("mytest#myclient.onmicrosoft.com", “XXX”, " myclient.onmicrosoft.com");
// THIS DOES WORK CORRECTLY!
ex.ImpersonatedUserId = new ImpersonatedUserId(ConnectingIdType.PrincipalName, “mytest#myclient.onmicrosoft.com”);
//this does NOT work!
Any ideas what I am missing?

You need to use the credentials of your "god-mode" user, but set the ImpersonatedUserId to the AD user. Something like:
ex.Credentials = new WebCredentials("account_with_impersonation_rights#myclient.onmicrosoft.com", "password");
ex.ImpersonatedUserId = new ImpersonatedUserId(ConnectingIdType.PrincipalName, "mytest#myclient.onmicrosoft.com");
When you connect to Office 365 via EWS, you always need to supply credentials. You can't use UseDefaultCredentials = true.

Related

Using WindowsIdentity to connect to ManagementScope(WMI)

I have a .net core application that is hosted on IIS. This application utilizes System.Management to connect to other machines to gather information.
I am noticing that some of my calls are getting an access denied response. The application pool is running as a user that is an admin on the remote machines. However the ManagementScope does not appear to be using the Application pool's identity.
I was wondering if there is a way to use the WindowsIdentity while connecting to the remote machine?
I am looking for something like the following.
private ManagementScope GetManagementScope(string machineName)
{
WindowsIdentity identity = WindowsIdentity.GetCurrent();
ConnectionOptions options = new ConnectionOptions
{
Impersonation = ImpersonationLevel.Impersonate,
Username = identity.Name
// Something here to pass along the password?
};
ManagementPath path = new ManagementPath
{
Server = machineName,
NamespacePath = "\\root\\MicrosoftIISv2"
};
return new ManagementScope(path, options);
}
I have tried hard coding the User name and password and that works fine but I would really like to use the Application pools identity.
I think, and hope, there is no way to retrieve the password.
The only way is to pass it as external parameter and possibly stored in a secure application.
Maybe you can consider to store this secret in Azure Key Vault and retrieve that setting.

Connecting to TfsTeamProjectCollection fails due to Application Pool Identity

I have ASP.Net application which uses TFS API and works under Domain. The problem is that locally everything works fine. After deployment to IIS, which is configured to use ApplicationPoolIdentity, my app is giving me 500 Internal Server Error. When I set Identity to use my username and password everything works fine again. App uses Windows authentication, and is used by multiple users.
We're submitting data to TFS, and if Identity is configured to my username, the in TFS history it shows that I have modified that item. We need it to be the user that actually made the modification.
Before in some places, like "Assigned To" or "Deployed By" I used
var currentDisplayName = System.DirectoryServices.AccountManagement.UserPrincipal.Current.DisplayName;
After I discovered this issue, resolved it by using
var currentDisplayName = System.Web.HttpContext.Current.User.Identity.Name;
But the issue where when i use Identity - ApplicationPoolIdentity, the app is not working.
Method where i get Team Project Collection:
var tfsTeamProjectUrl = ConfigurationProvider.TfsTeamProjectUrl;
var teamProjectCollection = new TfsTeamProjectCollection(new Uri(tfsTeamProjectUrl));
teamProjectCollection.EnsureAuthenticated();
return teamProjectCollection;
Locally this works fine, but on IIS, it wants to use Identity from IIS App Pools, But i need it to use credentials from the actual user.
UPDATE
I tried to Impersonate the actual user by doing this:
var tfsTeamProjectUrl = ConfigurationProvider.TfsTeamProjectUrl;
var baseUserConnection = new TfsTeamProjectCollection(new Uri(tfsTeamProjectUrl));
var ims = baseUserConnection.GetService<IIdentityManagementService>();
var username = System.Web.HttpContext.Current.User.Identity.Name;
var identity = ims.ReadIdentity(IdentitySearchFactor.AccountName, username,
MembershipQuery.None, ReadIdentityOptions.None);
var teamProjectCollection = new TfsTeamProjectCollection(new Uri(tfsTeamProjectUrl), identity.Descriptor);
teamProjectCollection.EnsureAuthenticated();
return teamProjectCollection;
But now i'm gettin
An exception of type 'Microsoft.TeamFoundation.TeamFoundationServerInvalidResponseException' occurred in Microsoft.TeamFoundation.Client.dll but was not handled in user code
Additional information: Please contact your administrator. There was an error contacting the server.
Technical information (for administrator):
HTTP code 500: Internal Server Error
It seems like IIS is deciding to try to access TFS with the app pool identity instead of the credentials that you are explicitly supplying. You are authenticating to the server but then not using the server object, so the app was reverting to whatever identity it was running under.
Try to use the authentication with below code:
string tfsServerUrl = "http://servername:8080/tfs";
System.Net.NetworkCredential tfsCredential = new System.Net.NetworkCredential("ServiceAccountName", "password", "DOMAIN");
TfsConfigurationServer tfs = new TfsConfigurationServer(new Uri(tfsServerUrl), tfsCredential);
tfs.Authenticate();

Accessing a generic process inbox using EWS

I am trying to use EWS to access a process mailbox. For some automated queries we created a genric process mailbox. I want to parse emails by watching the Process inbox.
My code was working earlier with the old exchange server. But after migration to office 365 it fails.
I am able to access my mailbox and parse on the office 365 using my credentials.
How do I access this process mailbox? Earlier I create an ExchangeService and connect to the process email address with UseDefaultCredentials = true.
I set the AutoDiscoverURl and used DefaultCredentials. But When I tried to read emails I get "The SMTP address has no mailbox associated with it."
EDIT:
I tried to use my own credentials instead of the Default Credentials.
string smtpaddress = "somesharedsmtp#domain.com";
es.Url = new Uri("https://outlook.office365.com/EWS/Exchange.asmx");
es.Credentials = new WebCredentials("myemail", "mypassword");
es.AutodiscoverUrl(smtpaddress, RedirectionCallback);
FolderId SharedMailbox = new FolderId(WellKnownFolderName.Inbox, "somesharedsmtp#domain.com");
Folder sharedInbox = Folder.Bind(es, SharedMailbox);
At this point I can check sharedInbox containing the details of the Inbox. I can see the unread email count and others.
But when I access
ItemView itemView = new ItemView(100);
FindItemsResults<Item> findResults1 = es.FindItems(pqInbox.Id, itemView);
I get exception "SMTP address has no mailbox associated with it"
disclaimer: I haven't worked with EWS in a while.
You can't use the default credentials for Office 365. You'll need to provide either the basic credential or use an OAuth token.
You should confirm that the account was migrated to Office 365. Login to OWA and look at the URL to make sure you are using Office 365 and not an on-premise server.
This was already answered by Exchange Web Services: UseDefaultCredentials property

Web service unable to connect Sharepoint site "unable to connect remote server"

I have written the code as below:
try
{
ClientContext context = new ClientContext("https://test.com/");
System.Net.ServicePointManager.ServerCertificateValidationCallback =
((sender, certificate, chain, sslPolicyErrors) => true);
string strUserName = #"abc";
string strPassword = "pwd";
var credentials = new NetworkCredential(strUserName, strPassword);
Web web = context.Web;
context.Load(web, w => w.Title);
context.Credentials = credentials;
context.ExecuteQuery();
// Now, the web's properties are available and we could display
// web properties, such as title.
System.Console.WriteLine("Web Title");
System.Console.WriteLine(web.Title);
}
catch (Exception ex)
{
}
It's working fine in the console application, but same code is not working when I am calling from a web service.
Given our discussion; the problem is likely that the account that your IIS app pool is running under is not authorized to access the Sharepoint site. You need the app pool account to have access in AD in order for your code to work. You'll need to do one of the following;
Get the App pool account granted AD rights to Sharepoint. This is less likely as IIS 7 and above use "odd accounts" by default for app pools.
More likely is you'll need to change the account your app pool is running under to one that has the appropriate AD rights. In most companies I've worked for there is a "Service Account" or "Automated Account" used for this purpose.

Cyber Ark .NETPasswordSDK not able to connect

I am not able to find any good documentation on .NET SDK for CyberArk.
I am trying to integrate CyberArk password management system to get password for an Outlook account using the below code
PSDKPasswordRequest passReq = new PSDKPasswordRequest();
PSDKPassword password = null;
// What is the purpose of CredFile??
passReq.CredFilePath = "F:\\CredFiles\\AppUser.cred";
passReq.Safe = "SAFE_NAME";
passReq.Folder = "root";
passReq.Object = userName;
passReq.Reason = "Get some stuff done.";
// Sending the request to get the password
password = CyberArk.AIM.NetPasswordSDK.PasswordSDK.GetPassword(passReq);
However I am not able to connect and getting the following error
"PDKTC006E Failed to connect to provider (Reason=[connect command failed])"\
As I understand it, the API (NetPasswordSDK) is actually a caching service that sits between you and the CyberArk appliance. So you have to configure the service correctly during install as it handles the connection to the CyberArk appliance.
Instructions:
Write down a CyberArk Administrator account's username/password
Write down the CyberArk IP address. This is NOT the web access IP address (PVWA). It's the IP address of the appliance.
On your dev machine, run the CyberArk SDK installer and enter in the IP address and Admin username/password from steps #1 and #2
Assuming the installer completes successfully, it is going to create a user called "Prov_MACHINENAME." (MACHINENAME will equal your NetBIOS hostname) on the CyberArk appliance.
On your dev machine, open C:\Program Files (x86)\CyberArk\ApplicationPasswordProvider\Vault\AppProviderUser.cred and write down the name generated during the install.
Log in to the CyberArk appliance as an administrator
Create a Safe named MySafe
Add the Administrator account from step #1 as a member to MySafe
Add the Prov_MACHINENAME account from step #5 as a member to MySafe
Create an Application named MyApp
Add the Application as a member MySafe
Create an Account named MyAccount and assign it to MySafe
You can now use the following code to connect:
PSDKPasswordRequest objPasswordRequest;
PSDKPassword objPassword;
objPasswordRequest = new PSDKPasswordRequest();
objPasswordRequest.AppID = "MyApp";
objPasswordRequest.Safe = "MySafe";
objPasswordRequest.Object = "MyAccount";
objPassword = PasswordSDK.GetPassword(objPasswordRequest);
password = objPassword.Content;
username = objPassword.UserName;

Categories

Resources