diff --git a/docs/simplesamlphp-changelog.md b/docs/simplesamlphp-changelog.md
index 707d1fb397a08bf3f4529d1fc8b77ddc1d566f97..bd5d853340526db923e8a3478e11e80faa4db311 100644
--- a/docs/simplesamlphp-changelog.md
+++ b/docs/simplesamlphp-changelog.md
@@ -49,6 +49,9 @@ Released TBD
 ### cas
   * Respect all LDAP options in LDAP call.
 
+### casserver
+  * Module removed; superseded by externally hosted module.
+
 ### consent
   * Sort attribute values for consent.
   * Fix table layout for MySQL > 5.6.
diff --git a/docs/simplesamlphp-upgrade-notes-1.16.md b/docs/simplesamlphp-upgrade-notes-1.16.md
index 6a809cc5da66f71584a9600ea13d78005c1ec080..b7f225947acc6835d654e5fae7ba39b57be2e320 100644
--- a/docs/simplesamlphp-upgrade-notes-1.16.md
+++ b/docs/simplesamlphp-upgrade-notes-1.16.md
@@ -15,3 +15,11 @@ The class `SimpleSAML_Error_BadUserInnput` has been renamed to
 
 The `authmyspace` module has been removed since the service is no longer
 available. 
+
+The `casserver` module has been removed because it was an outdated version,
+the up to date module is maintained in the
+[simplesamlphp-module-casserver](https://github.com/simplesamlphp/simplesamlphp-module-casserver)
+repository. It can be installed with composer:
+```
+composer require simplesamlphp/simplesamlphp-module-casserver
+```
diff --git a/modules/casserver/config-templates/module_casserver.php b/modules/casserver/config-templates/module_casserver.php
deleted file mode 100644
index fab96fbbf4d3a5f6e3f6a65edcbd2d686c56b354..0000000000000000000000000000000000000000
--- a/modules/casserver/config-templates/module_casserver.php
+++ /dev/null
@@ -1,21 +0,0 @@
-<?php
-/* 
- * Configuration for the module casserver.
- */
-
-$config = array (
-
-	'legal_service_urls' => array(
-		'http://test.feide.no/casclient',
-		'http://test.feide.no/cas2',
-	),
-
-	// Legal values: saml2, shib13
-	'auth' => 'saml2',
-	
-	'ticketcache' => 'ticketcache',
-
-	'attrname' => 'mail', // 'eduPersonPrincipalName',
-	#'attributes' => TRUE, // enable transfer of attributes
-	
-);
diff --git a/modules/casserver/default-disable b/modules/casserver/default-disable
deleted file mode 100644
index fa0bd82e2df7bd79d57593d35bc53c1f9d3ef71f..0000000000000000000000000000000000000000
--- a/modules/casserver/default-disable
+++ /dev/null
@@ -1,3 +0,0 @@
-This file indicates that the default state of this module
-is disabled. To enable, create a file named enable in the
-same directory as this file.
diff --git a/modules/casserver/www/cas.php b/modules/casserver/www/cas.php
deleted file mode 100644
index 712b4f08309f1a54b499c452524799ab9b53866c..0000000000000000000000000000000000000000
--- a/modules/casserver/www/cas.php
+++ /dev/null
@@ -1,34 +0,0 @@
-<?php
-
-/*
- * Frontend for login.php, proxy.php, validate.php and serviceValidate.php. It allows them to be called
- * as cas.php/login, cas.php/validate and cas.php/serviceValidate and is meant for clients
- * like phpCAS which expects one configured prefix which it appends login, validate and 
- * serviceValidate to.
- * 
- * This version supports CAS proxying. As SSP controls the user session (TGT in CAS parlance)
- * and the CASServer as a backend/proxy server is not aware of termination of the session the Proxy-
- * Granting-Tickets (PGT) issued have a very short ttl - pt. 60 secs.
- *
- * ServiceTickets (SP) and ProxyTickets (PT) now have a 5 secs ttl.
- *
- * Proxyed services (targetService) shall be present in the legal_service_urls config.
- * 
- */
-
- 
-$validFunctions = array(
-    'login' => 'login',
-    'proxy' => 'proxy',
-    'validate' => 'serviceValidate',
-    'serviceValidate' => 'serviceValidate',
-    'proxyValidate' => 'serviceValidate'
-);
-
-$function = substr($_SERVER['PATH_INFO'], 1);
-
-if (!isset($validFunctions[$function])) {
-    throw new \SimpleSAML\Error\NotFound('Not a valid function for cas.php.');
-}
-
-include($validFunctions[$function].".php");
diff --git a/modules/casserver/www/login.php b/modules/casserver/www/login.php
deleted file mode 100644
index 7b1d967fc8a3ae61369b66547007fd626c5ee379..0000000000000000000000000000000000000000
--- a/modules/casserver/www/login.php
+++ /dev/null
@@ -1,55 +0,0 @@
-<?php
-require 'tickets.php';
-
-/*
- * Incoming parameters:
- *  service
- *  renew
- *  gateway
- *  
- */
-
-if (!array_key_exists('service', $_GET))
-	throw new Exception('Required URL query parameter [service] not provided. (CAS Server)');
-
-$service = $_GET['service'];
-
-$forceAuthn =isset($_GET['renew']) && $_GET['renew'];
-$isPassive = isset($_GET['gateway']) && $_GET['gateway'];
-
-$config = \SimpleSAML\Configuration::getInstance();
-$casconfig = \SimpleSAML\Configuration::getConfig('module_casserver.php');
-
-$legal_service_urls = $casconfig->getValue('legal_service_urls');
-if (!checkServiceURL($service, $legal_service_urls))
-	throw new Exception('Service parameter provided to CAS server is not listed as a legal service: [service] = ' . $service);
-
-$auth = $casconfig->getValue('auth', 'saml2');
-if (!in_array($auth, array('saml2', 'shib13'), true))
- 	throw new Exception('CAS Service configured to use [auth] = ' . $auth . ' only [saml2,shib13] is legal.');
- 
-$as = new \SimpleSAML\Auth\Simple($auth);
-if (!$as->isAuthenticated()) {
-	$params = array(
-		'ForceAuthn' => $forceAuthn,
-		'isPassive' => $isPassive,
-	);
-	$as->login($params);
-}
-
-$attributes = $as->getAttributes();
-
-$path = $casconfig->resolvePath($casconfig->getValue('ticketcache', '/tmp'));
-
-$ticket = str_replace( '_', 'ST-', SimpleSAML\Utils\Random::generateID() );
-storeTicket($ticket, $path, array('service' => $service,
-	'forceAuthn' => $forceAuthn,
-	'attributes' => $attributes,
-	'proxies' => array(),
-	'validbefore' => time() + 5));
-
-\SimpleSAML\Utils\HTTP::redirectTrustedURL(
-	\SimpleSAML\Utils\HTTP::addURLParameters($service,
-		array('ticket' => $ticket)
-	)
-);
diff --git a/modules/casserver/www/proxy.php b/modules/casserver/www/proxy.php
deleted file mode 100644
index 4ae88113423f800493328ff238017ccd342d290e..0000000000000000000000000000000000000000
--- a/modules/casserver/www/proxy.php
+++ /dev/null
@@ -1,53 +0,0 @@
-<?php
-require 'tickets.php';
-
-/*
- * Incoming parameters:
- *  targetService
- *  ptg
- *  
- */
-
-if (array_key_exists('targetService', $_GET)) {
-	$targetService = $_GET['targetService'];
-	$pgt = $_GET['pgt'];
-} else {
-	throw new Exception('Required URL query parameter [targetService] not provided. (CAS Server)');
-}
-
-$casconfig = \SimpleSAML\Configuration::getConfig('module_casserver.php');
-
-$legal_service_urls = $casconfig->getValue('legal_service_urls');
-
-if (!checkServiceURL($targetService, $legal_service_urls))
-	throw new Exception('Service parameter provided to CAS server is not listed as a legal service: [service] = ' . $service);
-
-$path = $casconfig->resolvePath($casconfig->getValue('ticketcache', 'ticketcache'));
-
-$ticket = retrieveTicket($pgt, $path, false);
-if ($ticket['validbefore'] > time()) {
-	$pt = str_replace( '_', 'PT-', SimpleSAML\Utils\Random::generateID() );
-	storeTicket($pt, $path, array(
-		'service' => $targetService,
-		'forceAuthn' => false,
-		'attributes' => $ticket['attributes'],
-		'proxies' => $ticket['proxies'],
-		'validbefore' => time() + 5)
-	);
-		
-print <<<eox
-<cas:serviceResponse xmlns:cas='http://www.yale.edu/tp/cas'>
-    <cas:proxySuccess>
-        <cas:proxyTicket>$pt</cas:proxyTicket>
-    </cas:proxySuccess>
-</cas:serviceResponse>
-eox;
-} else {
-print <<<eox
-<cas:serviceResponse xmlns:cas='http://www.yale.edu/tp/cas'>
-    <cas:proxyFailure code="INVALID_REQUEST">
-        Proxygranting ticket to old - ssp casserver only supports shortlived (30 secs) pgts.
-    </cas:proxyFailure>
-</cas:serviceResponse>
-eox;
-}
diff --git a/modules/casserver/www/serviceValidate.php b/modules/casserver/www/serviceValidate.php
deleted file mode 100644
index 9fd4fdf62dd67cd7d121eb4e25ae771dd1b44572..0000000000000000000000000000000000000000
--- a/modules/casserver/www/serviceValidate.php
+++ /dev/null
@@ -1,107 +0,0 @@
-<?php
-require('tickets.php');
-
-// set manually if called directly - ie not included from validate.php or cas.php
-if (!$function) {
-    $function = 'serviceValidate';
-}
-
-/*
- * Incoming parameters:
- *  service
- *  renew
- *  ticket
- *
- */
-if (array_key_exists('service', $_GET)) {
-    $service = $_GET['service'];
-    $ticket = $_GET['ticket'];
-    $forceAuthn = isset($_GET['renew']) && $_GET['renew'];
-} else { 
-    throw new Exception('Required URL query parameter [service] not provided. (CAS Server)');
-}
-
-try {
-    // Load SimpleSAMLphp, configuration and metadata
-    $casconfig = \SimpleSAML\Configuration::getConfig('module_casserver.php');
-
-    $path = $casconfig->resolvePath($casconfig->getValue('ticketcache', 'ticketcache'));
-    $ticketcontent = retrieveTicket($ticket, $path);
-
-    $usernamefield = $casconfig->getValue('attrname', 'eduPersonPrincipalName');
-    $dosendattributes = $casconfig->getValue('attributes', false);
-
-    $attributes = $ticketcontent['attributes'];
-
-    $pgtiouxml = "";
-
-    if ($ticketcontent['service'] == $service
-            && $ticketcontent['forceAuthn'] == $forceAuthn
-            && array_key_exists($usernamefield, $attributes)
-            && $ticketcontent['validbefore'] > time()) {
-
-        if (isset($_GET['pgtUrl'])) {
-            $pgtUrl = $_GET['pgtUrl'];
-            $pgtiou = str_replace( '_', 'PGTIOU-', SimpleSAML\Utils\Random::generateID());
-            $pgt = str_replace( '_', 'PGT-', SimpleSAML\Utils\Random::generateID());
-            $content = array(
-                'attributes' => $attributes,
-                'forceAuthn' => false,
-                'proxies' => array_merge(array($service), $ticketcontent['proxies']),
-                'validbefore' => time() + 60);
-            \SimpleSAML\Utils\HTTP::fetch($pgtUrl . '?pgtIou=' . $pgtiou . '&pgtId=' . $pgt);
-            storeTicket($pgt, $path, $content);
-            $pgtiouxml = "\n<cas:proxyGrantingTicket>$pgtiou</cas:proxyGrantingTicket>\n";
-        }
-
-	$proxiesxml = join("\n", array_map(
-	    function($a) { return "<cas:proxy>$a</cas:proxy>"; },
-	    $ticketcontent['proxies']));
-	if ($proxiesxml) {
-	    $proxiesxml = "<cas:proxies>\n$proxiesxml\n</cas:proxies>\n";
-	}
-
-	returnResponse('YES', $function, $attributes[$usernamefield][0],
-            $dosendattributes ? $attributes : array(),
-            $pgtiouxml.$proxiesxml);
-    } else {
-        returnResponse('NO', $function);
-    }
-
-} catch (Exception $e) {
-    returnResponse('NO', $function, $e->getMessage());
-}
-
-function returnResponse($value, $function, $usrname = '', $attributes = array(), $xtraxml = "")
-{
-    if ($value === 'YES') {
-        if ($function != 'validate') {
-            $attributesxml = "";
-            foreach ($attributes as $attributename => $attributelist) {
-                $attr = htmlspecialchars($attributename);
-                foreach ($attributelist as $attributevalue) {
-                    $attributesxml .= "<cas:$attr>" . htmlspecialchars($attributevalue) . "</cas:$attr>\n";
-                }
-            }
-            if (sizeof($attributes)) $attributesxml = "<cas:attributes>\n" . $attributesxml . "</cas:attributes>\n";
-            echo '<cas:serviceResponse xmlns:cas="http://www.yale.edu/tp/cas">
-<cas:authenticationSuccess>
-<cas:user>' . htmlspecialchars($usrname) . '</cas:user>' .
-        $xtraxml .
-        $attributesxml .
-        '</cas:authenticationSuccess>
-</cas:serviceResponse>';
-        } else {
-            echo 'yes' . "\n" . $usrname;
-        }
-    } else {
-        if ($function != 'validate') {
-            echo '<cas:serviceResponse xmlns:cas="http://www.yale.edu/tp/cas">
-<cas:authenticationFailure code="">
-</cas:authenticationFailure>
-</cas:serviceResponse>';
-        } else {
-            echo 'no';
-        }
-    }
-}
diff --git a/modules/casserver/www/tickets.php b/modules/casserver/www/tickets.php
deleted file mode 100644
index 79498b1082d85769d1db6fe8cd945e7aa6190467..0000000000000000000000000000000000000000
--- a/modules/casserver/www/tickets.php
+++ /dev/null
@@ -1,41 +0,0 @@
-<?php
-
-function storeTicket($ticket, $path, $value ) {
-
-	if (!is_dir($path)) 
-		throw new Exception('Directory for CAS Server ticket storage [' . $path . '] does not exists. ');
-		
-	if (!is_writable($path)) 
-		throw new Exception('Directory for CAS Server ticket storage [' . $path . '] is not writable. ');
-
-	$filename = $path . '/' . $ticket;
-	file_put_contents($filename, serialize($value));
-}
-
-function retrieveTicket($ticket, $path, $unlink = true) {
-
-	if (!preg_match('/^(ST|PT|PGT)-?[a-zA-Z0-9]+$/D', $ticket)) throw new Exception('Invalid characters in ticket');
-
-	if (!is_dir($path)) 
-		throw new Exception('Directory for CAS Server ticket storage [' . $path . '] does not exists. ');
-
-	$filename = $path . '/' . $ticket;
-
-	if (!file_exists($filename))
-		throw new Exception('Could not find ticket');
-	
-	$content = file_get_contents($filename);
-	
-	if ($unlink) {
-		unlink($filename);
-	}
-	
-	return unserialize($content);
-}
-
-function checkServiceURL($service, array $legal_service_urls) {
-	foreach ($legal_service_urls AS $legalurl) {
-		if (strpos($service, $legalurl) === 0) return TRUE;
-	}
-	return FALSE;
-}
diff --git a/modules/casserver/www/validate.php b/modules/casserver/www/validate.php
deleted file mode 100644
index 29e29a05f651c7465fb1b0cff3eb61e871ca4cb9..0000000000000000000000000000000000000000
--- a/modules/casserver/www/validate.php
+++ /dev/null
@@ -1,4 +0,0 @@
-<?php
-
-$function = 'validate';
-include("serviceValidate.php");