Azure Daemon Application using EWS with OAuth


We've got a fair few samples for implementing a daemon application (one that requires no user interaction) using OAuth against Azure endpoints, but I couldn't find a specific example for EWS.  This guide describes how to set up an application (register it in Azure) and then obtain the correct permissions to be able to run continuously with no further user input.

Click here to download the sample application that this post refers to.

Part 1: Register the application in Azure

  1. Sign into the Azure portal, and open the Azure Active Directory tab.
  2. Select App registrations.
  3. Click New application registration.
  4. Create a new Web app/API:
  5. Once created, click on the application (from the App registrations node):
  6. Click Settings, then Required permissions, and then click Add:
  7. Select Office 365 Exchange Online (Microsoft.Exchange), and then tick Access mailboxes as the signed-in user via Exchange Web Services:
  8. Click Save, then Done to apply the new permission.
  9. The next step depends upon whether you are using certificate authentication or secret key.
    1. Set up certificate authentication:
      1. Generate your certificate (not that this article does not cover that process), with both private and public key.  Suitable file formats are .cer, .pem or .crt.
      2. Upload the public key:
    2. Create a secret key:
      1. Enter a key description, then a duration, and click Save:
      2. Copy the generated secret key (it will be displayed once only) for use in your application.
  10. The application registration is now complete.

Part 2: Obtain user consent and acquire the first token

This part refers to the sample application, which can be used as a code sample. This part of the set-up procedure requires user interaction, and so is part of the "install" process.

Before the daemon application can access a mailbox, it needs permission from the mailbox's owner (or an administrator).  Once this permission is obtained, the application must use this permission to obtain a token that will then allow it to access the mailbox.

To obtain permission, an application prompts the user to log-in to their mailbox and consent to application access (assuming a tenant administrator hasn't already consented on the user's behalf).  This is done by sending the user to a log-in URL (in Azure).  Once the user has logged in (and consented, if necessary) then Azure will redirect the user back to the application (using the Reply URL specified when the application was registered in Azure) with a code that can be used to obtain the first token.  This code is only valid for ten minutes, so the application must use it immediately.

  1. Click the User Consent... button, which will open the User Consent window:
  2. Check that the Reply URL is correct (it should match that shown in Azure).
  3. If the sample application was run with admin rights, then you can click Listen to open an HTTP listener that will automatically listen and receive the consent code once the user has granted it.  Note that the listener isn't required, as you can just copy the URL from the browser window after user consent.
  4. Click Log-in to open a browser window and complete the consent process.  The sample application launches the log-in using the system configured default browser.  If you want to use a specific browser, you can simply copy the URL from the textbox and browse to it directly.
  5. If you didn't start a listener, then after the sign-in process you'll end up at a blank page (or a 404), but with a localhost URL (or whichever reply URL you chose) showing in the address bar (containing a long code).  Simply copy this URL (in its entirety) and paste it into the user consent window to complete the token acquisition (the sample application extracts the code from the URL).

Once the token has been acquired, this will be shown in the application log:

Part 3: Running as a daemon

Now that the application has its token, it can use this token to authenticate with the mailbox and perform actions against it.  The sample application will simply return the number of items found in the Inbox when you click Get inbox count.

The access token that is returned as part of the token will only be valid for a given time (which will be one hour after it was issued).  When the access token expires, the application uses the refresh token (which was issued alongside the access token) to obtain a new access token.  This process can be repeated indefinitely until the refresh token expires (which it will do if not used within 90 days of issue - note that every time the access token is refreshed, the refresh token will be as well).

The sample application, once user consent is completed, can be restarted and will still be able to access the mailbox (because it has stored the access token).

The sample application demonstrates several important techniques:

  • Implementing a token cache.  By default, for a Web API, the ADAL libraries do not cache tokens. However, a token cache can be implemented using the TokenCache class. When this cache is set up, ADAL will automatically check for existing tokens first and use them if found. This is crucial to prevent a service application from needing to prompt the user. The token cache must persist across application/service restarts (so is saved to disk, in this example).
  • Obtaining an access token silently. This is another crucial feature for a daemon application. Once the first authorisation has been granted by the user (which requires user interaction), future authorisation requests should not prompt at all.
  • Renewing the access token when it expires. Access tokens are only valid for an hour, so must be renewed once they time out. This must also occur silently. Refresh tokens are valid for 90 days, and need to be renewed within 90 days or they are invalidated. A new refresh token is issued with each access token refresh (so an application can keep renewing a token indefinitely, unless the refresh token is revoked).

Controlling Application Scope/Permissions

You can lock down an application further by requiring user assignment, and hiding the application from users (both options available from the Enterprise Applications node):

When these options are set, no user will be able to use the application unless it is first assigned to them.  Users are assigned using the Users and groups tab.

Once assignment is set to be required, then if you try to log-in with an account that has not been assigned, you'll receive the error "AADSTS50105: The signed in user is not assigned to a role for the application...":

Note that if assignment is required, you may also need admin permission to grant the application permission to access the mailbox.  In this example, once I'd assigned the application to a new user account and then logged in to that account, I received this prompt instead of the standard "This application needs permission" prompt:

The easiest way to grant admin approval is to use the Have an admin account? link and sign in with the admin account.  This will complete the assignment of permissions, and after that the application will receive the token it needs to start working.

Token Viewer

The sample application has a token viewer built-in that allows you to see what is held in the token cache, and also what is in a token.  The token viewer can decode to JSON as needed:

References

OAuth is more secure than earlier authentication schemes because anytime an application has to authenticate (to obtain a token), it needs to provide more than one piece of information.  It needs to be able to prove that it is what it claims (using the secret key or certificate), and also provide a token from the user (or code to obtain a token) that proves the permission to access that user's information.  The only tokens that can be used to access the information by themselves (i.e. not requiring secondary proof) are short-lived (the access tokens last one hour), so even if they were sniffed over the wire (difficult as the transport is encrypted), then they could only be used for a short period (unlike if a username/password were compromised).

For further information on OAuth, these references may be useful.

Authorize access to REST APIs with OAuth 2.0 (provides an overview of the OAuth2 flow)

Microsoft Graph Permissions Reference (describes the available Graph permissions and what they mean)

Office 365 API Reference

 

Comments (0)

Skip to main content