Index: typo3/sysext/openid/ext_tables.php
===================================================================
--- typo3/sysext/openid/ext_tables.php	(Revision 4455)
+++ typo3/sysext/openid/ext_tables.php	(Arbeitskopie)
@@ -16,12 +16,19 @@
 			'eval' => 'trim,nospace,unique',
 		)
 	),
+	'tx_openid_force' => array (
+		'exclude' => 0,
+		'label' => 'LLL:EXT:openid/locallang_db.xml:be_users.tx_openid_force',
+		'config' => array (
+			'type' => 'check',
+		),
+	),
 );
 
 // Add new columns to be_users table
 t3lib_div::loadTCA('be_users');
 t3lib_extMgm::addTCAcolumns('be_users', $tempColumns, false);
-t3lib_extMgm::addToAllTCAtypes('be_users','tx_openid_openid;;;;1-1-1', '', 'after:username');
+t3lib_extMgm::addToAllTCAtypes('be_users','tx_openid_openid;;;;1-1-1,tx_openid_force', '', 'after:username');
 t3lib_extMgm::addLLrefForTCAdescr('be_users', 'EXT:' . $_EXTKEY . '/locallang_csh.xml');
 
 // Prepare new columns for fe_users table
@@ -36,12 +43,19 @@
 			'eval' => 'trim,nospace,uniqueInPid',
 		)
 	),
+	'tx_openid_force' => array (
+		'exclude' => 0,
+		'label' => 'LLL:EXT:openid/locallang_db.xml:fe_users.tx_openid_force',
+		'config' => array (
+			'type' => 'check',
+		),
+	),
 );
 
 // Add new columns to fe_users table
 t3lib_div::loadTCA('fe_users');
 t3lib_extMgm::addTCAcolumns('fe_users', $tempColumns, false);
-t3lib_extMgm::addFieldsToAllPalettesOfField('fe_users', 'username', 'tx_openid_openid');
+t3lib_extMgm::addFieldsToAllPalettesOfField('fe_users', 'username', 'tx_openid_openid,tx_openid_force');
 t3lib_extMgm::addLLrefForTCAdescr('fe_users', 'EXT:' . $_EXTKEY . '/locallang_csh.xml');
 
 ?>
\ No newline at end of file
Index: typo3/sysext/openid/locallang_db.xml
===================================================================
--- typo3/sysext/openid/locallang_db.xml	(Revision 4455)
+++ typo3/sysext/openid/locallang_db.xml	(Arbeitskopie)
@@ -7,7 +7,9 @@
 	<data type="array">
 		<languageKey index="default" type="array">
 			<label index="be_users.tx_openid_openid">OpenID identifier:</label>
+			<label index="be_users.tx_openid_force">Force OpenID login:</label>
 			<label index="fe_users.tx_openid_openid">OpenID identifier:</label>
+			<label index="fe_users.tx_openid_force">Force OpenID login:</label>
 		</languageKey>
 	</data>
 </T3locallang>
\ No newline at end of file
Index: typo3/sysext/openid/ext_tables.sql
===================================================================
--- typo3/sysext/openid/ext_tables.sql	(Revision 4455)
+++ typo3/sysext/openid/ext_tables.sql	(Arbeitskopie)
@@ -2,12 +2,14 @@
 # Table structure for table 'be_users'
 #
 CREATE TABLE be_users (
-	tx_openid_openid varchar(255) DEFAULT '' NOT NULL
+	tx_openid_openid varchar(255) DEFAULT '' NOT NULL,
+	tx_openid_force tinyint(1) unsigned DEFAULT '0' NOT NULL
 );
 
 #
 # Table structure for table 'fe_users'
 #
 CREATE TABLE fe_users (
-	tx_openid_openid varchar(255) DEFAULT '' NOT NULL
+	tx_openid_openid varchar(255) DEFAULT '' NOT NULL,
+	tx_openid_force tinyint(1) unsigned DEFAULT '0' NOT NULL
 );
