{"id":4236,"date":"2013-09-14T12:52:00","date_gmt":"2013-09-14T10:52:00","guid":{"rendered":"http:\/\/www.limilabs.com\/blog\/?p=4236"},"modified":"2022-03-29T15:33:10","modified_gmt":"2022-03-29T13:33:10","slug":"oauth2-outlook-com-imap-installed-applications","status":"publish","type":"post","link":"https:\/\/www.limilabs.com\/blog\/oauth2-outlook-com-imap-installed-applications","title":{"rendered":"OAuth 2.0 with Outlook.com over IMAP for installed applications"},"content":{"rendered":"\n<div class=\"well\">You can also read how to use:\n<p>&nbsp;<\/p>\n<ul>\n<li>OAuth 2.0 with Outlook.com over IMAP for installed applications<\/li>\n<li><a href=\"\/blog\/oauth2-outlook-com-imap-web-applications\">OAuth 2.0 with Outlook.com over IMAP for web applications<\/a><\/li>\n<\/ul>\n<ul>\n<li><a href=\"https:\/\/www.limilabs.com\/blog\/oauth2-office365-exchange-imap-pop3-smtp\">OAuth 2.0 with Office365\/Exchange IMAP\/POP3\/SMTP<\/a><\/li>\n<li><a href=\"https:\/\/www.limilabs.com\/blog\/oauth2-password-grant-office365-exchange-imap-pop3-smtp\">OAuth 2.0 password grant with Office365\/Exchange IMAP\/POP3\/SMTP<\/a><\/li>\n<li><a href=\"https:\/\/www.limilabs.com\/blog\/oauth2-device-flow-office365-exchange-imap-pop3-smtp\">OAuth 2.0 device flow with Office365\/Exchange IMAP\/POP3\/SMTP<\/a><\/li>\n<\/ul>\n<\/div>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"alignleft\"><img decoding=\"async\" src=\"\/blog\/wp-content\/uploads\/2013\/09\/Outlook.png\" alt=\"Outlook\"\/><\/figure><\/div>\n\n\n\n<p><strong>OAuth <\/strong> is an open protocol to allow secure API authorization in a simple and standard method from desktop and web applications.<\/p>\n\n\n\n<p>This article describes using OAuth 2.0 to access Outlook.com IMAP and SMTP servers using <a href=\"\/mail\">.NET IMAP component<\/a> in installed applications scenario. You can also use <a href=\"\/blog\/oauth2-outlook-com-imap-web-applications\">OAuth 2.0 with Outlook.com for web applications<\/a>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">DotNetOpenAuth<\/h2>\n\n\n\n<p>First download the latest version of DotNetOpenAuth &#8211; it&#8217;s free, open source library that implements OAuth 2.0: <a href=\"http:\/\/www.dotnetopenauth.net\" rel=\"nofollow\">http:\/\/www.dotnetopenauth.net<\/a><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Register Application<\/h2>\n\n\n\n<p>Before you can use OAuth 2.0, you must register your application using the Azure Portal.<\/p>\n\n\n\n<p>This process is described in detail here: <\/p>\n\n\n\n<p><a href=\"https:\/\/docs.microsoft.com\/en-us\/graph\/auth-register-app-v2\">https:\/\/docs.microsoft.com\/en-us\/graph\/auth-register-app-v2<\/a><\/p>\n\n\n\n<p>On Azure Portal go to&nbsp;<strong>&#8220;Azure Active Directory \/ App Registrations \/ New Registration&#8221;<\/strong><\/p>\n\n\n\n<p>After registering, you need to add a new&nbsp;<strong>Client Secret<\/strong>&nbsp;for your application. You can do that using the&nbsp;<strong>&#8220;Certificates &amp; secrets&#8221;<\/strong>&nbsp;menu within the&nbsp;<strong>&#8220;Azure Active Directory \/ App Registrations settings&#8221;<\/strong>. <\/p>\n\n\n\n<p>Deprecated url for registering applications: https:\/\/account.live.com\/developers\/applications\/ <\/p>\n\n\n\n<h2 class=\"wp-block-heading\"> ClientID, ClientSecret, Scope <\/h2>\n\n\n\n<p>Now we can define clientID, clientSecret and scope variables, as well as Outlook.com OAuth 2.0 server addresses. Scope basically specifies what services we want to have access to. In our case it is user&#8217;s email address and IMAP\/SMTP access:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\nstring clientID = &quot;000000014810009D&quot;;\nstring clientSecret = &quot;wiRCccXnq1uyKcXnq1uyK&quot;;\n \nAuthorizationServerDescription server = new AuthorizationServerDescription\n{\n    AuthorizationEndpoint = new Uri(&quot;https:\/\/login.live.com\/oauth20_authorize.srf&quot;),\n    TokenEndpoint = new Uri(&quot;https:\/\/login.live.com\/oauth20_token.srf&quot;),\n    ProtocolVersion = ProtocolVersion.V20,\n};\n\nList&lt;string&gt; scope = new List&lt;string&gt; \n{ \n    OutlookScope.ImapAndSmtp.Name, \n    OutlookScope.EmailAddress.Name \n};\n<\/pre><\/div>\n\n\n<h2 class=\"wp-block-heading\">Obtain an OAuth 2.0 access token<\/h2>\n\n\n\n<p>As we are using <strong>installed applications<\/strong> scenario we&#8217;ll use <em>NativeApplicationClient<\/em> class.<\/p>\n\n\n\n<p>Because of a small issue in DotNetOpenAuth we can not use <em>UserAgentClient<\/em> directly. <em>NativeApplicationClient <\/em>inherits <em>UserAgentClient<\/em> and workarounds this issue. <strong>You can find the implementation of <em>NativeApplicationClient <\/em>on the bottom of this article<\/strong>.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\nNativeApplicationClient consumer = new NativeApplicationClient(server, clientID, clientSecret);\nUri userAuthorizationUri = consumer.RequestUserAuthorization(scope);\n\nProcess.Start(userAuthorizationUri.AbsoluteUri);\n<\/pre><\/div>\n\n\n<p>We are using <em>Process.Start<\/em> here, but you can also embed <em>WebBrowser<\/em> control in your application.<\/p>\n\n\n\n<p>At this point user is redirected to Microsoft to authorize the access:<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"\/blog\/wp-content\/uploads\/2013\/09\/Outlook_2Confirm.png\" alt=\"Outlook_2Confirm\"\/><\/figure>\n\n\n\n<p>After this step user is presented a <strong>code that needs to be pasted to your application<\/strong>:<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"\/blog\/wp-content\/uploads\/2013\/09\/Outlook_3Redirect.png\" alt=\"Outlook_3Redirect\"\/><\/figure>\n\n\n\n<p>Please note that this code also appears in the title of the browser:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>It is possible to monitor processes on your machine and act automatically when it is there.<\/li><li>If you use embedded <em>WebBrowser<\/em> control in your application, you can monitor the HTML document title after any redirect.<\/li><\/ul>\n\n\n\n<p>Following is a code that reads this code and contacts Outlook.com to exchange it for a refresh-token and an access-token:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\nstring authCode = Console.ReadLine();\n\nconsumer.ClientCredentialApplicator =\n    ClientCredentialApplicator.PostParameter(clientSecret);\n\nIAuthorizationState grantedAccess = consumer.ProcessUserAuthorization(authCode);\n\nstring accessToken = grantedAccess.AccessToken;\n<\/pre><\/div>\n\n\n<p>An access token is usually short lived, and allows you to access the user&#8217;s data. You may also received a refresh token. A refresh token can be used to request a new access token once the previous expired.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Access IMAP\/SMTP server<\/h2>\n\n\n\n<p>Finally we&#8217;ll ask Microsoft for user&#8217;s email and use <em>LoginOAUTH2<\/em> method to access Outlook.com IMAP server:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\nIAuthorizationState grantedAccess = consumer.ProcessUserAuthorization(authCode);\nstring accessToken = grantedAccess.AccessToken;\n\nOutlookApi api = new OutlookApi(accessToken);\nstring user = api.GetEmail();\n\nusing (Imap client = new Imap())\n{\n    client.ConnectSSL(&quot;imap-mail.outlook.com&quot;);\n\n    imap.LoginOAUTH2(user, accessToken);\n\n    imap.SelectInbox();\n    Lis&lt;long&gt; uids = imap.Search(Flag.Unseen);\n\n    foreach (long uid in uids)\n    {\n        var eml = imap.GetMessageByUID(uid);\n        IMail email = new MailBuilder().CreateFromEml(eml);\n        Console.WriteLine(email.Subject);\n    }\n    imap.Close();\n}\n<\/pre><\/div>\n\n\n<h2 class=\"wp-block-heading\">NativeApplicationClient class<\/h2>\n\n\n\n<p>The OAuth 2.0 client for use by native applications. It&#8217;s main purpose is to build a generic URL containing the auth code, because DotNetOpenAuth library only allows parsing an URL as a method of retrieving the AuthorizationState.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\n\/\/\/ &lt;summary&gt;\n\/\/\/ The OAuth2 client for use by native applications. \n\/\/\/ This is a partial implementation which  should be used until \n\/\/\/ the feature has been fully implemented in DotNetOpenAuth.\n\/\/\/ &lt;\/summary&gt;\npublic class NativeApplicationClient : UserAgentClient\n{\n    \/\/\/ &lt;summary&gt;\n    \/\/\/ Represents a callback URL which points to a special out of band page \n    \/\/\/ used for native OAuth2 authorization. This URL will cause the authorization \n    \/\/\/ code to appear in the title of the window.\n    \/\/\/ &lt;\/summary&gt;\n    public string OutOfBandCallbackUrl = &quot;https:\/\/login.live.com\/oauth20_desktop.srf&quot;; \/\/ Outlook\n \n    \/\/\/ &lt;summary&gt;\n    \/\/\/ Initializes a new instance of the &lt;see cref=&quot;UserAgentClient&quot;\/&gt; class.\n    \/\/\/ &lt;\/summary&gt;\n    \/\/\/ &lt;param name=&quot;authorizationServer&quot;&gt;The token issuer.&lt;\/param&gt;\n    \/\/\/ &lt;param name=&quot;clientIdentifier&quot;&gt;The client identifier.&lt;\/param&gt;\n    \/\/\/ &lt;param name=&quot;clientSecret&quot;&gt;The client secret.&lt;\/param&gt;\n    public NativeApplicationClient(\n        AuthorizationServerDescription authorizationServer,\n        string clientIdentifier,\n        string clientSecret)\n        : base(authorizationServer, clientIdentifier, clientSecret)\n    {\n    }\n \n    \/\/\/ &lt;summary&gt;\n    \/\/\/ Initializes a new instance of the &lt;see cref=&quot;UserAgentClient&quot;\/&gt; class.\n    \/\/\/ &lt;\/summary&gt;\n    \/\/\/ &lt;param name=&quot;authorizationServer&quot;&gt;The token issuer.&lt;\/param&gt;\n    public NativeApplicationClient(\n        AuthorizationServerDescription authorizationServer)\n        : this(authorizationServer, null, null)\n    {\n    }\n \n    \/\/\/ &lt;summary&gt;\n    \/\/\/ Creates the URL which should be used by the user to request the initial \n    \/\/\/ authorization. Uses the default Out-of-band-URI as a callback.\n    \/\/\/ &lt;\/summary&gt;\n    \/\/\/ &lt;param name=&quot;scope&quot;&gt;Set of requested scopes&lt;\/param&gt;\n    \/\/\/ &lt;returns&gt;URI pointing to the authorization server&lt;\/returns&gt;\n    public Uri RequestUserAuthorization(IEnumerable&lt;string&gt; scope)\n    {\n        var state = new AuthorizationState(scope);\n        state.Callback = new Uri(OutOfBandCallbackUrl);\n        return RequestUserAuthorization(state, false, null);\n    }\n \n    \/\/\/ &lt;summary&gt;\n    \/\/\/ Uses the provided authorization code to create an authorization state.\n    \/\/\/ &lt;\/summary&gt;\n    \/\/\/ &lt;param name=&quot;authCode&quot;&gt;The authorization code for getting an access token.&lt;\/param&gt;\n    \/\/\/ &lt;param name=&quot;authorizationState&quot;&gt;The authorization.  Optional.&lt;\/param&gt;\n    \/\/\/ &lt;returns&gt;The granted authorization, or &lt;c&gt;null&lt;\/c&gt; if the authorization was null or rejected.&lt;\/returns&gt;\n    public IAuthorizationState ProcessUserAuthorization(\n        string authCode, \n        IAuthorizationState authorizationState)\n    {\n        if (authorizationState == null)\n        {\n            authorizationState = new AuthorizationState(null);\n            authorizationState.Callback = new Uri(OutOfBandCallbackUrl);\n        }\n \n        \/\/ Build a generic URL containing the auth code.\n        \/\/ This is done here as we cannot modify the DotNetOpenAuth library \n        \/\/ and the underlying method only allows parsing an URL as a method \n        \/\/ of retrieving the AuthorizationState.\n        string url = &quot;http:\/\/example.com\/?code=&quot; + authCode;\n        return ProcessUserAuthorization(new Uri(url), authorizationState);\n    }\n \n    \/\/\/ &lt;summary&gt;\n    \/\/\/ Uses the provided authorization code to create an authorization state.\n    \/\/\/ &lt;\/summary&gt;\n    \/\/\/ &lt;param name=&quot;authCode&quot;&gt;The authorization code for getting an access token.&lt;\/param&gt;\n    \/\/\/ &lt;returns&gt;The granted authorization, or &lt;c&gt;null&lt;\/c&gt; if the authorization was null or rejected.&lt;\/returns&gt;\n    public IAuthorizationState ProcessUserAuthorization(string authCode)\n    {\n        return ProcessUserAuthorization(authCode, null);\n    }\n};\n<\/pre><\/div>\n\n\n<h2 class=\"wp-block-heading\">Refreshing access token<\/h2>\n\n\n\n<p>An access token is usually <strong>short lived<\/strong>. The main reason behind this is security and prevention of replay attacks. This means that for long-lived applications you need to refresh the access token. To force sending refresh token you need to add &#8220;wl.offline_access&#8221; to requested scopes:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\nList&lt;string&gt; scope = new List&lt;string&gt; \n    { \n        OutlookScope.ImapAndSmtp.Name, \n        OutlookScope.EmailAddress.Name, \n        OutlookScope.OfflineAccess.Name \n    };\n<\/pre><\/div>\n\n\n<p><strong>Your refresh token will be sent only once \u2013 don\u2019t loose it!<\/strong><\/p>\n\n\n\n<p>We recommend storing entire <em>IAuthorizationState<\/em> object received from <em>WebServerClient.ProcessUserAuthorization<\/em> method call. This object contains both: refresh token and access token, along with its expiration time.<\/p>\n\n\n\n<p>The process of refreshing access token is simple:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\nIAuthorizationState grantedAccess = ...\nconsumer.RefreshAuthorization(grantedAccess, TimeSpan.FromMinutes(20));\n<\/pre><\/div>\n\n\n<p>In the example above the access token will not be refreshed if its remaining lifetime exceeds 20 minutes.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Apps and services you&#8217;ve given access<\/h2>\n\n\n\n<p>Users can manage consent for applications and services that can access some of their data on <a href=\"https:\/\/account.live.com\/consent\/Manage\">consent panel<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>You can also read how to use: &nbsp; OAuth 2.0 with Outlook.com over IMAP for installed applications OAuth 2.0 with Outlook.com over IMAP for web applications OAuth 2.0 with Office365\/Exchange IMAP\/POP3\/SMTP OAuth 2.0 password grant with Office365\/Exchange IMAP\/POP3\/SMTP OAuth 2.0 device flow with Office365\/Exchange IMAP\/POP3\/SMTP OAuth is an open protocol to allow secure API authorization [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[4],"tags":[15,28,77,84,50,85],"class_list":["post-4236","post","type-post","status-publish","format-standard","hentry","category-mail-dll","tag-c","tag-imap","tag-imap-component","tag-oauth-2-0","tag-smtp","tag-xoauth2"],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/www.limilabs.com\/blog\/wp-json\/wp\/v2\/posts\/4236"}],"collection":[{"href":"https:\/\/www.limilabs.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.limilabs.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.limilabs.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.limilabs.com\/blog\/wp-json\/wp\/v2\/comments?post=4236"}],"version-history":[{"count":22,"href":"https:\/\/www.limilabs.com\/blog\/wp-json\/wp\/v2\/posts\/4236\/revisions"}],"predecessor-version":[{"id":6043,"href":"https:\/\/www.limilabs.com\/blog\/wp-json\/wp\/v2\/posts\/4236\/revisions\/6043"}],"wp:attachment":[{"href":"https:\/\/www.limilabs.com\/blog\/wp-json\/wp\/v2\/media?parent=4236"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.limilabs.com\/blog\/wp-json\/wp\/v2\/categories?post=4236"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.limilabs.com\/blog\/wp-json\/wp\/v2\/tags?post=4236"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}