I'm a pretty new programmer. One of the things I've been tasked with at work is getting our custom tools to create draft emails and drop them into the draft email folder of the user running the tool. We presently use Exchange Server 2010 (but are in the process of migrating over to Exchange Online).
This link talks about a UseDefaultCredentials but I can't seem to work out how to implement it. I created an ExchangeService object called service and managed to interact with our Exchange server using this for credentials:
service.Credentials = new WebCredentials("my login name", "my password");
I'd like to be able to eliminate that from the code and have it use the credentials of the logged-in user who is using the tool. Is that possible?
ExchangeService service = new ExchangeService(ExchangeVersion.Exchange2010);
service.Credentials = new WebCredentials(CredentialCache.DefaultNetworkCredentials);
if you use the defaultcredentials you can eliminate your posted code. Just set "UseDefaultCredentials" to True and don't set the Credentials manually. In this case the credentials of the User who is running your tool will be taken. I use that on my own and it works finde for me.
Greets, J
Related
Background
I am trying to connect to Office 365, to read the calendars of users that have granted permission. I have tried two options:
Exchange Web Services (EWS)
Microsoft Graph
EWS works but has the downside that I use login/password combinations to connect. Even though I store them encrypted, I'd rather not store them at all.
Microsoft Graph works as well, but has a gigantic downside; any updates I make to an item using the API is sent to all attendees. This behavior can be turned off when using the EWS API, but not (yet?) for Graph.
I'd like to take the OAuth implementation I have for Microsoft Graph, and use the EWS service to connect. No updates to attendees unless users want them, and no stored credentials.
The problem
For my application to work properly, I need to;
Get the timezone of the calendar, which I do by reading the person's work hours;
Read and write calendar items, which is the purpose of the application.
I have already established a connection with OAuth to Office365, using OAuth.
I cannot figure out the smallest subset of permissions I need. I have not found any documentation regarding this. Any subset of rights I tried, I get a 401 when I ask for WorkHours.
Minimal Code sample
This will work when I enable 38 non-admin permissions that the app registration for Exchange Online supports, but will fail for every subset I have tried.
[TestMethod]
public void ConnectUsingEws()
{
var accessToken = "eyJz93a...k4laUWw";
var credentials = new OAuthCredentials(accessToken);
var service = new ExchangeService(TimeZoneInfo.Utc);
service.Url = new Uri("https://outlook.office365.com/EWS/exchange.asmx");
service.TraceEnabled = true;
service.TraceFlags = TraceFlags.All;
service.Credentials = credentials;
// This next line is where the service will always throw a 401.
var workHours = UserConfiguration.Bind(service, "WorkHours",
WellKnownFolderName.Calendar, UserConfigurationProperties.All);
// Do some XML magic on workHours to get the timezone.
}
TLDR
I'm sure it's one permission that needs to be enabled, and I'm also fairly certain it's not one that's very obvious.
EWS doesn't support the same level of Permission scopes that REST does with Oauth (which is a big downside of using EWS for a security perspective).
OAuth authentication for EWS is only available in Exchange as part of
Office 365. EWS applications require the "Full access to user's
mailbox" permission.
ref https://msdn.microsoft.com/en-us/library/office/dn903761(v=exchg.150).aspx
I am trying to use EWS on an Office 365 account however I get a return of (403 Forbidden)
ExchangeService service = new ExchangeService(ExchangeVersion.Exchange2013);
service.Credentials = new WebCredentials("mv003237", "correctpw","domain");
service.AutodiscoverUrl("mv003237#domain.co.uk");
To login and view the Webservices file on outlook.com/EWS/Exchange.asmx I need to authenticate with mv003237#live.domain.co.uk
I have tried several combinations of this and still get the same error message.
Has anyone had a similar experience of connecting to an office 365 account before?
My WINDOWS login for this account does have a domain of RDG-HOME but I haven't seen a domain for login into OWA.
Many thanks in advance
If you've already removed the domain name (as Matt suggested in his comment) the one thing that remains is to automatically follow redirects in the autodiscover process.
Change your last line to
service.AutodiscoverUrl("mv003237#domain.co.uk", redirect => true);
to follow the redirection response that Exchange Online sends.
So the complete sequence then becomes:
ExchangeService service = new ExchangeService(ExchangeVersion.Exchange2013);
service.Credentials = new WebCredentials("mv003237", "correctpw");
service.AutodiscoverUrl("mv003237#domain.co.uk", redirect => true);
Cannot comment due to low reputation score and hence responding as an answer.
Are you able to login into OWA with "mv003237#domain.co.uk"? If yes, have you tried by hardcoding Url instead of using Autodiscover to understand if issue is with Autodiscover or EWS. Try following instead of autodiscover call:
service.Url = new Uri(#"https://outlook.office365.com/ews/exchange.asmx");
If above works fine, subscribe to RedirectionUrlValidationCallback with AutodiscoverService and see which redirected URL is throwing 403. Or enable verbose logging with Trace* properties present on service object.
I have been tasked with writing a .NET application that has to have access to a users exchange calendar. This application will only be accessed from the local network and I need to have to automatically use the current domain users credentials to access exchange.
I have the following code but I get an error saying "The account does not have permission to impersonate the requested user."
ExchangeService service = new ExchangeService();
service.UseDefaultCredentials = true;
string exchange = "exchangeWSURL";
service.Url = new Uri(exchange);
service.ImpersonatedUserId = new ImpersonatedUserId(ConnectingIdType.PrincipalName, userid);
service.PreAuthenticate = true;
CalendarView cal = new CalendarView(startDate, startDate.AddDays(7));
FindItemsResults<Appointment> findResults = service.FindAppointments(WellKnownFolderName.Calendar, cal);
It looks like I am doing something wrong. I was hoping to now have to turn on impersonation for all users on the domain.
Any help would be wonderful.
This article provides what you seem to be looking for. Take note of the paragraph on "Impersonation". This seems to suit your needs perfectly.
ASP.NET and Exchange tips and samples
Copied from MSDN:
You must configure the Exchange server to allow impersonation before
your application can use impersonation. For more information, see
Configuring Exchange Impersonation (Exchange Web Services).
https://msdn.microsoft.com/en-us/library/dd633680(v=exchg.80).aspx
https://msdn.microsoft.com/en-us/library/bb204095(exchg.140).aspx
We're trying to authenticate to our hosted TFS service account in c# using TeamFoundationServer .net control, here is my code :
NetworkCredential tfsCredential = new NetworkCredential(username, password);
TeamFoundationServer tfsServer = new TeamFoundationServer(tfsAddress, tfsCredential);
tfsServer.Authenticate();
Note that this is not an on-premises TFS server, it is the hosted TFS service at tfspreview.com and we try to sign-in with windows live account and with alternate authentication credentials but every time we try to authenticate, internet explorer open in a new windows and ask for credentials.
If we use the IE prompt to connect it works but we want to store the credentials and connect to the server without asking for the credentials every time,
You can either configure basic authentication under your profile or you can use a service credential. It all depends on what sort of permission you need. The basic auth operates under a user account which tends to be bad practice while the service account had elevated permissions.
Configure basic authentication for TF Service
For basic user authentication you should connect to TF Service and open your profile as indicated. There is a "Credentials" tab on your profile which will let you configure those credentials. This is good for per/user access through the API but is not good if you want to run things through a server or service.
Retrieve TFS Service Credentials
I created an application called the TFS Service Credential Viewer that allows you to retrieve the service credentials for your TF Service instance. This is the same thing that the Build & Test servers do when you configure them locally to work against the cloud.
I hope this helps...
You can try with this code based on impersonation of server
var serverUrl = "";
ICredentials credentials = new NetworkCredential(username, password, domain);
ICredentialsProvider TFSProxyCredentials = new NetworkCredentialsProvider(credentials);
TfsTeamProjectCollection currentCollection = new TfsTeamProjectCollection(new Uri(serverUrl), credentials);
// Get the TFS Identity Management Service
IIdentityManagementService identityManagementService = currentCollection.GetService<IIdentityManagementService>();
// Look up the user that we want to impersonate
TeamFoundationIdentity identity = identityManagementService.ReadIdentity(IdentitySearchFactor.AccountName, username, MembershipQuery.None, ReadIdentityOptions.None);
// Open collection impersonated
TfsTeamProjectCollection tfs = new TfsTeamProjectCollection(new Uri(serverUrl), credentials, TFSProxyCredentials, identity.Descriptor);
//For example we can access to service WorkItemStore
var workItemStore = tfs.GetService<WorkItemStore>();
Tfspreview.com now supports basic authentication which would eliminate IE being displayed at all. See here for details on how to set this up for your tfspreview.com and then use the username and password you configured.
I am running into a very strange issue and I am convinced it is just something stupid that I am overlooking. Using the EWS managed API, I try to connect to a mailbox to read the contacts. Originally, I used the default credentials, in which case the auto discovery worked. The problem is that later on we want to run this on a server and impersonate a user, so I changed it by manually specifying the credentials. This then broke, even when using my own credentials.
As an example, this worked:
service = new ExchangeService(ExchangeVersion.Exchange2007_SP1);
service.AutodiscoverUrl("user#example.com", redirect => true);
This did not:
service = new ExchangeService(ExchangeVersion.Exchange2007_SP1);
service.UseDefaultCredentials = false;
service.Credentials = new NetworkCredential("user", "pass", "EXAMPLE_DOMAIN");
service.AutodiscoverUrl("user#example.com", redirect => true);
The given network credentials should be exactly the same as the default credentials, but when enabling the tracing, I get the response "401 Unauthorized" in the second case, so it is not acting as if it is the same.
What am I missing?
Ok, it seems that you need to use WebCredential("user", "pass", "EXAMPLE_DOMAIN"). I am not exactly sure why WebCredentials work but NetworkCredentials does not.