\ No newline at end of file
Index: typo3/sysext/openid/sv1/class.tx_openid_sv1.php
===================================================================
--- typo3/sysext/openid/sv1/class.tx_openid_sv1.php	(Revision 4455)
+++ typo3/sysext/openid/sv1/class.tx_openid_sv1.php	(Arbeitskopie)
@@ -74,6 +74,11 @@
 	protected $authenticationInformation = array();
 
 	/**
+	 * OpenID identifier after it has been normalized.
+	 */
+	protected $openIDIdentifier;
+
+	/**
 	 * OpenID response object. It is initialized when OpenID provider returns
 	 * with success/failure response to us.
 	 *
@@ -89,7 +94,7 @@
 	protected $parentObject;
 
 	/**
-	 * If set to true, than libraries are already included.
+	 * If set to true, then libraries are already included.
 	 */
 	protected static $openIDLibrariesIncluded = false;
 
@@ -131,6 +136,10 @@
 		// Store login and authetication data
 		$this->loginData = $loginData;
 		$this->authenticationInformation = $authenticationInformation;
+
+		// Implement normalization according to OpenID 2.0 specification
+		$this->openIDIdentifier = $this->normalizeOpenID($this->loginData['uname']);
+
 		// If we are here after authentication by the OpenID server, get its response.
 		if (t3lib_div::GPvar('tx_openid_mode') == 'finish' && $this->openIDResponse == null) {
 			$this->includePHPOpenIDLibrary();
@@ -167,7 +176,7 @@
 				}
 			} else {
 				// Here if user just started authentication
-				$userRecord = $this->getUserRecord($this->loginData['uname']);
+				$userRecord = $this->getUserRecord($this->openIDIdentifier);
 			}
 			// The above function will return user record from the OpenID. It means that
 			// user actually tried to authenticate using his OpenID. In this case
