Working with authentication in Exchange Online
By George Durzi
Summary
You can use familiar authentication methods with Exchange Online to authenticate calls to Exchange Web Services (EWS). This article provides information about authenticating your EWS calls by using the Autodiscover service.
Applies to: Microsoft Exchange Online
Published: April 2011
Introduction
Your Microsoft Exchange Web Services (EWS) Managed API–based applications will work mostly as-is with Microsoft Exchange Online. However, because Exchange Online uses Windows Live ID forms-based authentication, connecting to Exchange Online involves making minor changes to your on-premise applications to ensure that they provide the credentials in the appropriate format. You can also use application impersonation to enable a service account to perform operations by using the identity and permissions of the user who is currently logged on. When you use Autodiscover to get the correct Exchange Web Services URL to use for a specified Exchange Online mailbox, you can work directly with the Autodiscover service to bypass steps that typically happen in an on-premises Exchange Server deployment, thereby speeding up the Autodiscover process.
Authenticating calls to EWS in Exchange Online
To make calls to EWS in Exchange Online by using a specific user's identity, you just have to specify the credentials that the ExchangeService class will use to communicate with EWS.
To set the credentials that the ExchangeService class will use to connect to EWS, create an instance of the WebCredentials class and provide the user name and password. Exchange Online uses Windows Live ID forms-based authentication to authenticate requests, so you need to set the WebCredentials user name to the user's SMTP address (for example, danj@contoso.com). Set the Credentials property of the ExchangeService object to the instance of the WebCredentials class, as shown in the following code example. Alternatively, you can use the System.Net.NetworkCredential class to provide the user name and password.
string _userSMTPAddress = "danj@contoso.com"; string _password = "myP@ssword"; var credentials = new WebCredentials() { UserName = _userSMTPAddress, Password = _password }; _exchangeService = new ExchangeService(ExchangeVersion.Exchange2010_SP1); _exchangeService.Credentials = credentials; _exchangeService.AutodiscoverUrl(_userSMTPAddress, RedirectionUrlValidationCallback);
Note: |
|---|
|
Exchange Online and this code example use an overload of the ExchangeService.AutodiscoverUrl method that specifies an AutodiscoverRedirectionUrlValidationCallback method. This defines a delegate that is used by the AutodiscoverService class to determine whether a redirection URL can be used. The Autodiscover service may redirect the call several times to different URLs until it finds the EWS URL for the specified mailbox. This delegate lets the Autodiscover service know that it is OK to follow the redirection. If you do not specify this delegate, an exception will be raised by the call to the AutodiscoverUrl method. For more information about the redirection callback, see "Validating Redirection URLs" later in this article. |
To create the instance of WebCredentials and specify the user name and password to be used at runtime, your application has to store or prompt the user for their credentials. An alternative approach is to use application impersonation in Exchange Online so that all the calls to EWS are made by a service account that has permission to impersonate the current user and perform operations by using the user's identity and permissions.
Using application impersonation to perform EWS calls
You can use application impersonation to enable an account that has been granted the ApplicationImpersonation role to perform operations in Exchange Online using other users' identities and permissions. Consider the example of a Microsoft SharePoint 2010 Web Part that displays appointments from the user's calendar. Instead of prompting the user for credentials, the Web Part uses the credentials of a service account to retrieve the user's appointments from his or her calendar.
Note: |
|---|
|
For more information about how to set up the ApplicationImpersonation role for an account, see the article "Working with Application Impersonation in Exchange Online." |
Instead of using the user's credentials to connect to Exchange Online, connect by using the service account's credentials and impersonate the user, as shown in the following code example.
string _serviceAccountSMTPAddress = "ServiceAccount@contosocorp.com"; string _serviceAccountPassword = "Secret!"; string _impersonatedUserSMTPAddress = "danj@contosocorp.com"; // Define the credentials to use. var credentials = new WebCredentials() { UserName = _serviceAccountSMTPAddress, Password = _serviceAccountPassword }; _exchangeService = new ExchangeService(ExchangeVersion.Exchange2010_SP1); _exchangeService.Credentials = credentials; // Call AutodiscoverUrl for the impersonated user. _exchangeService.AutodiscoverUrl(_impersonatedUserSMTPAddress, RedirectionUrlValidationCallback); // Set the impersonated account. _exchangeService.ImpersonatedUserId = new ImpersonatedUserId( ConnectingIdType.SmtpAddress, _impersonatedUserSMTPAddress);
Note: |
|---|
|
You can store the service account's credentials in a secure store and access them programmatically from the Web Part. |
Working with the Autodiscover service in Exchange Online
The EWS Managed API makes calls to EWS "under the covers." Therefore, it needs to know the URL for EWS for a particular user's mailbox. The API includes functionality that works with the Autodiscover service to find the URL for EWS for the specified user's mailbox.
You should use the Autodiscover service to find the most appropriate URL for the specified user's mailbox instead of using a hard-coded EWS URL. This guarantees that your application always uses the correct EWS URL for that particular mailbox. Autodiscover determines the best endpoint for a particular user (the endpoint that is closest to the user's Mailbox server). Note that hard-coding the URL might fail, as the Exchange Web Services URL might change if new Client Access servers are deployed. In this scenario, using Autodiscover means that no code changes are necessary.
In an on-premises Microsoft Exchange Server deployment, the computer that has the Client Access server role installed exposes an Autodiscover virtual directory in IIS to handle Autodiscover service requests from Microsoft Office Outlook or custom applications built by using the EWS Managed API. An Active Directory object called the Service Connection Point (SCP) is also created on the Client Access server; the SCP contains a list of all the URLs for the Autodiscover service in the Microsoft Exchange deployment. When an EWS Managed API application calls the ExchangeService.AutodiscoverUrl method to connect to EWS with a particular user's credentials, the API will execute code to query the SCP for the URL of the Autodiscover service so that it can make a request to it for the EWS URL to use for the specified user's mailbox.
When you are working with Exchange Online, the EWS Managed API does not have an SCP that it can use to get the URL for the Autodiscover service. If you set the instance of the ExchangeService class in your application to enable tracing before calling the AutodiscoverUrl method, you will see that the application is unable to find an SCP on the local domain. The following code example shows an Autodiscover call for a user with tracing enabled.
var credentials = new WebCredentials() { UserName = _userSMTPAddress, Password = _password }; _exchangeService = new ExchangeService(ExchangeVersion.Exchange2010_SP1); // Enable tracing output to the console. _exchangeService.TraceEnabled = true; _exchangeService.Credentials = credentials; _exchangeService.AutodiscoverUrl(_userSMTPAddress, RedirectionUrlValidationCallback);
The following figure shows a trace log for a call in which the EWS Managed API is unable to find an SCP for an Exchange Online mailbox.
The application will instead rely on convention to try to find the URL of the Autodiscover service. The service is typically available at one of the following two URLs:
-
https:// domain/autodiscover/autodiscover.xml
-
https://autodiscover. domain/autodiscover/autodiscover.xml
In these URLs, domain represents the prefix in the user's SMTP address; for example, you would type contoso.com for the user danj@contoso.com.
As part of this process, the request can be redirected to another URL. For example, the request to http://autodiscover.contoso.com/autodiscover/autodiscover.xml is redirected to https://autodiscover-s.outlook.com/autodiscover/autodiscover.xml — a generic Autodiscover service endpoint for Exchange Online. The request is redirected again as necessary until it terminates at the Autodiscover service URL for your tenancy in Exchange Online.
Finally, a request is made to the Autodiscover service URL in your Exchange Online tenancy to retrieve the EWS URL for the specified user's mailbox. In large tenancies — as in large on-premises Microsoft Exchange deployments — mailboxes can be geographically dispersed. In such an environment, it is important always to use the Autodiscover service to ensure that you are using the most efficient EWS URL for that mailbox.
An alternative to using the ExchangeService.Autodiscover method to get the EWS URL for a particular mailbox is to work with the AutodiscoverService class directly. This gives you more control over the Autodiscover process. For example, instead of waiting for a time-out to elapse while the Autodiscover process tries to find the SCP when the SCP doesn't exist, you can set the EnableScpLookup property of the AutodiscoverService class to false to bypass that step.
Call the GetUserSettings method on the instance of the AutodiscoverService class. This returns an instance of the GetUserSettingsResponse class, which you can use to extract the specific user settings that you need. In this case, we are interested in the ExternalEwsUrl setting, which represents the externally accessible Exchange Web Services URL for that mailbox. You can then manually set the Url property of the ExchangeService object to that value, as shown in the following code example.
// Create an instance of the AutodiscoverService. _autodiscoverService = new Microsoft.Exchange.WebServices.Autodiscover.AutodiscoverService(); // Enable tracing. _autodiscoverService.TraceEnabled = true; // Set the credentials. _autodiscoverService.Credentials = credentials; // Prevent the AutodiscoverService from looking in the local Active Directory // for the Exchange Web Services Services SCP. _autodiscoverService.EnableScpLookup = false; // Specify a redirection URL validation callback that returns true for valid URLs. _autodiscoverService.RedirectionUrlValidationCallback = RedirectionUrlValidationCallback; // Get the Exchange Web Services URL for the user's mailbox. GetUserSettingsResponse response = _autodiscoverService.GetUserSettings( _userName, UserSettingName.ExternalEwsUrl); // Extract the Exchange Web Services URL from the response. var externalEwsUrl = new Uri(response.Settings[UserSettingName.ExternalEwsUrl].ToString()); // Set the URL of the ExchangeService object. _exchangeService.Url = externalEwsUrl;
For more information about the Autodiscover service, see Understanding the Autodiscover Service on Microsoft TechNet.
Validating redirection URLs
The AutodiscoverService class requires a validation callback method that inspects redirection URLs that are returned by the Autodiscover service to help ensure that client applications are not redirected to a malicious URL.
Your application can use any appropriate strategy in the validation callback method to determine whether the application should follow the redirection. For example, you can provide a Safe Recipients list of valid redirection URLs for the application, or you can open a dialog box to enable the user to inspect and approve the redirection. The actual validation method that your application uses should meet the security requirements of your organization.
The following is a base redirection validation callback method. It inspects the redirection URL and only allows the AutodiscoverService object to follow the redirection if the URL is using HTTPS to help secure the authentication information in the request.
static bool RedirectionUrlValidationCallback(string redirectionUrl) { // The default for the validation callback is to reject the URL. bool result = false; Uri redirectionUri = new Uri(redirectionUrl); // Validate the contents of the redirection URL. In this simple validation // callback, the redirection URL is considered valid if it is using HTTPS // to encrypt the authentication credentials. if (redirectionUri.Scheme == "https") { result = true; } return result; }
Note: |
|---|
|
The redirection URL validation callback method in this example provides sufficient security for development and testing of Exchange Online applications. However, it may not provide sufficient security for your deployed application. You should always make sure that the certificate validation callback method that you use meets the security requirements of your organization. |
Conclusion
You only need to make minor modifications to the Autodiscover and authentication code in your EWS Managed API applications to migrate them to Exchange Online. You can work with the AutodiscoverService class directly to have greater control over the Autodiscover process — for example, to bypass the step in which the process looks for the Active Directory SCP. Because Exchange Online uses Live ID forms-based authentication to authenticate requests, you also need to use the user's SMTP address as his or her user name when you define the credentials that are used to connect to Exchange Online.
About the Author
George Durzi is a Principal Consultant at Clarity Consulting, where he works with clients to implement solutions based on various Microsoft tools and technologies. George started working with Office 365 as part of a project for the Microsoft Developer and Platform Evangelism team to build and deliver developer training content for early adopters of SharePoint Online, Lync Online, and Exchange Online. George is active in the Chicago software development community, helping to organize and speaking at events in the region. He is the co-author of Professional Unified Communications Development with Microsoft Lync Server 2010.
Note: