diff --git a/raddb/eap.conf b/raddb/eap.conf
index 073dd41..3e07c38 100644
--- a/raddb/eap.conf
+++ b/raddb/eap.conf
@@ -259,6 +259,16 @@
 		       #
 		#	check_cert_cn = %{User-Name}
 		#
+			#
+			# If check_cert_san is set, the value will
+			# be xlat'ed and checked against each of the
+			# elements within the subjectAltName attribute.
+			# If subjectAltName is missing, or no elements
+			# match the value, the certificate verification
+			# will fail.
+			#
+		#	check_cert_san = %{User-Name}
+
 			# Set this option to specify the allowed
 			# TLS cipher suites.  The format is listed
 			# in "man 1 ciphers".
diff --git a/src/modules/rlm_eap/types/rlm_eap_tls/rlm_eap_tls.c b/src/modules/rlm_eap/types/rlm_eap_tls/rlm_eap_tls.c
index 28049cb..40d6002 100644
--- a/src/modules/rlm_eap/types/rlm_eap_tls/rlm_eap_tls.c
+++ b/src/modules/rlm_eap/types/rlm_eap_tls/rlm_eap_tls.c
@@ -122,6 +122,8 @@ static CONF_PARSER module_config[] = {
 	  offsetof(EAP_TLS_CONF, cipher_list), NULL, NULL},
 	{ "check_cert_issuer", PW_TYPE_STRING_PTR,
 	  offsetof(EAP_TLS_CONF, check_cert_issuer), NULL, NULL},
+	{ "check_cert_san", PW_TYPE_STRING_PTR,
+	  offsetof(EAP_TLS_CONF, check_cert_san), NULL, NULL},
 	{ "make_cert_command", PW_TYPE_STRING_PTR,
 	  offsetof(EAP_TLS_CONF, make_cert_command), NULL, NULL},
 
@@ -465,6 +467,7 @@ static int cbtls_verify(int ok, X509_STORE_CTX *ctx)
 	char issuer[1024]; /* Used for the issuer name */
 	char common_name[1024];
 	char cn_str[1024];
+	char san_str[1024];
 	char buf[64];
 	EAP_HANDLER *handler = NULL;
 	X509 *client_cert;
@@ -662,6 +665,48 @@ static int cbtls_verify(int ok, X509_STORE_CTX *ctx)
  		}
 
 		/*
+		 *	Check the SAN against the xlat'ed value.
+		 */
+		if (my_ok && conf->check_cert_san) {
+			if (!radius_xlat(san_str, sizeof(san_str), conf->check_cert_san, handler->request, NULL)) {
+				radlog(L_ERR, "rlm_eap_tls (%s): xlat failed.",
+					conf->check_cert_san);
+				/* if this fails, fail the verification */
+				my_ok = 0;
+			} else {
+				STACK_OF(GENERAL_NAME) *names;
+				BIO *bio;
+				if ((names = X509_get_ext_d2i(client_cert,
+					NID_subject_alt_name, NULL, NULL)) &&
+					(bio = BIO_new(BIO_s_mem()))) {
+					GENERAL_NAME *name;
+					char bio_str[1024];
+					int found = 0, i, n;
+
+					for (i = 0; i < sk_GENERAL_NAME_num(names); i++) {
+						name = sk_GENERAL_NAME_value(names, i);
+						ASN1_STRING_print_ex(bio, name->d.ia5, ASN1_STRFLGS_ESC_CTRL|ASN1_STRFLGS_UTF8_CONVERT);
+						n = BIO_pending(bio);
+						if (n > 0 && n < sizeof(bio_str)) {
+							n = BIO_read(bio, bio_str, n);
+							bio_str[n] = 0;
+							RDEBUG2("checking certificate subjectAltName (%s) with xlat'ed value (%s)", bio_str, san_str);
+							if (!strcmp(san_str, bio_str)) {
+								found = 1;
+							}
+						}
+					}
+					BIO_free(bio);
+
+					if (!found) {
+						radlog(L_AUTH, "rlm_eap_tls: Certificate subjectAltName does not match specified value (%s)!", san_str);
+						my_ok = 0;
+					}
+				}
+			}
+		}
+
+		/*
 		 *	If the conf tells us to, check the CN in the
 		 *	cert against xlat'ed value, but only if the
 		 *	previous checks passed.
diff --git a/src/modules/rlm_eap/types/rlm_eap_tls/rlm_eap_tls.h b/src/modules/rlm_eap/types/rlm_eap_tls/rlm_eap_tls.h
index d60b1b6..e8b70ba 100644
--- a/src/modules/rlm_eap/types/rlm_eap_tls/rlm_eap_tls.h
+++ b/src/modules/rlm_eap/types/rlm_eap_tls/rlm_eap_tls.h
@@ -60,6 +60,7 @@ typedef struct eap_tls_conf {
 	char		*check_cert_cn;
 	char		*cipher_list;
 	char		*check_cert_issuer;
+	char		*check_cert_san;
 
         int     	session_cache_enable;
         int     	session_timeout;