@@ -190,7 +199,7 @@
 	public function authUser(array $userRecord) {
 		$result = 0;	// 0 means authentication failure
 
-		if ($userRecord['tx_openid_openid'] == '') {
+		if ($userRecord['tx_openid_openid'] == '' && $userRecord['tx_openid_force'] == false && $this->forceOpenIDusage() == false) {
 			// If user does not have OpenID, let other services to try (code 100)
 			$result = 100;
 		} else {
@@ -208,18 +217,24 @@
 				}
 			} else {
 				// We may need to send a request to the OpenID server.
-				// Check if the user identifier looks like OpenID user identifier first.
-				// Prevent PHP warning in case if identifiers is not an OpenID identifier
-				// (not an URL).
-				$urlParts = @parse_url($this->loginData['uname']);
-				if (is_array($urlParts) && $urlParts['scheme'] != '' && $urlParts['host']) {
-					// Yes, this looks like a good OpenID. Ask OpenID server (should not return)
-					$this->sendOpenIDRequest();
-					// If we are here, it means we have a valid OpenID but failed to
-					// contact the server. We stop authentication process.
-					// Alternatively it may mean that OpenID format is not correct.
-					// In both cases we return code 0 (complete failure)
-				} else {
+				// First, check if the supplied login name equals with the configured OpenID.
+				if ($this->openIDIdentifier == $userRecord['tx_openid_openid']) {
+					// Next, check if the user identifier looks like an OpenID identifier.
+					// Prevent PHP warning in case if identifiers is not an OpenID identifier
+					// (not an URL).
+					// TODO: Improve testing here. After normalization has been added, now all identifiers will succeed here...
+					$urlParts = @parse_url($this->openIDIdentifier);
+					if (is_array($urlParts) && $urlParts['scheme'] != '' && $urlParts['host']) {
+
+						// Yes, this looks like a good OpenID. Ask OpenID server (should not return)
+						$this->sendOpenIDRequest();
+
+						// If we are here, it means we have a valid OpenID but failed to
+						// contact the server. We stop authentication process.
+						// Alternatively it may mean that OpenID format is not correct.
+						// In both cases we return code 0 (complete failure)
+					}
+				} elseif ($userRecord['tx_openid_force'] == false && $this->forceOpenIDusage() == false) {
 					$result = 100;
 				}
 			}
@@ -335,7 +350,7 @@
 	protected function sendOpenIDRequest() {
 		$this->includePHPOpenIDLibrary();
 
-		$openIDIdentifier = $this->loginData['uname'];
+		$openIDIdentifier = $this->openIDIdentifier;
 
 		// Initialize OpenID client system, get the consumer
 		$openIDConsumer = $this->getOpenIDConsumer();
@@ -358,7 +373,7 @@
 		$returnURL = $this->getReturnURL();
 		$trustedRoot = t3lib_div::getIndpEnv('TYPO3_SITE_URL');
 
-	    if ($authenticationRequest->shouldSendRedirect()) {
+		if ($authenticationRequest->shouldSendRedirect()) {
 			$redirectURL = $authenticationRequest->redirectURL($trustedRoot, $returnURL);
 
 			// If the redirect URL can't be built, return. We can only return.
@@ -421,7 +436,7 @@
 			$claimedIdentifier = t3lib_div::GPvar('tx_openid_claimed');
 		} else {
 			$requestURL = t3lib_div::getIndpEnv('TYPO3_REQUEST_URL');
-			$claimedIdentifier = $this->loginData['uname'];
+			$claimedIdentifier = $this->openIDIdentifier;
 		}
 		$returnURL .= 'tx_openid_location=' . rawurlencode($requestURL) . '&' .
 						'tx_openid_mode=finish&' .
@@ -430,6 +445,49 @@
 	}
 
 	/**
+	 * Implement normalization according to OpenID 2.0 specification
+	 * See http://openid.net/specs/openid-authentication-2_0.html#normalization
+	 *
+	 * @param	string		$openIDIdentifier	OpenID identifier to normalize
+	 * @return	string		Normalized OpenID identifier
+	 */
+	protected function normalizeOpenID($openIDIdentifier) {
+		// Strip everything with and behind the fragment delimiter character "#"
+		if (strpos($openIDIdentifier, '#') !== false) {
+			$openIDIdentifier = preg_replace('/#.*$/', '', $openIDIdentifier);
+		}
+
+		// A URI with a missing scheme is normalized to a http URI
+		if (!preg_match('#^https?://#',$openIDIdentifier)) {
+			$openIDIdentifier = 'http://' . $openIDIdentifier;
+		}
+
+		// An empty path component is normalized to a slash
+		// (e.g. "http://domain.org" -> "http://domain.org/")
+		if (preg_match('#^https?://[^/]+$#',$openIDIdentifier)) {
+			$openIDIdentifier.= '/';
+		}
+
+		return $openIDIdentifier;
+	}
+
+	/**
+	 * Check if OpenID is forced globally. If this is the case, password logins will not work any more.
+	 *
+	 * @return	boolean		True if OpenID is forced globally
+	 */
+	protected function forceOpenIDusage() {
+		$isForced = false;
+		$extConf = unserialize($GLOBALS['TYPO3_CONF_VARS']['EXT']['extConf'][$this->extKey]);
+
+		if ($extConf['force_'.strtolower(TYPO3_MODE)] == true) {
+			$isForced = true;
+		}
+
+		return $isForced;
+	}
+
+	/**
 	 * Writes log message. Destination log depends on the current system mode.
 	 * For FE the function writes to the admin panel log. For BE messages are
 	 * sent to the system log. If developer log is enabled, messages are also
Index: typo3/sysext/openid/ext_conf_template.txt
===================================================================
--- typo3/sysext/openid/ext_conf_template.txt	(Revision 0)
+++ typo3/sysext/openid/ext_conf_template.txt	(Revision 0)
@@ -0,0 +1,5 @@
+  # cat=basic/enable; type=boolean; label= Force OpenID for backend (BE) users. If this is set, password logins will not work any more.
+force_be = 0
+
+  # cat=basic/enable; type=boolean; label= Force OpenID for frontend (FE) users. If this is set, password logins will not work any more.
+force_fe = 0
