diff --git a/config-templates/config.php b/config-templates/config.php
index b573f432d8ce2bea2a3961d5ed173342b91caac6..50e03fdcc02401a32c49e0be25d52ce0190e10d2 100644
--- a/config-templates/config.php
+++ b/config-templates/config.php
@@ -564,7 +564,7 @@ $config = [
      * Example:
      *  'session.cookie.samesite' => 'None',
      */
-    'session.cookie.samesite' => null,
+    'session.cookie.samesite' => \SimpleSAML\Utils\HTTP::canSetSameSiteNone() ? 'None' : null,
 
     /*
      * Options to override the default settings for php sessions.
@@ -792,7 +792,7 @@ $config = [
     'language.cookie.secure' => false,
     'language.cookie.httponly' => false,
     'language.cookie.lifetime' => (60 * 60 * 24 * 900),
-    'language.cookie.samesite' => null,
+    'language.cookie.samesite' => \SimpleSAML\Utils\HTTP::canSetSameSiteNone() ? 'None' : null,
 
     /**
      * Custom getLanguage function called from SimpleSAML\Locale\Language::getLanguage().
diff --git a/lib/SimpleSAML/Utils/HTTP.php b/lib/SimpleSAML/Utils/HTTP.php
index 23c7bdf84d0f627e24c1d0abd8a7977b3beb63fa..d74031ef02e56d166cc2dc26c38c1b651752b886 100644
--- a/lib/SimpleSAML/Utils/HTTP.php
+++ b/lib/SimpleSAML/Utils/HTTP.php
@@ -18,6 +18,51 @@ use SimpleSAML\XHTML\Template;
  */
 class HTTP
 {
+    /**
+     * Determine if the user agent can support cookies being sent with SameSite equal to "None".
+     * Browsers with out support may drop the cookie and or treat is a stricter setting
+     * Browsers with support may have additional requirements on setting it on non-secure websites.
+     *
+     * Based on the Azure teams experience rolling out support and Chromium's advice
+     * https://devblogs.microsoft.com/aspnet/upcoming-samesite-cookie-changes-in-asp-net-and-asp-net-core/
+     * https://www.chromium.org/updates/same-site/incompatible-clients
+     * @return bool true if user agent supports a None value for SameSite.
+     */
+    public static function canSetSameSiteNone(): bool
+    {
+        $useragent = $_SERVER['HTTP_USER_AGENT'] ?? null;
+        if (!$useragent) {
+            return true;
+        }
+        // All iOS 12 based browsers have no support
+        if (strpos($useragent, "CPU iPhone OS 12") !== false || strpos($useragent, "iPad; CPU OS 12") !== false) {
+            return false;
+        }
+
+        // Safari Mac OS X 10.14 has no support
+        // - Safari on Mac OS X.
+        if (strpos($useragent, "Macintosh; Intel Mac OS X 10_14") !== false) {
+            // regular safari
+            if (strpos($useragent, "Version/") !== false && strpos($useragent, "Safari") !== false) {
+                return false;
+            } elseif (preg_match('|AppleWebKit/[\.\d]+ \(KHTML, like Gecko\)$|', $useragent)) {
+                return false;
+            }
+        }
+
+        // Chrome based UCBrowser may have support (>= 12.13.2) even though its chrome version is old
+        $matches = [];
+        if (preg_match('|UCBrowser/(\d+\.\d+\.\d+)[\.\d]*|', $useragent, $matches)) {
+            return version_compare($matches[1], '12.13.2', '>=');
+        }
+
+        // Chrome 50-69 may have broken SameSite=None and don't require it to be set
+        if (strpos($useragent, "Chrome/5") !== false || strpos($useragent, "Chrome/6") !== false) {
+            return false;
+        }
+        return true;
+    }
+
     /**
      * Obtain a URL where we can redirect to securely post a form with the given data to a specific destination.
      *
diff --git a/modules/multiauth/docs/multiauth.md b/modules/multiauth/docs/multiauth.md
index 97ae265feb2724b63d0c4b154b748d75cb6ca979..5b474513a0ed6088e2c0c7a49cf6a361cab7c0de 100644
--- a/modules/multiauth/docs/multiauth.md
+++ b/modules/multiauth/docs/multiauth.md
@@ -36,12 +36,14 @@ authentication source:
                     'es' => 'Entrar usando un SP SAML',
                 ),
                 'css-class' => 'SAML',
+                'AuthnContextClassRef' => array('urn:oasis:names:tc:SAML:2.0:ac:classes:SmartcardPKI', 'urn:oasis:names:tc:SAML:2.0:ac:classes:MobileTwoFactorContract'),
             ),
             'example-admin' => array(
                 'text' => array(
                     'en' => 'Log in using the admin password',
                     'es' => 'Entrar usando la contraseña de administrador',
                 ),
+                'AuthnContextClassRef' => 'urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport',
             ),
         ),
     ),
@@ -77,7 +79,7 @@ compatible fashion so both cases should work.
 
 Each source in the sources array has a key and a value. As
 mentioned above the key is the authsource identifier and the value
-is another array with two optional keys: 'text' and 'css-class'.
+is another array with optional keys: 'text', 'css-class', 'help', and 'AuthnContextClassRef'.
 The text element is another array with localized strings for one
 or more languages. These texts will be shown in the selectsource.php
 view. Note that you should at least enter the text in the default
@@ -87,7 +89,14 @@ the <li> element in the selectsource.php view. By default the
 authtype of the authsource is used as the css class with colons
 replaced by dashes. So in the previous example, the css class used
 in the 'example-admin' authentication source would be
-'core-AdminPassword'.
+'core-AdminPassword'. The help element is another array with localized
+strings for one or more languages. These texts will be shown in the
+selectsource.php view. The AuthnContextClassRef is either a string or
+an array of strings containing [context class ref names](https://docs.oasis-open.org/security/saml/v2.0/saml-authn-context-2.0-os.pdf).
+If an SP sets AuthnContextClassRef the list of authsources will be
+filtered to only those containing context class refs that are part of the list set by the SP.
+If a single authsource results from this filtering the user will be taken directly to the
+authentication page for that source, and will never be shown the multiauth select page.
 
 It is possible to add the parameter `source` to the calling URL, 
 when accessing a service, to allow the user to preselect the
diff --git a/modules/multiauth/lib/Auth/Source/MultiAuth.php b/modules/multiauth/lib/Auth/Source/MultiAuth.php
index 3f93169cb7f463ed93cebdd4c3108a5637b654af..9e5273146c489bd01d28d0f9f3f987681558e663 100644
--- a/modules/multiauth/lib/Auth/Source/MultiAuth.php
+++ b/modules/multiauth/lib/Auth/Source/MultiAuth.php
@@ -4,6 +4,7 @@ declare(strict_types=1);
 
 namespace SimpleSAML\Module\multiauth\Auth\Source;
 
+use SAML2\Constants;
 use Exception;
 use SimpleSAML\Assert\Assert;
 use SimpleSAML\Auth;
@@ -12,6 +13,7 @@ use SimpleSAML\Error;
 use SimpleSAML\Module;
 use SimpleSAML\Session;
 use SimpleSAML\Utils;
+use SimpleSAML\Module\saml\Error\NoAuthnContext;
 
 /**
  * Authentication source which let the user chooses among a list of
@@ -113,11 +115,22 @@ class MultiAuth extends Auth\Source
                 }
             }
 
+            $class_ref = [];
+            if (array_key_exists('AuthnContextClassRef', $info)) {
+                $ref = $info['AuthnContextClassRef'];
+                if (is_string($ref)) {
+                    $class_ref = [$ref];
+                } else {
+                    $class_ref = $ref;
+                }
+            }
+
             $this->sources[] = [
                 'source' => $source,
                 'text' => $text,
                 'help' => $help,
                 'css_class' => $css_class,
+                'AuthnContextClassRef' => $class_ref,
             ];
         }
     }
@@ -144,6 +157,30 @@ class MultiAuth extends Auth\Source
             $state['multiauth:preselect'] = $this->preselect;
         }
 
+        if (
+            !is_null($state['saml:RequestedAuthnContext'])
+            && array_key_exists('AuthnContextClassRef', $state['saml:RequestedAuthnContext'])
+        ) {
+            $refs = array_values($state['saml:RequestedAuthnContext']['AuthnContextClassRef']);
+            $new_sources = [];
+            foreach ($this->sources as $source) {
+                if (count(array_intersect($source['AuthnContextClassRef'], $refs)) >= 1) {
+                    $new_sources[] = $source;
+                }
+            }
+            $state[self::SOURCESID] = $new_sources;
+
+            $number_of_sources = count($new_sources);
+            if ($number_of_sources === 0) {
+                throw new NoAuthnContext(
+                    Constants::STATUS_RESPONDER,
+                    'No authentication sources exist for the requested AuthnContextClassRefs: ' . implode(', ', $refs)
+                );
+            } else if ($number_of_sources === 1) {
+                MultiAuth::delegateAuthentication($new_sources[0]['source'], $state);
+            }
+        }
+
         // Save the $state array, so that we can restore if after a redirect
         $id = Auth\State::saveState($state, self::STAGEID);
 
diff --git a/tests/lib/SimpleSAML/Utils/HTTPTest.php b/tests/lib/SimpleSAML/Utils/HTTPTest.php
index e60dae5c8d9df57cb059166b946fbde836ed9d24..f6f90fd64b31ee8e3d158540ac4d2c4ecc82db65 100644
--- a/tests/lib/SimpleSAML/Utils/HTTPTest.php
+++ b/tests/lib/SimpleSAML/Utils/HTTPTest.php
@@ -526,4 +526,57 @@ class HTTPTest extends ClearStateTestCase
         $this->assertMatchesRegularExpression('/\b[Ss]ame[Ss]ite=Lax(;|$)/', $headers[2]);
         $this->assertMatchesRegularExpression('/\b[Ss]ame[Ss]ite=Strict(;|$)/', $headers[3]);
     }
+
+    /**
+     * Test detecting if user agent supports None
+     * @dataProvider detectSameSiteProvider
+     * @param null|string $userAgent The user agent. Null means not set, like with CLI
+     * @param bool $supportsNone None can be set as a SameSite flag
+     */
+    public function testDetectSameSiteNoneBehavior(?string $userAgent, bool $supportsNone): void
+    {
+        if ($userAgent) {
+            $_SERVER['HTTP_USER_AGENT'] = $userAgent;
+        }
+        $this->assertEquals($supportsNone, HTTP::canSetSameSiteNone(), $userAgent ?? 'No user agent set');
+    }
+
+    public function detectSameSiteProvider(): array
+    {
+        // @codingStandardsIgnoreStart
+        return [
+          [null, true],
+          ['some-new-browser', true],
+            //Browsers that can handle 'None'
+            // Chrome
+            ['Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.70 Safari/537.36', true],
+            // Chome on windows
+            ['Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36', true],
+            // Chrome linux
+            ['Mozilla/5.0 (X11; HasCodingOs 1.0; Linux x64) AppleWebKit/637.36 (KHTML, like Gecko) Chrome/70.0.3112.101 Safari/637.36 HasBrowser/5.0', true],
+             // Safari iOS 13
+            ['Mozilla/5.0 (iPhone; CPU iPhone OS 13_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/11.2 Mobile/15E148 Safari/604.1', true],
+            // Mac OS X with support
+            ['Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.1 Safari/605.1.15', true],
+            // UC Browser with support
+            ['Mozilla/5.0 (Linux; U; Android 9; en-US; SM-A705FN Build/PPR1.180610.011) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/57.0.2987.108 UCBrowser/12.13.2.1208 Mobile Safari/537.36', true],
+            ['Mozilla/5.0 (Linux; U; Android 10; en-US; RMX2020 Build/QP1A.190711.020) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/57.0.2987.108 UCBrowser/12.13.5.1209 Mobile Safari/537.36', true],
+            // Embedded Mac with support
+            ['Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_4) AppleWebKit/605.1.15 (KHTML, like Gecko)', true],
+            // Browser without support
+            // Old Safari on mac
+            ['Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/12.1.1 Safari/605.1.15', false],
+            // Old Safari on iOS 12 (phone and ipad
+            ['Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/12.1 Mobile/15E148 Safari/604.1', false],
+            ['Mozilla/5.0 (iPad; CPU OS 12_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/12.0 Mobile/16A5288q Safari/605.1.15', false],
+            // Chromium without support
+            ['Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Ubuntu Chromium/65.0.3325.181 Chrome/65.0.3325.181 Safari/537.36', false],
+            // UC Browser without support
+            ['Mozilla/5.0 (Linux; U; Android 8.1.0; zh-CN; EML-AL00 Build/HUAWEIEML-AL00) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/57.0.2987.108 baidu.sogo.uc.UCBrowser/11.9.4.974 UWS/2.13.1.48 Mobile Safari/537.36 AliApp(DingTalk/4.5.11) com.alibaba.android.rimet/10487439 Channel/227200 language/zh-CN', false],
+            ['Mozilla/5.0 (Linux; U; Android 7.1.1; en-US; CPH1723 Build/N6F26Q) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/57.0.2987.108 UCBrowser/12.13.0.1207 Mobile Safari/537.36', false],
+            // old embedded browser
+            ['Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_4) AppleWebKit/605.1.15 (KHTML, like Gecko)', false]
+        ];
+        // @codingStandardsIgnoreEnd
+    }
 }