diff --git a/config-templates/config.php b/config-templates/config.php
index 2379369c16ed98871534f3cd48d8c434f4055aad..4a286d3fd731b1e97fab74885f61a78be8fb1fb7 100644
--- a/config-templates/config.php
+++ b/config-templates/config.php
@@ -290,6 +290,14 @@ $config = array (
 	 */
 	'session.authtoken.cookiename' => 'SimpleSAMLAuthToken',
 
+	/**
+	 * Custom function for session checking called on session init and loading.
+	 * See docs/simplesamlphp-advancedfeatures.txt for function code example.
+	 *
+	 * Example:
+	 *   'session.check_function' => array('sspmod_example_Util', 'checkSession'),
+	 */
+
 	/*
 	 * Languages available, RTL languages, and what language is default
 	 */
diff --git a/docs/simplesamlphp-advancedfeatures.txt b/docs/simplesamlphp-advancedfeatures.txt
index e5bac450c7d16e623207f3bbda1b1466338263cc..c1af38f4f614c798a10ffe427102ab31629aee45 100644
--- a/docs/simplesamlphp-advancedfeatures.txt
+++ b/docs/simplesamlphp-advancedfeatures.txt
@@ -171,6 +171,56 @@ There is also an additional fallback for the private key and the certificate. If
 
 
 
+Session checking function
+-------------------------
+
+Optional session checking function, called on session init and loading, defined with 'session.check_function' in config.php.
+
+Example code for the function with GeoIP country check:
+
+
+    public static function checkSession($session, $init = FALSE) {
+        $data_type = 'example:check_session';
+        $data_key = 'remote_addr';
+
+        $remote_addr = NULL;
+        if (!empty($_SERVER['REMOTE_ADDR'])) {
+            $remote_addr = (string)$_SERVER['REMOTE_ADDR'];
+        }
+
+        if ($init) {
+            $session->setData($data_type, $data_key, $remote_addr);
+            return;
+        }
+
+        if (!function_exists('geoip_country_code_by_name')) {
+            SimpleSAML_Logger::warning('geoip php module required.');
+            return TRUE;
+        }
+
+        $stored_remote_addr = $session->getData($data_type, $data_key);
+        if ($stored_remote_addr === NULL) {
+            SimpleSAML_Logger::warning('Stored data not found.');
+            return FALSE;
+        }
+
+        $country_a = geoip_country_code_by_name($remote_addr);
+        $country_b = geoip_country_code_by_name($stored_remote_addr);
+
+        if ($country_a === $country_b) {
+            if ($stored_remote_addr !== $remote_addr) {
+                $session->setData($data_type, $data_key, $remote_addr);
+            }
+
+            return TRUE;
+        }
+
+        return FALSE;
+    }
+
+
+
+
 Support
 -------
 
diff --git a/lib/SimpleSAML/Session.php b/lib/SimpleSAML/Session.php
index d586e5104bea037e2cad277add1afc70b3a4e929..e373dc4f4350563e2dd1abb8b108392db3c77193 100644
--- a/lib/SimpleSAML/Session.php
+++ b/lib/SimpleSAML/Session.php
@@ -169,6 +169,14 @@ class SimpleSAML_Session {
 
 		$this->dirty = TRUE;
 		$this->addShutdownFunction();
+
+		/* Initialize data for session check function if defined */
+		$globalConfig = SimpleSAML_Configuration::getInstance();
+		$checkFunction = $globalConfig->getArray('session.check_function', NULL);
+		if (isset($checkFunction)) {
+			assert('is_callable($checkFunction)');
+			call_user_func($checkFunction, $this, TRUE);
+		}
 	}
 
 
@@ -1030,16 +1038,30 @@ class SimpleSAML_Session {
 			$session->sessionId = $sh->getCookieSessionId();
 		}
 
-		if ($checkToken && $session->authToken !== NULL) {
+		if ($checkToken) {
 			$globalConfig = SimpleSAML_Configuration::getInstance();
-			$authTokenCookieName = $globalConfig->getString('session.authtoken.cookiename', 'SimpleSAMLAuthToken');
-			if (!isset($_COOKIE[$authTokenCookieName])) {
-				SimpleSAML_Logger::warning('Missing AuthToken cookie.');
-				return NULL;
+
+			if ($session->authToken !== NULL) {
+				$authTokenCookieName = $globalConfig->getString('session.authtoken.cookiename', 'SimpleSAMLAuthToken');
+				if (!isset($_COOKIE[$authTokenCookieName])) {
+					SimpleSAML_Logger::warning('Missing AuthToken cookie.');
+					return NULL;
+				}
+				if ($_COOKIE[$authTokenCookieName] !== $session->authToken) {
+					SimpleSAML_Logger::warning('Invalid AuthToken cookie.');
+					return NULL;
+				}
 			}
-			if ($_COOKIE[$authTokenCookieName] !== $session->authToken) {
-				SimpleSAML_Logger::warning('Invalid AuthToken cookie.');
-				return NULL;
+
+			/* Run session check function if defined */
+			$checkFunction = $globalConfig->getArray('session.check_function', NULL);
+			if (isset($checkFunction)) {
+				assert('is_callable($checkFunction)');
+				$check = call_user_func($checkFunction, $session);
+				if ($check !== TRUE) {
+					SimpleSAML_Logger::warning('Session did not pass check function.');
+					return NULL;
+				}
 			}
 		}