Date: Saturday, January 28, 2023 @ 12:49:39
  Author: arojas
Revision: 467523

upgpkg: thunderbird 102.7.0-2: Fix Microsoft365 login (FS#77208)

Added:
  thunderbird/trunk/microsoft365.patch
Modified:
  thunderbird/trunk/PKGBUILD

--------------------+
 PKGBUILD           |    4 
 microsoft365.patch |  430 +++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 433 insertions(+), 1 deletion(-)

Modified: PKGBUILD
===================================================================
--- PKGBUILD    2023-01-28 12:28:07 UTC (rev 467522)
+++ PKGBUILD    2023-01-28 12:49:39 UTC (rev 467523)
@@ -8,7 +8,7 @@
 pkgbase=thunderbird
 pkgname=(thunderbird)
 pkgver=102.7.0
-pkgrel=1
+pkgrel=2
 pkgdesc='Standalone mail and news reader from mozilla.org'
 url='https://www.mozilla.org/thunderbird/'
 arch=(x86_64)
@@ -34,6 +34,7 @@
         distribution.ini
         mozconfig.cfg
         metainfo.patch
+        microsoft365.patch
         rustc_version-0.4.0.patch)
 validpgpkeys=(
   14F26682D0916CDD81E37B6D61B7B526D98F0353 # Mozilla Software Releases 
<[email protected]>
@@ -222,6 +223,7 @@
             
'5cd3ac4c94ef6dcce72fba02bc18b771a2f67906ff795e0e3d71ce7db6d8a41165bd5443908470915bdbdb98dddd9cf3f837c4ba3a36413f55ec570e6efdbb9f'
             
'a34dd97954f415a5ffe956ca1f10718bd164950566ceba328805c2ccbb54ed9081df07f2e063479bf932c4a443bb5b7443cca2f82eea3914465ed6e4863e0c0e'
             
'7e43b1f25827ddae615ad43fc1e11c6ba439d6c2049477dfe60e00188a70c0a76160c59a97cc01d1fd99c476f261c7cecb57628b5be48874be7cf991c22db290'
+            
'8e48e468a125a6b073edb59ec2fcf553d5c8108f6b4a3c40309f229e20ef025a9d8b7e32fa742d3924cd9426275bee854f1a97edbd57bbe3a3ad1865579c5af4'
             
'36d9662fc94cbf7dcf371adc13a9cda679bc75df961d86de019d3c8ebb0be3062d5ef762d175fab58696db74758100a65de45d7832e0e2bd4e15c901f72d8349'
             
'bc8fbedb66c1872b451b9f830c9dffd1bc89622203fed79e69809afaeb1453c9eea870d20234f8d9c22b81ac8bbde8cbd253c699bcec02bc527a28c029138d2e'
             
'f3bd6a6b1462dbabdbb24e760eb92a75006f56f53ecc620ff29c43e7ee4dfe8a96849ce68113fad27bb88e1f37b37cd3b379509a371e3c47045157752d3c2b9b'

Added: microsoft365.patch
===================================================================
--- microsoft365.patch                          (rev 0)
+++ microsoft365.patch  2023-01-28 12:49:39 UTC (rev 467523)
@@ -0,0 +1,430 @@
+diff --git a/mailnews/base/src/OAuth2.jsm b/mailnews/base/src/OAuth2.jsm
+--- a/comm/mailnews/base/src/OAuth2.jsm
++++ b/comm/mailnews/base/src/OAuth2.jsm
+@@ -32,16 +32,17 @@ var gConnecting = {};
+  * @param {string} issuerDetails.tokenEndpoint - The token endpoint as defined
+  *   by RFC 6749 Section 3.2.
+  */
+ function OAuth2(scope, issuerDetails) {
+   this.scope = scope;
+   this.authorizationEndpoint = issuerDetails.authorizationEndpoint;
+   this.clientId = issuerDetails.clientId;
+   this.consumerSecret = issuerDetails.clientSecret || null;
++  this.useCORS = issuerDetails.useCORS;
+   this.redirectionEndpoint =
+     issuerDetails.redirectionEndpoint || "http://localhost";;
+   this.tokenEndpoint = issuerDetails.tokenEndpoint;
+ 
+   this.extraAuthParams = [];
+ 
+   this.log = console.createInstance({
+     prefix: "mailnews.oauth",
+@@ -52,16 +53,17 @@ function OAuth2(scope, issuerDetails) {
+ 
+ OAuth2.prototype = {
+   clientId: null,
+   consumerSecret: null,
+   requestWindowURI: "chrome://messenger/content/browserRequest.xhtml",
+   requestWindowFeatures: "chrome,private,centerscreen,width=980,height=750",
+   requestWindowTitle: "",
+   scope: null,
++  useCORS: true,
+ 
+   accessToken: null,
+   refreshToken: null,
+   tokenExpires: 0,
+ 
+   connect(aSuccess, aFailure, aWithUI, aRefresh) {
+     this.connectSuccessCallback = aSuccess;
+     this.connectFailureCallback = aFailure;
+@@ -249,21 +251,27 @@ OAuth2.prototype = {
+       this.log.info(
+         `Making access token request to the token endpoint: 
${this.tokenEndpoint}`
+       );
+       data.append("grant_type", "authorization_code");
+       data.append("code", aCode);
+       data.append("redirect_uri", this.redirectionEndpoint);
+     }
+ 
+-    fetch(this.tokenEndpoint, {
++    const fetchOptions = {
+       method: "POST",
+       cache: "no-cache",
+       body: data,
+-    })
++    };
++
++    if (!this.useCORS) {
++      fetchOptions.mode = "no-cors";
++    }
++
++    fetch(this.tokenEndpoint, fetchOptions)
+       .then(response => response.json())
+       .then(result => {
+         let resultStr = JSON.stringify(result, null, 2);
+         if ("error" in result) {
+           // RFC 6749 section 5.2. Error Response
+           this.log.info(
+             `The authorization server returned an error response: 
${resultStr}`
+           );
+diff --git a/mailnews/base/src/OAuth2Providers.jsm 
b/mailnews/base/src/OAuth2Providers.jsm
+--- a/comm/mailnews/base/src/OAuth2Providers.jsm
++++ b/comm/mailnews/base/src/OAuth2Providers.jsm
+@@ -80,67 +80,73 @@ var kIssuers = new Map([
+   [
+     "accounts.google.com",
+     {
+       clientId:
+         
"406964657835-aq8lmia8j95dhl1a2bvharmfk3t1hgqj.apps.googleusercontent.com",
+       clientSecret: "kSmqreRr0qwBWJgbf5Y-PjSU",
+       authorizationEndpoint: "https://accounts.google.com/o/oauth2/auth";,
+       tokenEndpoint: "https://www.googleapis.com/oauth2/v3/token";,
++      useCORS: true,
+     },
+   ],
+   [
+     "o2.mail.ru",
+     {
+       clientId: "thunderbird",
+       clientSecret: "I0dCAXrcaNFujaaY",
+       authorizationEndpoint: "https://o2.mail.ru/login";,
+       tokenEndpoint: "https://o2.mail.ru/token";,
++      useCORS: true,
+     },
+   ],
+   [
+     "oauth.yandex.com",
+     {
+       clientId: "2a00bba7374047a6ab79666485ffce31",
+       clientSecret: "3ded85b4ec574c2187a55dc49d361280",
+       authorizationEndpoint: "https://oauth.yandex.com/authorize";,
+       tokenEndpoint: "https://oauth.yandex.com/token";,
++      useCORS: true,
+     },
+   ],
+   [
+     "login.yahoo.com",
+     {
+       clientId:
+         
"dj0yJmk9NUtCTWFMNVpTaVJmJmQ9WVdrOVJ6UjVTa2xJTXpRbWNHbzlNQS0tJnM9Y29uc3VtZXJzZWNyZXQmeD0yYw--",
+       clientSecret: "f2de6a30ae123cdbc258c15e0812799010d589cc",
+       authorizationEndpoint: 
"https://api.login.yahoo.com/oauth2/request_auth";,
+       tokenEndpoint: "https://api.login.yahoo.com/oauth2/get_token";,
++      useCORS: true,
+     },
+   ],
+   [
+     "login.aol.com",
+     {
+       clientId:
+         
"dj0yJmk9OXRHc1FqZHRQYzVvJmQ9WVdrOU1UQnJOR0pvTjJrbWNHbzlNQS0tJnM9Y29uc3VtZXJzZWNyZXQmeD02NQ--",
+       clientSecret: "79c1c11991d148ddd02a919000d69879942fc278",
+       authorizationEndpoint: "https://api.login.aol.com/oauth2/request_auth";,
+       tokenEndpoint: "https://api.login.aol.com/oauth2/get_token";,
++      useCORS: true,
+     },
+   ],
+ 
+   [
+     "login.microsoftonline.com",
+     {
+       clientId: "9e5f94bc-e8a4-4e73-b8be-63364c29d753", // Application 
(client) ID
+       // 
https://docs.microsoft.com/en-us/azure/active-directory/develop/active-directory-v2-protocols#endpoints
+       authorizationEndpoint:
+         "https://login.microsoftonline.com/common/oauth2/v2.0/authorize";,
+       tokenEndpoint:
+         "https://login.microsoftonline.com/common/oauth2/v2.0/token";,
+       redirectionEndpoint: "https://localhost";,
++      useCORS: false,
+     },
+   ],
+ 
+   // For testing purposes.
+   [
+     "mochi.test",
+     {
+       clientId: "test_client_id",
+@@ -148,16 +154,17 @@ var kIssuers = new Map([
+       authorizationEndpoint:
+         
"http://mochi.test:8888/browser/comm/mail/components/addrbook/test/browser/data/redirect_auto.sjs";,
+       tokenEndpoint:
+         
"http://mochi.test:8888/browser/comm/mail/components/addrbook/test/browser/data/token.sjs";,
+       // I don't know why, but tests refuse to work with a plain HTTP endpoint
+       // (the request is redirected to HTTPS, which we're not listening to).
+       // Just use an HTTPS endpoint.
+       redirectionEndpoint: "https://localhost";,
++      useCORS: true,
+     },
+   ],
+ ]);
+ 
+ /**
+  * OAuth2Providers: Methods to lookup OAuth2 parameters for supported OAuth2
+  * providers.
+  */
+diff --git a/mailnews/base/src/OAuth2.jsm b/mailnews/base/src/OAuth2.jsm
+--- a/comm/mailnews/base/src/OAuth2.jsm
++++ b/comm/mailnews/base/src/OAuth2.jsm
+@@ -37,10 +37,10 @@ function OAuth2(scope, issuerDetails) {
+   this.authorizationEndpoint = issuerDetails.authorizationEndpoint;
+   this.clientId = issuerDetails.clientId;
+   this.consumerSecret = issuerDetails.clientSecret || null;
+-  this.useCORS = issuerDetails.useCORS;
+   this.redirectionEndpoint =
+     issuerDetails.redirectionEndpoint || "http://localhost";;
+   this.tokenEndpoint = issuerDetails.tokenEndpoint;
++  this.useHttpChannel = issuerDetails.useHttpChannel || false;
+ 
+   this.extraAuthParams = [];
+ 
+@@ -58,7 +58,7 @@ OAuth2.prototype = {
+   requestWindowFeatures: "chrome,private,centerscreen,width=980,height=750",
+   requestWindowTitle: "",
+   scope: null,
+-  useCORS: true,
++  useHttpChannel: false,
+ 
+   accessToken: null,
+   refreshToken: null,
+@@ -256,53 +256,138 @@ OAuth2.prototype = {
+       data.append("redirect_uri", this.redirectionEndpoint);
+     }
+ 
+-    const fetchOptions = {
+-      method: "POST",
+-      cache: "no-cache",
+-      body: data,
+-    };
++    // Microsoft's OAuth explicitly breaks on receiving an Origin header, and
++    // we don't have control over whether fetch() sends Origin. Later versions
++    // of Gecko don't send it in this instance, but we have to work around it 
in
++    // this one.
++    if (this.useHttpChannel) {
++      // Get the request body as a string-based stream
++      let stream = Cc["@mozilla.org/io/string-input-stream;1"].createInstance(
++        Ci.nsIStringInputStream
++      );
++
++      let body = data.toString();
++      stream.setUTF8Data(body, body.length);
++
++      // Set up an HTTP channel in order to make our request
++      let channel = Services.io.newChannelFromURI(
++        Services.io.newURI(this.tokenEndpoint),
++        null,
++        Services.scriptSecurityManager.getSystemPrincipal(),
++        null,
++        Ci.nsILoadInfo.SEC_ALLOW_CROSS_ORIGIN_SEC_CONTEXT_IS_NULL,
++        Ci.nsIContentPolicy.TYPE_OTHER
++      );
++
++      channel.QueryInterface(Ci.nsIHttpChannel);
++      channel.setRequestHeader(
++        "Content-Type",
++        "application/x-www-form-urlencoded",
++        false
++      );
++
++      channel.QueryInterface(Ci.nsIUploadChannel);
++      channel.setUploadStream(stream, "application/x-www-form-urlencoded", 
-1);
++      channel.requestMethod = "POST";
++
++      // Set up a response handler for our request
++      let listener = 
Cc["@mozilla.org/network/stream-loader;1"].createInstance(
++        Ci.nsIStreamLoader
++      );
++
++      const oauth = this;
++
++      listener.init({
++        onStreamComplete(loader, context, status, resultLength, resultBytes) {
++          try {
++            let resultStr = new TextDecoder().decode(
++              Uint8Array.from(resultBytes)
++            );
++            let result = JSON.parse(resultStr);
+ 
+-    if (!this.useCORS) {
+-      fetchOptions.mode = "no-cors";
+-    }
++            if ("error" in result) {
++              // RFC 6749 section 5.2. Error Response
++              oauth.log.info(
++                `The authorization server returned an error response: 
${resultStr}`
++              );
++              // Typically in production this would be {"error": 
"invalid_grant"}.
++              // That is, the token expired or was revoked (user changed 
password?).
++              // Reset the tokens we have and call success so that the auth 
flow
++              // will be re-triggered.
++              oauth.accessToken = null;
++              oauth.refreshToken = null;
++              oauth.connectSuccessCallback();
++              return;
++            }
++
++            // RFC 6749 section 5.1. Successful Response
++            oauth.log.info(
++              `Successful response from the authorization server: 
${resultStr}`
++            );
++            oauth.accessToken = result.access_token;
++            if ("refresh_token" in result) {
++              oauth.refreshToken = result.refresh_token;
++            }
++            if ("expires_in" in result) {
++              oauth.tokenExpires =
++                new Date().getTime() + result.expires_in * 1000;
++            } else {
++              oauth.tokenExpires = Number.MAX_VALUE;
++            }
+ 
+-    fetch(this.tokenEndpoint, fetchOptions)
+-      .then(response => response.json())
+-      .then(result => {
+-        let resultStr = JSON.stringify(result, null, 2);
+-        if ("error" in result) {
+-          // RFC 6749 section 5.2. Error Response
++            oauth.connectSuccessCallback();
++          } catch (err) {
++            oauth.log.info(`Connection to authorization server failed: 
${err}`);
++            oauth.connectFailureCallback(err);
++          }
++        },
++      });
++
++      // Make the request
++      channel.asyncOpen(listener, channel);
++    } else {
++      fetch(this.tokenEndpoint, {
++        method: "POST",
++        cache: "no-cache",
++        body: data,
++      })
++        .then(response => response.json())
++        .then(result => {
++          let resultStr = JSON.stringify(result, null, 2);
++          if ("error" in result) {
++            // RFC 6749 section 5.2. Error Response
++            this.log.info(
++              `The authorization server returned an error response: 
${resultStr}`
++            );
++            // Typically in production this would be {"error": 
"invalid_grant"}.
++            // That is, the token expired or was revoked (user changed 
password?).
++            // Reset the tokens we have and call success so that the auth flow
++            // will be re-triggered.
++            this.accessToken = null;
++            this.refreshToken = null;
++            this.connectSuccessCallback();
++            return;
++          }
++
++          // RFC 6749 section 5.1. Successful Response
+           this.log.info(
+-            `The authorization server returned an error response: 
${resultStr}`
++            `Successful response from the authorization server: ${resultStr}`
+           );
+-          // Typically in production this would be {"error": "invalid_grant"}.
+-          // That is, the token expired or was revoked (user changed 
password?).
+-          // Reset the tokens we have and call success so that the auth flow
+-          // will be re-triggered.
+-          this.accessToken = null;
+-          this.refreshToken = null;
++          this.accessToken = result.access_token;
++          if ("refresh_token" in result) {
++            this.refreshToken = result.refresh_token;
++          }
++          if ("expires_in" in result) {
++            this.tokenExpires = new Date().getTime() + result.expires_in * 
1000;
++          } else {
++            this.tokenExpires = Number.MAX_VALUE;
++          }
+           this.connectSuccessCallback();
+-          return;
+-        }
+-
+-        // RFC 6749 section 5.1. Successful Response
+-        this.log.info(
+-          `Successful response from the authorization server: ${resultStr}`
+-        );
+-        this.accessToken = result.access_token;
+-        if ("refresh_token" in result) {
+-          this.refreshToken = result.refresh_token;
+-        }
+-        if ("expires_in" in result) {
+-          this.tokenExpires = new Date().getTime() + result.expires_in * 1000;
+-        } else {
+-          this.tokenExpires = Number.MAX_VALUE;
+-        }
+-        this.connectSuccessCallback();
+-      })
+-      .catch(err => {
+-        this.log.info(`Connection to authorization server failed: ${err}`);
+-        this.connectFailureCallback(err);
+-      });
++        })
++        .catch(err => {
++          this.log.info(`Connection to authorization server failed: ${err}`);
++          this.connectFailureCallback(err);
++        });
++    }
+   },
+ };
+diff --git a/mailnews/base/src/OAuth2Providers.jsm 
b/mailnews/base/src/OAuth2Providers.jsm
+--- a/comm/mailnews/base/src/OAuth2Providers.jsm
++++ b/comm/mailnews/base/src/OAuth2Providers.jsm
+@@ -85,7 +85,6 @@ var kIssuers = new Map([
+       clientSecret: "kSmqreRr0qwBWJgbf5Y-PjSU",
+       authorizationEndpoint: "https://accounts.google.com/o/oauth2/auth";,
+       tokenEndpoint: "https://www.googleapis.com/oauth2/v3/token";,
+-      useCORS: true,
+     },
+   ],
+   [
+@@ -95,7 +94,6 @@ var kIssuers = new Map([
+       clientSecret: "I0dCAXrcaNFujaaY",
+       authorizationEndpoint: "https://o2.mail.ru/login";,
+       tokenEndpoint: "https://o2.mail.ru/token";,
+-      useCORS: true,
+     },
+   ],
+   [
+@@ -105,7 +103,6 @@ var kIssuers = new Map([
+       clientSecret: "3ded85b4ec574c2187a55dc49d361280",
+       authorizationEndpoint: "https://oauth.yandex.com/authorize";,
+       tokenEndpoint: "https://oauth.yandex.com/token";,
+-      useCORS: true,
+     },
+   ],
+   [
+@@ -116,7 +113,6 @@ var kIssuers = new Map([
+       clientSecret: "f2de6a30ae123cdbc258c15e0812799010d589cc",
+       authorizationEndpoint: 
"https://api.login.yahoo.com/oauth2/request_auth";,
+       tokenEndpoint: "https://api.login.yahoo.com/oauth2/get_token";,
+-      useCORS: true,
+     },
+   ],
+   [
+@@ -127,7 +123,6 @@ var kIssuers = new Map([
+       clientSecret: "79c1c11991d148ddd02a919000d69879942fc278",
+       authorizationEndpoint: "https://api.login.aol.com/oauth2/request_auth";,
+       tokenEndpoint: "https://api.login.aol.com/oauth2/get_token";,
+-      useCORS: true,
+     },
+   ],
+ 
+@@ -141,7 +136,7 @@ var kIssuers = new Map([
+       tokenEndpoint:
+         "https://login.microsoftonline.com/common/oauth2/v2.0/token";,
+       redirectionEndpoint: "https://localhost";,
+-      useCORS: false,
++      useHttpChannel: true,
+     },
+   ],
+ 
+@@ -159,7 +154,6 @@ var kIssuers = new Map([
+       // (the request is redirected to HTTPS, which we're not listening to).
+       // Just use an HTTPS endpoint.
+       redirectionEndpoint: "https://localhost";,
+-      useCORS: true,
+     },
+   ],
+ ]);

Reply via email to