diff --git a/bin/browserid b/bin/browserid
index 6f23273cbcb5e5c86adc231d3831e548b7175c6b..03fa955e44d9c29e754dee7b3bc5721ec32c2155 100755
--- a/bin/browserid
+++ b/bin/browserid
@@ -24,7 +24,7 @@ config = require('../lib/configuration.js'),
 heartbeat = require('../lib/heartbeat.js'),
 metrics = require('../lib/metrics.js'),
 logger = require('../lib/logging.js').logger,
-forward = require('../lib/http_forward'),
+forward = require('../lib/http_forward').forward,
 shutdown = require('../lib/shutdown'),
 views = require('../lib/browserid/views.js');
 
diff --git a/bin/proxy b/bin/proxy
index 02b2da157cdbf29799957d5d764aec5cdf2e45ce..ce26d11277480ae7ea312db34bcf5c17da061a24 100755
--- a/bin/proxy
+++ b/bin/proxy
@@ -14,6 +14,9 @@ config = require('../lib/configuration.js');
 var port = config.has('bind_to.port') ? config.get('bind_to.port') : 0;
 var addy = config.has('bind_to.host') ? config.get('bind_to.host') : "127.0.0.1";
 
+// set a maximum allowed time on responses to declaration of support requests
+forward.setTimeout(config.get('declaration_of_support_timeout_ms'));
+
 const allowed = /^https:\/\/[a-zA-Z0-9\.\-_]+\/\.well-known\/browserid$/;
 
 var server = http.createServer(function (req, res) {
@@ -24,7 +27,7 @@ var server = http.createServer(function (req, res) {
     return;
   }
 
-  forward(url, req, res, function(err) {
+  forward.forward(url, req, res, function(err) {
     if (err) {
       res.writeHead(400);
       res.end('Oops: ' + err.toString());
diff --git a/lib/configuration.js b/lib/configuration.js
index 8ba0fabc93cc20943e9df3bc9d10cda75c97c627..c414472c78173816225ce90a4ee205e79d0a3618 100644
--- a/lib/configuration.js
+++ b/lib/configuration.js
@@ -187,7 +187,11 @@ var conf = module.exports = convict({
     env: 'DBWRITER_URL'
   },
   process_type: 'string',
-  email_to_console: 'boolean = false'
+  email_to_console: 'boolean = false',
+  declaration_of_support_timeout_ms: {
+    doc: "The amount of time we wait for a server to respond with a declaration of support, before concluding that they are not a primary.  Only relevant when our local proxy is in use, not in production or staging",
+    format: 'integer = 15000'
+  }
 });
 
 // At the time this file is required, we'll determine the "process name" for this proc
diff --git a/lib/http_forward.js b/lib/http_forward.js
index 5277aa95643a31659a9a45085902e5b31cc37065..d88cbd85de18c4f97f85fbb563fc0929dc05c30d 100644
--- a/lib/http_forward.js
+++ b/lib/http_forward.js
@@ -9,7 +9,21 @@ https = require('https'),
 logger = require('./logging.js').logger,
 querystring = require('querystring');
 
-module.exports = function(dest, req, res, cb) {
+var global_forward_timeout = undefined;
+
+exports.setTimeout = function(to) {
+  if (typeof to != 'number') throw "setTimeout expects a numeric argument";
+  global_forward_timeout = to;
+};
+
+exports.forward = function(dest, req, res, cb) {
+  var _cb = cb;
+  var requestTimeout = undefined;
+  cb = function() {
+    if (requestTimeout) clearTimeout(requestTimeout);
+    if (_cb) _cb.apply(null, arguments);
+  }
+
   function cleanupReq() {
     if (preq) {
       preq.removeAllListeners();
@@ -56,6 +70,10 @@ module.exports = function(dest, req, res, cb) {
     cb(e);
   });
 
+  if (global_forward_timeout) {
+    requestTimeout = setTimeout(function() { preq.destroy(); }, global_forward_timeout);
+  }
+
   if (req.headers['content-type']) {
     preq.setHeader('Content-Type', req.headers['content-type']);
   }
diff --git a/lib/primary.js b/lib/primary.js
index 55861ece63a6614d02107bf4b4927705d3031e83..5e7f481d43acbc617408affb594cadad418190d4 100644
--- a/lib/primary.js
+++ b/lib/primary.js
@@ -186,7 +186,7 @@ exports.checkSupport = function(domain, cb, delegates) {
   if (typeof domain !== 'string' || !domain.length) {
     return process.nextTick(function() { cb("invalid domain"); });
   }
-  getWellKnown(domain, delegates, function (err, body, domain, delegates) {
+  getWellKnown(domain, delegates, function (err, body, domain, cbdelegates) {
     if (err) {
       logger.debug(err);
       return cb(err);
@@ -196,7 +196,7 @@ exports.checkSupport = function(domain, cb, delegates) {
       }
 
       try {
-        var r = parseWellKnownBody(body, domain, delegates, function (err, r) {
+        var r = parseWellKnownBody(body, domain, cbdelegates, function (err, r) {
           if (err) {
             logger.debug(err);
             cb(err);
@@ -226,6 +226,18 @@ exports.getPublicKey = function(domain, cb) {
   });
 };
 
+// Does emailDomain actual delegate to the issuingDomain?
+exports.delegatesAuthority = function (emailDomain, issuingDomain, cb) {
+  exports.checkSupport(emailDomain, function(err, urls, publicKey) {
+    // Check http or https://{issuingDomain}/some/sign_in_path
+    if (! err && urls && urls.auth &&
+        urls.auth.indexOf('://' + issuingDomain + '/') !== -1) {
+      cb(true);
+    }
+    cb(false);
+  });
+}
+
 // verify an assertion generated to authenticate to browserid
 exports.verifyAssertion = function(assertion, cb) {
   if (config.get('disable_primary_support')) {
diff --git a/lib/verifier/certassertion.js b/lib/verifier/certassertion.js
index b437fe4f9abbc5ecbcb38b66ae71e21557ceda50..babd1eae4e55096bad33b0016b243c876ff2a521 100644
--- a/lib/verifier/certassertion.js
+++ b/lib/verifier/certassertion.js
@@ -134,20 +134,30 @@ function verify(assertion, audience, successCB, errorCB) {
         return errorCB("audience mismatch: " + err);
       }
 
-      // verify that the issuer is the same as the email domain
-      // NOTE: for "delegation of authority" support we'll need to make this check
-      // more sophisticated
+      var token_verify = function (tok, pk, principal, ultimateIssuer) {
+        if (tok.verify(pk)) {
+          return successCB(principal.email, tok.audience, tok.expires, ultimateIssuer);
+        } else {
+          return errorCB("verification failure");
+        }
+      }
+
+      // verify that the issuer is the same as the email domain or
+      // that the email's domain delegated authority to the issuer
       var domainFromEmail = principal.email.replace(/^.*@/, '');
+
       if (ultimateIssuer != HOSTNAME && ultimateIssuer !== domainFromEmail)
       {
-        return errorCB("issuer issue '" + ultimateIssuer + "' may not speak for emails from '"
-                       + domainFromEmail + "'");
-      }
-
-      if (tok.verify(pk)) {
-        successCB(principal.email, tok.audience, tok.expires, ultimateIssuer);
+          primary.delegatesAuthority(domainFromEmail, ultimateIssuer, function (delegated) {
+            if (delegated) {
+              return token_verify(tok, pk, principal, ultimateIssuer);
+            } else {
+              return errorCB("issuer issue '" + ultimateIssuer + "' may not speak for emails from '"
+                         + domainFromEmail + "'");
+            }
+          });
       } else {
-        errorCB("verification failure");
+        return token_verify(tok, pk, principal, ultimateIssuer);
       }
     }, errorCB);
 };
diff --git a/lib/wsapi.js b/lib/wsapi.js
index c76c7e3e23bf501492316c40eb4dcf1b3a4c4c0a..7b736425feb5113c86a8f8d9ca91fddfe3204e87 100644
--- a/lib/wsapi.js
+++ b/lib/wsapi.js
@@ -22,7 +22,7 @@ secrets = require('./secrets'),
 config = require('./configuration'),
 logger = require('./logging.js').logger,
 httputils = require('./httputils.js'),
-forward = require('./http_forward.js'),
+forward = require('./http_forward.js').forward,
 url = require('url'),
 fs = require('fs'),
 path = require('path'),
diff --git a/lib/wsapi/address_info.js b/lib/wsapi/address_info.js
index c1d734bdb4269fae0b2ec62d9688b9d3e6ade1c4..778bd4291953da0cc9af22988a039bd80e67cab3 100644
--- a/lib/wsapi/address_info.js
+++ b/lib/wsapi/address_info.js
@@ -31,7 +31,7 @@ exports.process = function(req, res) {
     return httputils.badRequest(res, "invalid email address");
   }
 
-  primary.checkSupport(m[1], function(err, urls, publicKey) {
+  primary.checkSupport(m[1], function(err, urls, publicKey, delegates) {
     if (err) {
       logger.warn('error checking "' + m[1] + '" for primary support: ' + err);
       return httputils.serverError(res, "can't check email address");
diff --git a/lib/wsapi/cert_key.js b/lib/wsapi/cert_key.js
index 777d61223b6732ab620c66325baa9975eac891f5..0f0c81ef3f8d7336db02f0ad90a6719fcc086957 100644
--- a/lib/wsapi/cert_key.js
+++ b/lib/wsapi/cert_key.js
@@ -6,7 +6,7 @@ const
 db = require('../db.js'),
 httputils = require('../httputils'),
 logger = require('../logging.js').logger,
-forward = require('../http_forward.js'),
+forward = require('../http_forward.js').forward,
 config = require('../configuration.js'),
 urlparse = require('urlparse'),
 wsapi = require('../wsapi.js');