Merge branch 'master' into aidanr/login_auth_work
diff --git a/bundles/org.eclipse.orion.client.core/web-ide.conf b/bundles/org.eclipse.orion.client.core/web-ide.conf
index 0806dcd..aff1310 100644
--- a/bundles/org.eclipse.orion.client.core/web-ide.conf
+++ b/bundles/org.eclipse.orion.client.core/web-ide.conf
@@ -110,3 +110,9 @@
 
 #uncomment this line to enable access logs in NCSA format on the Jetty server
 #orion.jetty.access.logs.enable=true
+
+#uncomment and update these lines and specify the oauth client and secret keys
+#orion.oauth.google.client={client_key}
+#orion.oauth.google.secret={secret_key}
+#orion.oauth.github.client={client_key}
+#orion.oauth.github.secret={secret_key}
\ No newline at end of file
diff --git a/bundles/org.eclipse.orion.client.ui/web/mixloginstatic/LoginWindow.html b/bundles/org.eclipse.orion.client.ui/web/mixloginstatic/LoginWindow.html
index f82fbfd..579635c 100644
--- a/bundles/org.eclipse.orion.client.ui/web/mixloginstatic/LoginWindow.html
+++ b/bundles/org.eclipse.orion.client.ui/web/mixloginstatic/LoginWindow.html
@@ -1,139 +1,162 @@
 <!DOCTYPE html>
 <html>
-<head>
-<meta name="copyright" content="Copyright (c) 2010,2012 IBM Corporation and others.">
-<meta http-equiv="Content-Language" content="en-us">
-<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
-<link rel="stylesheet" type="text/css" href="css/landing.css" />
-<script src="../requirejs/require.js"></script>
-<script type="text/javascript">
-/*eslint-env browser, amd*/
-require({
-  baseUrl: '..',
+	<head>
+		<meta name="copyright" content="Copyright (c) 2010,2012 IBM Corporation and others.">
+		<meta http-equiv="Content-Language" content="en-us">
+		<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+		<link rel="stylesheet" type="text/css" href="css/landing.css" />
+		<script src="../requirejs/require.js"></script>
+		<script type="text/javascript">
+			/*eslint-env browser, amd*/
+			require({
+			  baseUrl: '..',
 
-  // set the paths to our library packages
-  packages: [],
-  paths: {
-	  text: 'requirejs/text',
-	  i18n: 'requirejs/i18n',
-	  domReady: 'requirejs/domReady'
-  }
-});
-require(["mixloginstatic/LoginWindow"]);
-</script>
-<title>Orion Login Page</title>
-</head>
-<body style="margin: 0; padding: 0;" tabindex="-1">
-	<div class="orion-banner">
-		<div class="orion-nav-bar">
-			<header class="orion-logo" role="banner"></header>
-			<nav role="navigation">
-				<a class="orion-rss-link" href="http://planetorion.org/news/" target="_blank" title="Orion News" alt="Orion News" tabindex="100"></a>
-				<a class="orion-twitter-link" href="http://twitter.com/orionhub" target="_blank" title="Orion Twitter" alt="Orion Twitter" tabindex="99"></a>
-			</nav>
+			  // set the paths to our library packages
+			  packages: [],
+			  paths: {
+				  text: 'requirejs/text',
+				  i18n: 'requirejs/i18n',
+				  domReady: 'requirejs/domReady'
+			  }
+			});
+			require(["mixloginstatic/LoginWindow"]);
+		</script>
+		<title>Orion Login Page</title>
+	</head>
+	<body style="margin: 0; padding: 0;" tabindex="-1">
+		<div class="orion-banner">
+			<div class="orion-nav-bar">
+				<header class="orion-logo" role="banner"></header>
+				<nav role="navigation">
+					<a class="orion-rss-link" href="http://planetorion.org/news/" target="_blank" title="Orion News" alt="Orion News" tabindex="100"></a>
+					<a class="orion-twitter-link" href="http://twitter.com/orionhub" target="_blank" title="Orion Twitter" alt="Orion Twitter" tabindex="99"></a>
+				</nav>
+			</div>
 		</div>
-	</div>
-	<div class="orion-login-container" id="login-window" style="display:none;">
-		<div class="orion-landing-area" role="main">
-			<aside id="orionInfoArea" class="orion-info" style="visibility: hidden;" tabindex="0" role="complementary" aria-atomic="true" aria-live="assertive">
-					<div id="orionInfoMessage" class="orion-info-message">&nbsp;</div>
-					<div id="orionInfoLink" class="orion-info-link"><a href="/mixloginstatic/ServerStatus.html"> [more info...]</a></div>
-			</aside>
-			<div id="errorWin" class="orion-error" style="visibility: hidden;" aria-atomic="true" aria-live="assertive">
-					<div id="errorMessage">&nbsp;</div>
-			</div>
-
-			<div class="orion-welcome-area"></div>
-			<div class="orion-login" id="orionLoginForm" style="visibility: hidden;">
-				<div id="orion-login-header" class="orion-form-header">Log in</div>
-				<form>
-					<div class="orion-input-holder">
-						<input type="text" class="orion-text-input" name="login" id="login" placeholder="username" title="Username" autocomplete="on" autofocus="autofocus" spellcheck="false" autocapitalize="off">
-					</div>
-					<div class="orion-input-holder">
-						<input name="password" type="password" id="password" class="orion-text-input" placeholder="password" title="Password">
-					</div>
-					<div class="orion-login-button-holder">
-						<input type="button" name="password" id="loginButton" class="orion-login-button" value="Sign in" tabindex="0">
-					</div>
-					<div class="orion-login-button-holder">
-						<input type="button" id="cancelLoginButton" class="orion-cancel-button" value="Cancel" tabindex="0">
-					</div>
-
-					<div class="orion-login-forgot-holder">
-						<a id="resetUserLink" class="orion-forgot-password">Forgot password?</a>
-					</div>
-				</form>
-			</div>
-
-			<div class="orion-signup" id="newUserHeaderShown" style="visibility: hidden;">
-				<div id="orion-signup-header" class="orion-form-header">Create an account</div>
-				<form>
-					<div class="orion-register-input-holder">
-						<input type="text" class="orion-text-input" placeholder="username" title="Username" autocomplete="on" autofocus="autofocus" id="create_login" spellcheck="false" autocapitalize="off">
-					</div>
-					<div class="orion-register-input-holder">
-						<input type="password" class="orion-text-input" placeholder="password" title="Password" autocomplete="on" id="create_password" aria-required="true">
-					</div>
-					<div class="orion-register-input-holder">
-						<input type="password" class="orion-text-input" placeholder="retype password" title="Retype password" autocomplete="on" name="passwordRetype" id="create_passwordRetype" aria-required="true">
-					</div>
-					<div class="orion-register-input-holder">
-						<input type="text" class="orion-text-input" placeholder="email" title="Email" autocomplete="on" name="email" id="create_email" aria-required="true">
-					</div>
-					<div class="orion-login-button-holder">
-						<input id="createButton" type="button" class="orion-login-button" value="Sign up" tabindex="0">
-					</div>
-					<div style="padding-right: 5px;"></div>
-					<div class="orion-login-button-holder">
-						<input id="hideRegisterButton" type="button" class="orion-cancel-button" value="Cancel" tabindex="0">
-					</div>
-
-				</form>
-			</div>
-
-			<div class="orion-reset" id="orionReset" style="visibility: hidden;">
-				<div id="orion-reset-header" class="orion-form-header">Reset Orion account</div>
-				<div class="orion-reset-note">Provide your username or email to reset your password.</div>
-				<form>
-					<div class="orion-reset-input-holder">
-						<input type="text" class="orion-text-input" id="reset" placeholder="username" autocapitalize="off">
-					</div>
-					<div class="orion-reset-input-holder">
-						<input type="text" class="orion-text-input" id="resetEmail" placeholder="email">
-					</div>
-					<div class="orion-login-button-holder">
-						<input type="button" id="sendResetButton" class="orion-send-button" tabindex="0" value="Send">
-					</div>
-					<div class="orion-login-button-holder">
-						<input type="button" id="cancelResetButton" class="orion-cancel-button" tabindex="0" value="Cancel">
-					</div>
-				</form>
-			</div>
-
-			<div class="orion-open" id="orionOpen" style="visibility: visible;" tabindex="-1">
-				<div id="existingAccountLogin" class="orion-sheet-header" tabindex="-1">Have an account? Sign in:</div>
-				<div class="orion-open-images" tabindex="-1">
-					<a id="orionLogin" href="#orionLoginForm" class="loginIcon orionLoginIcon" tabindex="0">
-						Sign in with existing Orion account
-					</a>
-					<a id="googleLogin" class="loginIcon googleIcon" tabindex="0">
-						Sign in with associated Google account
-					</a>
-					<a id="personaLogin" class="loginIcon personaIcon" tabindex="0">
-						Sign in with associated Mozilla Persona account
-					</a>
+		<div class="orion-login-container" id="login-window" style="display:none;">
+			<div class="orion-landing-area" role="main">
+				<aside id="orionInfoArea" class="orion-info" style="visibility: hidden;" tabindex="0" role="complementary" aria-atomic="true" aria-live="assertive">
+						<div id="orionInfoMessage" class="orion-info-message">&nbsp;</div>
+						<div id="orionInfoLink" class="orion-info-link"><a href="/mixloginstatic/ServerStatus.html"> [more info...]</a></div>
+				</aside>
+				<div id="errorWin" class="orion-error" style="visibility: hidden;" aria-atomic="true" aria-live="assertive">
+						<div id="errorMessage">&nbsp;</div>
 				</div>
-			</div>
 
-			<div class="orion-register" id="orionRegister">
-				<div id="orion-register-header" class="orion-sheet-header">Need an account?</div>
-				<form>
-					<input id="registerButton" type="button" class="orion-register-button" value="Create a new account" tabindex="0">
-				</form>
-			</div>
+				<div class="orion-welcome-area"></div>
+				<div class="orion-login" id="orionLoginForm" style="visibility: hidden;">
+					<div id="orion-login-header" class="orion-form-header">Log in</div>
+					<form>
+						<div class="orion-input-holder">
+							<input type="text" class="orion-text-input" name="login" id="login" placeholder="username" title="Username" autocomplete="on" autofocus="autofocus" spellcheck="false" autocapitalize="off">
+						</div>
+						<div class="orion-input-holder">
+							<input name="password" type="password" id="password" class="orion-text-input" placeholder="password" title="Password">
+						</div>
+						<div class="orion-login-button-holder">
+							<input type="button" name="password" id="loginButton" class="orion-login-button" value="Sign in" tabindex="0">
+						</div>
+						<div class="orion-login-button-holder">
+							<input type="button" id="cancelLoginButton" class="orion-cancel-button" value="Cancel" tabindex="0">
+						</div>
 
+						<div class="orion-login-forgot-holder">
+							<a id="resetUserLink" class="orion-forgot-password">Forgot password?</a>
+						</div>
+					</form>
+				</div>
+
+				<div class="orion-signup" id="newUserHeaderShown" style="visibility: hidden;">
+					<div id="orion-signup-header" class="orion-form-header">Create an account</div>
+					<form>
+						<div class="orion-register-input-holder">
+							<input type="text" class="orion-text-input" placeholder="username" title="Username" autocomplete="on" autofocus="autofocus" id="create_login" spellcheck="false" autocapitalize="off">
+						</div>
+						<div class="orion-register-input-holder">
+							<input type="password" class="orion-text-input" placeholder="password" title="Password" autocomplete="on" id="create_password" aria-required="true">
+						</div>
+						<div class="orion-register-input-holder">
+							<input type="password" class="orion-text-input" placeholder="retype password" title="Retype password" autocomplete="on" name="passwordRetype" id="create_passwordRetype" aria-required="true">
+						</div>
+						<div class="orion-register-input-holder">
+							<input type="text" class="orion-text-input" placeholder="email" title="Email" autocomplete="on" name="email" id="create_email" aria-required="true">
+						</div>
+						<div class="orion-login-button-holder">
+							<input id="createButton" type="button" class="orion-login-button" value="Sign up" tabindex="0">
+						</div>
+						<div style="padding-right: 5px;"></div>
+						<div class="orion-login-button-holder">
+							<input id="hideRegisterButton" type="button" class="orion-cancel-button" value="Cancel" tabindex="0">
+						</div>
+
+					</form>
+				</div>
+				<div class="orion-signup orion-signup-linked" id="createLinkedHeaderShown" style="visibility: hidden;">
+					<div id="orion-create-linked-header" class="orion-form-header">Create a linked account</div>
+					<form>
+						<div class="orion-register-input-holder">
+							<label>Username:</label>
+							<div style="padding-right: 5px;"></div>
+							<input type="text" class="orion-text-input" placeholder="username" title="Username" autocomplete="on" autofocus="autofocus" id="create_linked_login" spellcheck="false" autocapitalize="off">
+						</div>
+						<div class="orion-register-input-holder">
+							<label>Email:</label>
+							<div style="padding-right: 5px;"></div>
+							<input type="text" class="orion-text-input" placeholder="email" title="Email" autocomplete="on" name="email" id="create_linked_email" aria-required="true">
+						</div>
+						<div class="orion-login-button-holder">
+							<input id="createLinkedButton" type="button" class="orion-login-button" value="Sign up" tabindex="0">
+						</div>
+						<div style="padding-right: 5px;"></div>
+						<div class="orion-login-button-holder">
+							<input id="hideLinkedRegisterButton" type="button" class="orion-cancel-button" value="Cancel" tabindex="0">
+						</div>
+
+					</form>
+				</div>
+				<div class="orion-reset" id="orionReset" style="visibility: hidden; height: 212px;">
+					<div id="orion-reset-header" class="orion-form-header">Reset Orion account</div>
+					<div class="orion-reset-note">Provide your username or email to reset your password.</div>
+					<form>
+						<div class="orion-reset-input-holder">
+							<input type="text" class="orion-text-input" id="reset" placeholder="username" autocapitalize="off">
+						</div>
+						<div class="orion-reset-input-holder">
+							<input type="text" class="orion-text-input" id="resetEmail" placeholder="email">
+						</div>
+						<div class="orion-login-button-holder">
+							<input type="button" id="sendResetButton" class="orion-send-button" tabindex="0" value="Send">
+						</div>
+						<div class="orion-login-button-holder">
+							<input type="button" id="cancelResetButton" class="orion-cancel-button" tabindex="0" value="Cancel">
+						</div>
+					</form>
+				</div>
+
+				<div class="orion-open" id="orionOpen" style="visibility: visible;" tabindex="-1">
+					<div id="existingAccountLogin" class="orion-sheet-header" tabindex="-1">Have an account? Sign in:</div>
+					<div class="orion-open-images" tabindex="-1">
+						<a id="orionLogin" href="#orionLoginForm" class="loginIcon orionLoginIcon" tabindex="0">
+							Sign in with existing Orion account
+						</a>
+						<a id="googleLoginPlus" class="loginIcon googleplusIcon" tabindex="0">
+							Sign in with associated Google plus account
+						</a>
+						<a id="githubLogin" class="loginIcon githubIcon" tabindex="0">
+							Sign in with associated GitHub account
+						</a>
+					</div>
+				</div>
+
+				<div class="orion-register" id="orionRegister">
+					<div id="orion-register-header" class="orion-sheet-header">Need an account?</div>
+					<form>
+						<input id="registerButton" type="button" class="orion-register-button" value="Create a new account" tabindex="0">
+					</form>
+				</div>
+
+			</div>
 		</div>
-	</div>
-</body>
+
+	</body>
 </html>
diff --git a/bundles/org.eclipse.orion.client.ui/web/mixloginstatic/LoginWindow.js b/bundles/org.eclipse.orion.client.ui/web/mixloginstatic/LoginWindow.js
index 039aff6..fba984a 100644
--- a/bundles/org.eclipse.orion.client.ui/web/mixloginstatic/LoginWindow.js
+++ b/bundles/org.eclipse.orion.client.ui/web/mixloginstatic/LoginWindow.js
@@ -11,11 +11,10 @@
 
 /*eslint-env browser, amd*/
 
-define(['domReady', 'orion/xhr', 'orion/PageUtil', 'orion/PageLinks', 'orion/webui/littlelib', 'persona/include'], function(domReady, xhr, PageUtil, PageLinks, lib) {
+define(['domReady', 'orion/xhr', 'orion/PageUtil', 'orion/PageLinks', 'orion/webui/littlelib'], function(domReady, xhr, PageUtil, PageLinks, lib) {
 	var userCreationEnabled;
 	var registrationURI;
 	var forceUserEmail;
-	var personaLoginClicked = false;
 
 	function getParam(key) {
 		var regex = new RegExp('[\\?&]' + key + '=([^&#]*)');
@@ -156,13 +155,13 @@
 
 	}
 
-	function createOpenIdLink(openid) {
-		if (openid !== "" && openid !== null) {
+	function createOAuthLink(oauth) {
+		if (oauth !== "" && oauth !== null) {
 			var redirect = getRedirect();
 			if (redirect !== null && PageUtil.validateURLScheme(decodeURIComponent(redirect))) {
-				return "../login/openid?openid=" + encodeURIComponent(openid) + "&redirect=" + redirect;
+				return "../login/oauth?oauth="+oauth+"&redirect=" + redirect;
 			} else {
-				return "../login/openid?openid=" + encodeURIComponent(openid);
+				return "../login/oauth?oauth="+oauth;
 			}
 		}
 	}
@@ -183,38 +182,6 @@
 		return outcome;
 	}
 
-	function personaLogin( event ) {
-		if( handleSelectionEvent( event ) ){
-			personaLoginClicked = true;
-			navigator.id.request();
-		}
-	}
-
-	function addPersonaHandler(button) {
-		var currentUser = null;
-		navigator.id.watch({
-			loggedInUser: currentUser,
-			onlogin: function(assertion) {
-				if (personaLoginClicked) {
-					xhr("POST", "../login/persona", {
-						headers: {
-							"Content-type": "application/x-www-form-urlencoded",
-							"Orion-Version": "1"
-						},
-						data: "assertion=" + encodeURIComponent(assertion)
-					}).then(function() {
-						finishLogin();
-					}, function(error) {
-						showErrorMessage(JSON.parse(error.responseText).error);
-					});
-				}
-			},
-			onlogout: function() {
-				// TODO
-			}
-		});
-	}
-
 	function confirmLogin(login, password) {
 		if (!login) {
 			login = document.getElementById('login').value.trim();
@@ -262,6 +229,16 @@
 		document.getElementById("registerButton").focus();
 	}
 
+	function hideLinkedRegistration() {
+		document.getElementById('createLinkedHeaderShown').style.visibility = 'hidden';
+		document.getElementById('orionOpen').style.visibility = '';
+
+		if (userCreationEnabled || registrationURI) {
+			document.getElementById('orionRegister').style.visibility = '';
+		}
+		document.getElementById("registerButton").focus();
+	}
+
 	function confirmCreateUser() {
 		if (!validatePassword()) {
 			document.getElementById("create_password").setAttribute("aria-invalid", "true");
@@ -297,6 +274,51 @@
 		mypostrequest.send(parameters);
 	}
 
+	function confirmCreateLinkedUser(){
+		var login = document.getElementById("create_linked_login").value;
+		var email =  document.getElementById("create_linked_email").value;
+		var identifier = getParam("identifier");
+		var password = generateRandomPassword();
+
+		var mypostrequest = new XMLHttpRequest();
+		mypostrequest.onreadystatechange = function() {
+			if (mypostrequest.readyState === 4) {
+				if (mypostrequest.status !== 200 && window.location.href.indexOf("http") !== -1) {
+					if (!mypostrequest.responseText) {
+						return;
+					}
+					var responseObject = JSON.parse(mypostrequest.responseText);
+					showErrorMessage(responseObject.Message);
+					if(mypostrequest.status === 201){
+						hideLinkedRegistration();
+					}
+				} else {
+					confirmLogin(login, password);
+				}
+			}
+		};
+		var parameters = "login=" + encodeURIComponent(login) + "&password=" + encodeURIComponent(password) + "&identifier=" + encodeURIComponent(identifier) + "&email=" + encodeURIComponent(email);
+		mypostrequest.open("POST", "../users", true);
+		mypostrequest.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
+		mypostrequest.setRequestHeader("Orion-Version", "1");
+		mypostrequest.send(parameters);
+	}
+
+	function generateRandomPassword() {
+		// Passwords are a mix of both alpha and non-alpha charaters
+		var aphaCharacters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
+		var nonAlphaCharacters = "0123456789";
+		var minLength = 7;
+		var password = "";
+		for(var i = 0; i < minLength; i++) {
+			password += aphaCharacters.charAt(Math.floor(Math.random() * aphaCharacters.length));
+		}
+		for(var i = 0; i < minLength; i++) {
+			password += nonAlphaCharacters.charAt(Math.floor(Math.random() * nonAlphaCharacters.length));
+		}
+		return password;
+	}
+
 	function revealRegistration( event ) {
 		// If registrationURI is set and userCreation is not, open the URI in a new window
 
@@ -317,6 +339,20 @@
 		}
 	}
 
+	function showCreateUser( email, username ) {
+		// Hide stuff
+		document.getElementById('orionOpen').style.visibility = 'hidden';
+		document.getElementById('orionRegister').style.visibility = 'hidden';
+
+		document.getElementById('orionLoginForm').style.visibility = 'hidden';
+		document.getElementById('orionRegister').style.visibility = 'hidden';
+		// Show stuff
+		document.getElementById('createLinkedHeaderShown').style.visibility = '';
+		document.getElementById('create_linked_login').focus();
+		document.getElementById('create_linked_login').value = username;
+		document.getElementById('create_linked_email').value = email;
+	}
+
 	function formatForNoUserCreation() {
 		document.getElementById('orionRegister').style.visibility = 'hidden';
 	}
@@ -359,14 +395,13 @@
 		hideErrorMessage();
 	}
 
-	function googleLogin( event ){
+	function clickElement( event ){
 		if( handleSelectionEvent( event ) ){
 			event.srcElement.click();
 		}
 	}
 
 	domReady(function() {
-		addPersonaHandler(document.getElementById("personaLogin"));
 
 		var error = getParam("error");
 		if (error) {
@@ -375,6 +410,13 @@
 			showErrorMessage(errorMessage);
 		}
 
+		var oauth = getParam("oauth");
+		if (oauth) {
+			var email = getParam("email");
+			var username = getParam("username");
+			showCreateUser(email, username);
+		}
+
 		var checkusersrequest = new XMLHttpRequest();
 		checkusersrequest.onreadystatechange = function() {
 			if (checkusersrequest.readyState === 4) {
@@ -416,7 +458,8 @@
 		checkemailrequest.send();
 
 		xhr("GET", "../server-status.json", { //$NON-NLS-0$
-			timeout: 15000
+			timeout: 15000,
+			responseType: "json"
 		}).then(function(result) {
 			var results = JSON.parse(result.response);
 			var messages = results.messages;
@@ -528,16 +571,20 @@
 
 		document.getElementById("hideRegisterButton").addEventListener("click", hideRegistration);
 
+		document.getElementById("createLinkedButton").addEventListener("click", confirmCreateLinkedUser);
+		document.getElementById("hideLinkedRegisterButton").addEventListener("click", hideLinkedRegistration);
+
+
 		// FIX the hrefs of the various forms here.
-		document.getElementById("googleLogin").href = createOpenIdLink("https://www.google.com/accounts/o8/id");
-		document.getElementById("googleLogin").addEventListener("keydown", googleLogin);
+		document.getElementById("googleLoginPlus").href = createOAuthLink("google");
+		document.getElementById("googleLoginPlus").addEventListener("keydown", clickElement);
+
+		document.getElementById("githubLogin").href = createOAuthLink("github");
+		document.getElementById("githubLogin").addEventListener("keydown", clickElement);
 
 		document.getElementById("orionLogin").addEventListener("click", revealLogin);
 		document.getElementById("orionLogin").onkeydown = revealLogin;
 
-		document.getElementById("personaLogin").onclick = personaLogin;
-		document.getElementById("personaLogin").onkeydown = personaLogin;
-
 		document.getElementById("cancelResetButton").onclick = hideResetUser;
 
 		document.getElementById("sendResetButton").onclick = confirmResetUser;
diff --git a/bundles/org.eclipse.orion.client.ui/web/mixloginstatic/css/landing.css b/bundles/org.eclipse.orion.client.ui/web/mixloginstatic/css/landing.css
index d755848..e8274f1 100644
--- a/bundles/org.eclipse.orion.client.ui/web/mixloginstatic/css/landing.css
+++ b/bundles/org.eclipse.orion.client.ui/web/mixloginstatic/css/landing.css
@@ -1,23 +1,24 @@
 body {
-	font: 14px/18px 'Lucida Sans Unicode', 'Lucida Grande', "HelveticaNeue","Helvetica Neue",Helvetica,Arial,sans-serif;
+	font: 14px/18px 'Lucida Sans Unicode', 'Lucida Grande', "HelveticaNeue",
+		"Helvetica Neue", Helvetica, Arial, sans-serif;
 	color: #333;
-	background:#fafafa;
+	background: #fafafa;
 	clear: both;
-	overflow:hidden;
-	cursor:default;
+	overflow: hidden;
+	cursor: default;
 }
 
 /*Remove button padding in FF*/
 input::-moz-focus-inner {
-    border: 0;
-    padding: 0;
+	border: 0;
+	padding: 0;
 }
 
 input[type="button"]:active {
 	padding: 0;
 }
 
-.orion-banner{
+.orion-banner {
 	margin: 0;
 	height: 100px;
 	padding-top: 2px;
@@ -25,17 +26,20 @@
 	padding-left: 8px;
 	padding-right: 8px;
 	vertical-align: baseline;
-	position:absolute;
-	width:100%;
+	position: absolute;
+	width: 100%;
 	background: #444;
 	background: -moz-linear-gradient(top, #444 0%, black 100%);
-	background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#555), color-stop(100%,black));
-	background: -webkit-linear-gradient(top, #444 0%,black 100%);
-	background: -o-linear-gradient(top, #444 0%,black 100%);
-	background: -ms-linear-gradient(top, #444 0%,black 100%); /* IE10+ */
-	background: linear-gradient(to bottom, #444 0%,black 100%);
-	-ms-filter: "progid:DXImageTransform.Microsoft.gradient(GradientType=0, startColorStr='#444444', EndColorStr='black')"; /* IE9 */
-	-moz-box-shadow: 0 2px 15px rgba(0,0,0,0.25);
+	background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #555),
+		color-stop(100%, black));
+	background: -webkit-linear-gradient(top, #444 0%, black 100%);
+	background: -o-linear-gradient(top, #444 0%, black 100%);
+	background: -ms-linear-gradient(top, #444 0%, black 100%); /* IE10+ */
+	background: linear-gradient(to bottom, #444 0%, black 100%);
+	-ms-filter:
+		"progid:DXImageTransform.Microsoft.gradient(GradientType=0, startColorStr='#444444', EndColorStr='black')";
+	/* IE9 */
+	-moz-box-shadow: 0 2px 15px rgba(0, 0, 0, 0.25);
 	box-shadow: 0 4px 15px rgba(0, 0, 0, 0.3);
 	-webkit-transition: box-shadow 0.2s linear;
 	-moz-transition: box-shadow 0.2s linear;
@@ -45,19 +49,16 @@
 	border-bottom: 1px solid #222;
 }
 
-
-
-.orion-twitter-link{
+.orion-twitter-link {
 	background: url('combined.png');
-	height:16px;
-	width:20px;
-	float:right;
-	margin-right:20px;
-	margin-top:65px;
+	height: 16px;
+	width: 20px;
+	float: right;
+	margin-right: 20px;
+	margin-top: 65px;
 	background-position: 0 -362px;
 }
 
-
 .orion-nav-bar {
 	padding-top: 7px;
 	padding-right: 5px;
@@ -66,52 +67,51 @@
 	width: 800px;
 }
 
-.orion-logo{
+.orion-logo {
 	background: url('combined.png');
 	background-position: 0 -160px;
-	float:left;
-	height:86px;
-	width:114px;
+	float: left;
+	height: 86px;
+	width: 114px;
 }
 
-.orion-rss-link{
+.orion-rss-link {
 	background: url('combined.png') no-repeat;
-	height:16px;
-	width:20px;
-	float:right;
+	height: 16px;
+	width: 20px;
+	float: right;
 	/* margin-right:20px; */
-	margin-top:65px;
+	margin-top: 65px;
 	background-position: 0 -296px;
 }
 
-
-.orion-slogan{
-	width:412px;
-	float:right;
-	text-transform:lowercase;
-	padding-top:20px;
+.orion-slogan {
+	width: 412px;
+	float: right;
+	text-transform: lowercase;
+	padding-top: 20px;
 }
 
-.orion-slogan-highlight{
-	color:#ffc000;
-	font-size:30px;
-	color:#222;
-	font-size:20px;
+.orion-slogan-highlight {
+	color: #ffc000;
+	font-size: 30px;
+	color: #222;
+	font-size: 20px;
 	font-weight: bold;
-	line-height:26px;
-	display:inline;
-	font-weight:bold;
-	margin-right:3px;
+	line-height: 26px;
+	display: inline;
+	font-weight: bold;
+	margin-right: 3px;
 }
 
-.orion-slogan-lowlight{
-	font-size:35px;
+.orion-slogan-lowlight {
+	font-size: 35px;
 	font-weight: normal;
-	font-size:20px;
-	line-height:35px;
-	color:#FFC000;
-	display:inline;
-	font-weight:bold;
+	font-size: 20px;
+	line-height: 35px;
+	color: #FFC000;
+	display: inline;
+	font-weight: bold;
 }
 
 .orion-welcome-area {
@@ -126,24 +126,24 @@
 }
 
 .orion-welcome-area-text {
-	font-size:12px;
+	font-size: 12px;
 	position: absolute;
 	background: white;
-	opacity:0.8;
-	height:108px;
-	width:480px;
-	top:180px;
-	padding:20px;
+	opacity: 0.8;
+	height: 108px;
+	width: 480px;
+	top: 180px;
+	padding: 20px;
 }
 
 .orion-welcome-area-text-content {
 	background: white;
-	font-size:12px;
-	opacity:1;
-	width:100%;
-	width:480px;
-	color:black;
-	font-weight:bold;
+	font-size: 12px;
+	opacity: 1;
+	width: 100%;
+	width: 480px;
+	color: black;
+	font-weight: bold;
 }
 
 .orion-landing-area {
@@ -154,10 +154,10 @@
 	height: 328px;
 	width: 838px;
 	margin: -154px 0 0 -450px;
-	min-height:400px;
+	min-height: 400px;
 }
 
-.orion-login,.orion-signup, .orion-reset, .orion-error, .orion-info {
+.orion-login, .orion-signup, .orion-reset, .orion-error, .orion-info {
 	border-radius: 4px;
 	border: solid 1px #DDD;
 }
@@ -170,7 +170,7 @@
 	height: 101px;
 }
 
-.orion-login{
+.orion-login {
 	position: absolute;
 	top: 0;
 	left: 536px;
@@ -178,7 +178,7 @@
 	height: 150px;
 }
 
-.orion-signup, .orion-reset  {
+.orion-signup, .orion-reset {
 	position: absolute;
 	top: 0;
 	left: 536px;
@@ -186,34 +186,42 @@
 	height: 270px;
 }
 
+.orion-signup-linked {
+	position: absolute;
+	top: 0;
+	left: 536px;
+	width: 300px;
+	height: 210px;
+}
+
 .orion-login, .orion-signup, .orion-reset {
 	background: white;
 	/* box-shadow: 0 1px 0 rgba(0,0,0,.1); */
-	padding:10px;
+	padding: 10px;
 }
 
 .orion-form-header, .orion-sheet-header {
 	font-weight: bold;
-	font-size:15px;
+	font-size: 15px;
 	padding-bottom: 10px;
 }
 
 .orion-form-header {
-	margin-bottom:5px;
+	margin-bottom: 5px;
 	border-bottom: solid 1px #EEE;
-	color:#666;
+	color: #666;
 }
 
-.orion-register-header{
+.orion-register-header {
 	font-weight: bold;
-	font-size:15px;
-	float:left;
-	margin-bottom:5px;
-	color:#666;
+	font-size: 15px;
+	float: left;
+	margin-bottom: 5px;
+	color: #666;
 	vertical-align: 8px;
 	padding-right: 20px;
 	padding-bottom: 10px;
-	display:inline;
+	display: inline;
 	/* border-bottom: solid 1px #EEE; */
 }
 
@@ -226,14 +234,15 @@
 	width: 100%;
 	padding: 4px;
 	margin: 0;
-	margin-top:5px;
+	margin-top: 5px;
 	outline: none;
 	background-color: white;
 	border: none;
 	border-radius: 3px;
-	font-family: Verdana, Arial, Helvetica, Myriad, Tahoma, clean, sans-serif;
+	font-family: Verdana, Arial, Helvetica, Myriad, Tahoma, clean,
+		sans-serif;
 	font-size: 14px;
-	color:#999;
+	color: #999;
 }
 
 .orion-input-holder {
@@ -242,7 +251,6 @@
 	border-bottom: dashed 1px #DDD;
 }
 
-
 .orion-register-input-holder, .orion-reset-input-holder {
 	padding-bottom: 5px;
 	margin-bottom: 15px;
@@ -250,85 +258,86 @@
 }
 
 .orion-login-button-holder {
-	padding:0;
-	padding-top:1px;
-	float:right;
+	padding: 0;
+	padding-top: 1px;
+	float: right;
 }
 
 .orion-login-forgot-holder {
-	padding-top:10px;
-	padding-left:5px;
-	float:left;
+	padding-top: 10px;
+	padding-left: 5px;
+	float: left;
 }
 
 .orion-login-button, .orion-send-button {
-	background:#ffc000;
-	border-radius:4px;
-	height:30px;
-	width:80px;
+	background: #ffc000;
+	border-radius: 4px;
+	height: 30px;
+	width: 80px;
 	border: solid 1px #CCC;
-	color:#666;
-	font-size:12px;
-	font-weight:bold;
+	color: #666;
+	font-size: 12px;
+	font-weight: bold;
 	margin-left: 5px;
-	cursor:pointer;
+	cursor: pointer;
 }
 
 .orion-login-button:hover, .orion-send-button:hover {
-	background:white;
-	color:#ffc000;
+	background: white;
+	color: #ffc000;
 }
 
 .orion-register-button {
-	background:#444;
-	border-radius:4px;
-	height:50px;
-	width:150px;
+	background: #444;
+	border-radius: 4px;
+	height: 50px;
+	width: 150px;
 	border: solid 1px #CCC;
-	color:white;
-	font-size:12px;
-	font-weight:bold;
+	color: white;
+	font-size: 12px;
+	font-weight: bold;
 	/* margin-left: 10px; */
 }
 
 .orion-register-button:hover {
-	opacity:.6;
+	background: white;
+	color: #666;
 }
 
 .orion-cancel-button {
-	background:white;
-	border-radius:4px;
-	height:30px;
-	width:80px;
+	background: white;
+	border-radius: 4px;
+	height: 30px;
+	width: 80px;
 	border: solid 1px #CCC;
-	color:#666;
-	font-size:12px;
-	font-weight:bold;
+	color: #666;
+	font-size: 12px;
+	font-weight: bold;
 }
 
-.orion-cancel-button:hover{
-	background:#666;
-	color:white;
+.orion-cancel-button:hover {
+	background: #666;
+	color: white;
 }
 
 .orion-or-div {
-	margin:17px;
-	top:10px;
-	height:30px;
-	vertical-align:middle;
-	display:inline;
-	line-height:33px;
+	margin: 17px;
+	top: 10px;
+	height: 30px;
+	vertical-align: middle;
+	display: inline;
+	line-height: 33px;
 }
 
-.orion-forgot-password{
+.orion-forgot-password {
 	font-size: 9pt;
-	color:#999;
-	margin-top:15px;
+	color: #999;
+	margin-top: 15px;
 	cursor: pointer;
 	text-decoration: underline;
 }
 
-.orion-forgot-password:hover{
+.orion-forgot-password:hover {
 	color: #333;
 	text-decoration: none;
 }
@@ -337,7 +346,7 @@
 	position: absolute;
 	top: 0;
 	left: 536px;
-	width: 300px;
+	width: 320px;
 	height: 150px;
 }
 
@@ -349,32 +358,32 @@
 	height: 35px;
 }
 
-.orion-open-images{
-	padding-top:5px;
-	display:inline;
+.orion-open-images {
+	padding-top: 5px;
+	display: inline;
 }
 
-.orion-error{
+.orion-error {
 	color: #B94A48;
 	background-color: #F2DEDE;
 	border-color: #EED3D7;
 	width: 852px;
-	margin-right:0;
+	margin-right: 0;
 	position: absolute;
 	top: 345px;
-	padding:5px;
-	padding-right:0;
+	padding: 5px;
+	padding-right: 0;
 }
 
 .orion-info {
 	color: #333;
 	background-color: white;
 	width: 852px;
-	margin-right:0;
+	margin-right: 0;
 	position: absolute;
 	top: 390px;
 	padding: 5px;
-	padding-right:0;
+	padding-right: 0;
 }
 
 .orion-info-link {
@@ -383,7 +392,7 @@
 	text-decoration: underline;
 }
 
-.orion-info-link:hover{
+.orion-info-link:hover {
 	color: #333;
 	text-decoration: underline;
 }
@@ -409,33 +418,19 @@
 	border-radius: 4px;
 	border: solid 1px #CCC;
 	background: white;
-	box-shadow: 0 1px 0 rgba(0,0,0,.1);
+	box-shadow: 0 1px 0 rgba(0, 0, 0, .1);
 }
 
-.personaIcon{
-	background: url('../images/persona.png') no-repeat;
-	/* background-position: 0 -809px; */
-	width: 70px;
-	height: 50px;
-	/* margin-top: 6px; */
-	opacity:1;
-	margin-left:10px;
-}
-
-.personaIcon:hover{
-	opacity:0.6;
-}
-
-.openIdIcon{
+.openIdIcon {
 	background: url('../images/openid.png') no-repeat;
 	/* background-position: 0 -80px; */
 	width: 50px;
 	height: 50px;
 	/* margin-top:2px; */
-	margin-left:10px;
+	margin-left: 10px;
 }
 
-.orionLoginIcon{
+.orionLoginIcon {
 	background: url('../images/oriongrey.png') no-repeat;
 	/* background-position: 0 -80px; */
 	width: 50px;
@@ -444,19 +439,19 @@
 	/* margin-left:10px; */
 }
 
-.orionLoginIcon:hover{
-	opacity:0.6;
+.orionLoginIcon:hover {
+	opacity: 0.6;
 }
 
-.orIcon{
-	border:#DDD;
-	border-radius:4px;
+.orIcon {
+	border: #DDD;
+	border-radius: 4px;
 	width: 50px;
 	height: 50px;
 	margin-left: 7px;
 }
 
-.googleIcon{
+.googleplusIcon {
 	background: url('../images/google.png') no-repeat;
 	background-position: 0 0;
 	width: 50px;
@@ -465,10 +460,20 @@
 	/* margin-top: 3px; */
 }
 
-.googleIcon:hover{
-	opacity:.6;
+.githubIcon {
+	background: url('../images/GitHub-Mark-Light-32px.png') no-repeat;
+	background-position: center;
+	background-color: #414142;
+	width: 50px;
+	height: 50px;
+	float: left;
+	margin-left: 10px;
+	border-radius: 2px;
 }
 
+.loginIcon:hover {
+	opacity: .6;
+}
 
 .openSignIn {
 	height: 23px;
@@ -480,10 +485,11 @@
 	border-radius: 4px;
 }
 
-.loginIcon{
-	float:left;
+.loginIcon {
+	float: left;
 	/* hide text */
 	text-indent: 100%;
 	white-space: nowrap;
 	overflow: hidden;
-}
\ No newline at end of file
+	cursor: pointer;
+}
diff --git a/bundles/org.eclipse.orion.client.ui/web/mixloginstatic/css/manageExternalIds.css b/bundles/org.eclipse.orion.client.ui/web/mixloginstatic/css/manageExternalIds.css
new file mode 100644
index 0000000..6d29dc5
--- /dev/null
+++ b/bundles/org.eclipse.orion.client.ui/web/mixloginstatic/css/manageExternalIds.css
@@ -0,0 +1,105 @@
+@CHARSET "UTF-8";
+
+html, body {
+	margin: 0;
+	padding: 0;
+	font: 9pt Arial, Helvetica, Myriad, Tahoma, clean, sans-serif;
+}
+
+h2 {
+	font-size: 1.1em;
+	font-weight: bold;
+	color: #6d6d6d;
+	margin-top: 4px;
+	margin-bottom: 4px;
+}
+
+a {
+	cursor: hand;
+	text-decoration: none;
+	color: #024892;
+}
+
+a:visited {
+	color: #024892;
+}
+
+a:active {
+	color: #024892;
+}
+
+a:hover {
+	cursor: hand;
+	text-decoration: underline;
+	color: #024892;
+}
+
+img.loginWindow {
+	height: 32px;
+	border: 0px;
+	margin-left: 5px;
+	margin-right: 5px;
+}
+
+.secondaryColumn {
+	color: #666666;
+}
+
+.manageExternalIdsTable {
+	border-spacing: 0;
+}
+
+.manageExternalIdRow .removeExternalId {
+	cursor: pointer;
+	visibility: hidden;
+}
+
+.manageExternalIdRow:hover .removeExternalId {
+	visibility: visible !important;
+}
+
+.lightTreeTableRow {
+	background-color: #FFFFFF;
+}
+
+.darkTreeTableRow {
+	background-color: #f7f7f7;
+}
+
+.navTableHeading {
+	color: #404040;
+	border-bottom: 1px solid #404040;
+}
+
+.navColumn {
+	min-width: 150px;
+}
+
+a.loginWindow {
+	display: inline-block;
+	cursor: pointer;
+}
+
+a.loginWindow:hover {
+	opacity: .6;
+}
+
+a.loginWindow.githubImage {
+	height: 32px;
+	width: 32px;
+	background-color: #414142;
+	float: left;
+	margin-left: 5px;
+	margin-right: 5px;
+	border-radius: 1px;
+}
+
+img.loginWindow.githubImage {
+	height: 20px;
+	width: 20px;
+	position: relative;
+	top: 6px;
+	left: 6px;
+	margin-left: 0px;
+	margin-right: 0px;
+}
\ No newline at end of file
diff --git a/bundles/org.eclipse.orion.client.ui/web/mixloginstatic/css/manageOpenids.css b/bundles/org.eclipse.orion.client.ui/web/mixloginstatic/css/manageOpenids.css
deleted file mode 100644
index 5d25a7b..0000000
--- a/bundles/org.eclipse.orion.client.ui/web/mixloginstatic/css/manageOpenids.css
+++ /dev/null
@@ -1,80 +0,0 @@
-@CHARSET "UTF-8";

-

-html, body {

-	margin: 0;

-	padding: 0;

-	font: 9pt Arial,Helvetica,Myriad,Tahoma,clean,sans-serif; 

-}

-

-h2 {

-	font-size: 1.1em;

-	font-weight: bold;

-	color: #6d6d6d;

-	margin-top: 4px;

-	margin-bottom: 4px;

-}

-

-a {

-	cursor: hand;

-	text-decoration: none;

-	color: #024892;

-}

-

-a:visited {

-	color: #024892;

-}

-

-a:active {

-	color: #024892;

-}

-

-a:hover {

-	cursor: hand;

-	text-decoration: underline;

-	color: #024892;

-}

-

-img.loginWindow{

-	height: 30px;

-	border: 0px;

-	margin-left: 5px;

-	margin-right: 5px;

-}

-

-.secondaryColumn {

-	color: #666666;	

-}

-

-.manageOpenIdsTable{

-	border-spacing: 0;

-}

-

-.manageOpenIdRow .removeOpenId {

-	cursor: pointer;

-	visibility: hidden;

-}

-

-.manageOpenIdRow:hover .removeOpenId {

-	visibility: visible !important;

-}

-

-/*.removeOpenId {

-	cursor: pointer;

-}*/

-

-.lightTreeTableRow {

-	background-color: #FFFFFF;

-}

-

-.darkTreeTableRow {

-	background-color: #f7f7f7;

-}

-

-.navTableHeading {

-	color: #404040;

-	border-bottom: 1px solid #404040;

-}

-

-.navColumn {

-	min-width: 150px;

-}

diff --git a/bundles/org.eclipse.orion.client.ui/web/mixloginstatic/images/GitHub-Mark-Light-32px.png b/bundles/org.eclipse.orion.client.ui/web/mixloginstatic/images/GitHub-Mark-Light-32px.png
new file mode 100644
index 0000000..628da97
--- /dev/null
+++ b/bundles/org.eclipse.orion.client.ui/web/mixloginstatic/images/GitHub-Mark-Light-32px.png
Binary files differ
diff --git a/bundles/org.eclipse.orion.client.ui/web/mixloginstatic/manageOpenids.html b/bundles/org.eclipse.orion.client.ui/web/mixloginstatic/manageExternalIds.html
similarity index 66%
rename from bundles/org.eclipse.orion.client.ui/web/mixloginstatic/manageOpenids.html
rename to bundles/org.eclipse.orion.client.ui/web/mixloginstatic/manageExternalIds.html
index b729d2f..bdb1378 100644
--- a/bundles/org.eclipse.orion.client.ui/web/mixloginstatic/manageOpenids.html
+++ b/bundles/org.eclipse.orion.client.ui/web/mixloginstatic/manageExternalIds.html
@@ -2,13 +2,13 @@
 <html>
 	<head>
 		<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
-		<link rel="stylesheet" type="text/css" href="css/manageOpenids.css" />
+		<link rel="stylesheet" type="text/css" href="css/manageExternalIds.css" />
 		<script src="../requirejs/require.js"></script>
 		<script>
 		/*eslint-env browser, amd*/
 		require({
 		  baseUrl: '..',
-		
+
 		  // set the paths to our library packages
 		  packages: [],
 		  paths: {
@@ -17,13 +17,13 @@
 			  domReady: 'requirejs/domReady'
 		  }
 		});
-		
-		require(["mixloginstatic/manageOpenids"]);
+
+		require(["mixloginstatic/manageExternalIds"]);
 		</script>
 	</head>
-<body>
-	<div id="newOpenId">
-	</div>
-	<div id="openidList"></div>
-</body>
+	<body>
+		<div id="newExternalId">
+		</div>
+		<div id="externalIdList"></div>
+	</body>
 </html>
\ No newline at end of file
diff --git a/bundles/org.eclipse.orion.client.ui/web/mixloginstatic/manageExternalIds.js b/bundles/org.eclipse.orion.client.ui/web/mixloginstatic/manageExternalIds.js
new file mode 100644
index 0000000..529aa4b
--- /dev/null
+++ b/bundles/org.eclipse.orion.client.ui/web/mixloginstatic/manageExternalIds.js
@@ -0,0 +1,250 @@
+/*******************************************************************************
+ * @license
+ * Copyright (c) 2012 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials are made 
+ * available under the terms of the Eclipse Public License v1.0 
+ * (http://www.eclipse.org/legal/epl-v10.html), and the Eclipse Distribution 
+ * License v1.0 (http://www.eclipse.org/org/documents/edl-v10.html). 
+ * 
+ * Contributors: IBM Corporation - initial API and implementation
+ ******************************************************************************/
+/*eslint-env browser, amd*/
+/*global confirm*/
+define(["i18n!orion/mixloginstatic/nls/messages", "orion/xhr", "orion/webui/littlelib", "domReady!"], function(messages, xhr, lib) {
+	var lastHash;
+	var jsonData;
+
+	var loadAttachedExternalIds, loadUserData;
+
+	function removeOpenId(openid) {
+		if (confirm("Are you sure you want to remove " + openid + " from the list of your external accounts?")) {
+			var openids = jsonData.properties.openid.split('\n');
+			var newopenids = [];
+			for (var i = 0; i < openids.length; i++) {
+				if (openids[i] !== openid) {
+					newopenids.push(openids[i]);
+				}
+			}
+			jsonData.properties.openid = newopenids.join("\n");
+
+			xhr("PUT", jsonData.Location, { //$NON-NLS-0$
+				data: JSON.stringify(jsonData),
+				headers: {
+					"Orion-Version": "1"
+				},
+				timeout: 15000
+			}).then(function(xhrResult) {
+				loadUserData(jsonData.Location);
+			}, function(xhrResult) {
+				console.error(xhrResult.error);
+			});
+		}
+	}
+	function removeOAuth(oauth) {
+		if (confirm("Are you sure you want to remove " + oauth + " from the list of your external accounts?")) {
+			var oauths = jsonData.properties.oauth.split('\n');
+			var newoauths = "";
+			for (var i = 0; i < oauths.length; i++) {
+				if (oauths[i] !== oauth) {
+					newoauths += (oauths[i] + '\n');
+				}
+			}
+			jsonData.properties.oauth = newoauths;
+
+			xhr("PUT", jsonData.Location, { //$NON-NLS-0$
+				data: JSON.stringify(jsonData),
+				headers: {
+					"Orion-Version": "1"
+				},
+				timeout: 15000
+			}).then(function(xhrResult) {
+				loadUserData(jsonData.Location);
+			}, function(xhrResult) {
+				console.error(xhrResult.error);
+			});
+		}
+	}
+
+	loadAttachedExternalIds = function(userjsonData) {
+		jsonData = userjsonData;
+		var list = lib.node("externalIdList"); //$NON-NLS-0$
+		if (list.childNodes.length) {
+			/* there's already a table that is now to be replaced */
+			list.removeChild(list.childNodes[0]);
+		}
+		var table = document.createElement("table"); //$NON-NLS-0$
+		table.classList.add("manageExternalIdsTable"); //$NON-NLS-0$
+		list.appendChild(table); //$NON-NLS-0$
+		if (jsonData.properties && (jsonData.properties.openid || jsonData.properties.oauth)) {
+
+			var openids = jsonData.properties.openid ? jsonData.properties.openid.split('\n') : []; //$NON-NLS-0$
+			var oauths = jsonData.properties.oauth ? jsonData.properties.oauth.split('\n') : []; //$NON-NLS-0$
+			for (var i = openids.length - 1; i >= 0; i--) {
+				if (openids[i] === "") {
+					openids.splice(i, 1);
+				}
+			}
+			for (var i = oauths.length - 1; i >= 0; i--) {
+				if (oauths[i] === "") {
+					oauths.splice(i, 1);
+				}
+			}
+
+			if (openids.length || oauths.length) {
+				var thead = document.createElement("thead"); //$NON-NLS-0$
+				thead.classList.add("navTableHeading"); //$NON-NLS-0$
+				table.appendChild(thead);
+
+				var tr = document.createElement("tr"); //$NON-NLS-0$
+				thead.appendChild(tr);
+				var td = document.createElement("td"); //$NON-NLS-0$
+				td.classList.add("navColumn"); //$NON-NLS-0$
+				td.innerHTML = "<h2>External Id</h2>"; //$NON-NLS-0$
+				tr.appendChild(td);
+			}
+
+			for (var i = 0; i < openids.length; i++) {
+				var openid = openids[i];
+				addAuthenticationEntry(openid, i, table, removeOpenId);
+			}
+			for (var i = 0; i < oauths.length; i++) {
+				var oauth = oauths[i];
+				addAuthenticationEntry(oauth, i, table, removeOAuth);
+			}
+		}
+	};
+
+	function addAuthenticationEntry(externalId, i, table, removeFunction){
+		var tr = document.createElement("tr"); //$NON-NLS-0$
+		tr.classList.add(i % 2 === 0 ? "lightTreeTableRow" : "darkTreeTableRow");  //$NON-NLS-1$ //$NON-NLS-0$
+		tr.classList.add("manageExternalIdRow"); //$NON-NLS-0$
+		tr.style.verticalAlign = "baseline"; //$NON-NLS-0$
+		table.appendChild(tr);
+
+		var td = document.createElement("td"); //$NON-NLS-0$
+		td.classList.add("navColumn"); //$NON-NLS-0$
+		tr.appendChild(td);
+		var span = document.createElement("span"); //$NON-NLS-0$
+		span.title = externalId;
+		td.appendChild(span);
+		var textNode = document.createTextNode(externalId.length > 70 ? (externalId.substring(0, 65) + "...") : externalId);
+		span.appendChild(textNode);
+
+		td = document.createElement("td"); //$NON-NLS-0$
+		td.classList.add("navColumn"); //$NON-NLS-0$
+		tr.appendChild(td);
+		var removeLink = document.createElement("a"); //$NON-NLS-0$
+		removeLink.classList.add("removeExternalId"); //$NON-NLS-0$
+		removeLink.id = "remlink" + i; //$NON-NLS-0$
+		removeLink.innerHTML = "Remove";
+		removeLink.style.visibility = "hidden"; //$NON-NLS-0$
+		removeLink.title = "Remove " + externalId;
+		td.appendChild(removeLink);
+
+		removeLink.addEventListener("click", function(externalId) { //$NON-NLS-0$
+			removeFunction(externalId);
+		}.bind(this, externalId));
+	}
+
+	loadUserData = function(userLocation){
+		xhr("GET", userLocation, { //$NON-NLS-0$
+			headers : {
+				"Orion-Version" : "1"
+			},
+			timeout : 15000
+		}).then(function(xhrResult) {
+			loadAttachedExternalIds(JSON.parse(xhrResult.response));
+		}, function(xhrResult) {
+			console.error(xhrResult.error);
+		});
+	};
+
+	function onHashChange(hash) {
+		if (lastHash === hash) {
+			return;
+		}
+
+		loadUserData(hash);
+
+		lastHash = hash;
+	}
+
+	window.handleOAuthResponse = function(oauthid) {
+		var oauthids = jsonData.properties.oauth ? jsonData.properties.oauth.split('\n') : [];
+		for (var i = 0; i < oauthids.length; i++) {
+			if (oauthids[i] === oauthid) {
+				return;
+			}
+		}
+
+		if (!jsonData.properties.oauth) {
+			jsonData.properties.oauth = oauthid;
+		} else {
+			jsonData.properties.oauth += '\n' + oauthid;
+		}
+
+		xhr("PUT", jsonData.Location, { //$NON-NLS-0$
+			data: JSON.stringify(jsonData),
+			headers: {
+				"Orion-Version": "1"
+			},
+			timeout: 15000
+		}).then(function(xhrResult) {
+			loadUserData(jsonData.Location);
+		}, function(xhrResult) {
+			console.error(xhrResult.error);
+		});
+	};
+
+	function confirmOAuth(oauth) {
+		if (oauth !== "" && oauth !== null) {
+			window.open("../mixlogin/manageoauth/oauth?oauth=" + encodeURIComponent(oauth), "oauth_popup", "width=790,height=580");
+		}
+	}
+
+	function createProviderLink(name, imageUrl, clazz, onclick) {
+		var img = document.createElement("img");
+		img.className = "loginWindow " + clazz;
+		img.id = img.alt = img.title = name;
+		img.src = imageUrl;
+
+		var a = document.createElement("a");
+		a.className = "loginWindow " + clazz;
+		a.onclick = onclick;
+		a.setAttribute("aria-labelledby", "addExternalAccount " + name);
+		a.appendChild(img);
+		return a;
+	}
+
+	function attachExternalAccountsHeader(){
+		var externalIdContainer = document.getElementById("newExternalId");
+		var h2 = document.createElement("h2"); //$NON-NLS-0$
+		h2.style.margin = "10px 5px 10px 0"; //$NON-NLS-0$
+		h2.style.cssFloat = "left";//$NON-NLS-0$
+		h2.id = "addExternalAccount";//$NON-NLS-0$
+		h2.innerHTML = messages["AddExternalAccount"];//$NON-NLS-0$
+		externalIdContainer.appendChild(h2);
+	}
+
+	function attachExternalProviders(){
+		var providerElements = [];
+		// Add OAuth Providers
+		providerElements.push(createProviderLink("Google OAuth", "../mixloginstatic/images/google.png", "", confirmOAuth.bind(null, "google")));
+		providerElements.push(createProviderLink("GitHub OAuth", "../mixloginstatic/images/GitHub-Mark-Light-32px.png", "githubImage", confirmOAuth.bind(null, "github")));
+
+		var openIdContainer = document.getElementById("newExternalId");
+		providerElements.forEach(function(provider) {
+			openIdContainer.appendChild(provider);
+			openIdContainer.appendChild(document.createTextNode(" "));
+		});
+	}
+
+	// Page glue code starts here
+	window.addEventListener("hashchange", function() {
+		onHashChange(window.location.hash.substring(1));
+	});
+
+	onHashChange(window.location.hash.substring(1));
+	attachExternalAccountsHeader();
+	attachExternalProviders();
+});
diff --git a/bundles/org.eclipse.orion.client.ui/web/mixloginstatic/manageOpenids.js b/bundles/org.eclipse.orion.client.ui/web/mixloginstatic/manageOpenids.js
deleted file mode 100644
index bb628c1..0000000
--- a/bundles/org.eclipse.orion.client.ui/web/mixloginstatic/manageOpenids.js
+++ /dev/null
@@ -1,225 +0,0 @@
-/*******************************************************************************
- * @license
- * Copyright (c) 2012, 2014 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials are made 
- * available under the terms of the Eclipse Public License v1.0 
- * (http://www.eclipse.org/legal/epl-v10.html), and the Eclipse Distribution 
- * License v1.0 (http://www.eclipse.org/org/documents/edl-v10.html). 
- * 
- * Contributors: IBM Corporation - initial API and implementation
- ******************************************************************************/
-/*eslint-env browser, amd*/
-/*global confirm*/
-define([
-	"i18n!orion/mixloginstatic/nls/messages",
-	"orion/bootstrap",
-	"orion/xhr",
-	'orion/i18nUtil',
-	"orion/webui/littlelib",
-	"domReady!"
-], function(messages, mBootstrap, xhr, i18nUtil, lib) {
-	var lastHash;
-	var jsonData;
-
-	var loadAttachedOpenIds, loadUserData;
-
-	function removeOpenId(openid) {
-		if (confirm(i18nUtil.formatMessage(messages['ConfirmRemove'], [openid]))) {
-			var openids = jsonData.properties.openid.split('\n'); //$NON-NLS-0$
-			var newopenids = "";
-			for (var i = 0; i < openids.length; i++) {
-				if (openids[i] !== openid) {
-					newopenids += (openids[i] + '\n'); //$NON-NLS-0$
-				}
-			}
-			jsonData.properties.openid = newopenids;
-
-			xhr("PUT", jsonData.Location, { //$NON-NLS-0$
-				data: JSON.stringify(jsonData),
-				headers: {
-					"Orion-Version": "1"  //$NON-NLS-0$ //$NON-NLS-1$
-				},
-				timeout: 15000
-			}).then(function(xhrResult) {
-				loadUserData(jsonData.Location);
-			}, function(xhrResult) {
-				console.error(xhrResult.error);
-			});
-		}
-	}
-	
-	loadAttachedOpenIds = function(userjsonData) {
-		jsonData = userjsonData;
-		var list = lib.node("openidList"); //$NON-NLS-0$
-		if (list.childNodes.length) {
-			/* there's already a table that is now to be replaced */
-			list.removeChild(list.childNodes[0]);
-		}
-		var table = document.createElement("table"); //$NON-NLS-0$
-		table.classList.add("manageOpenIdsTable"); //$NON-NLS-0$
-		list.appendChild(table); //$NON-NLS-0$
-		if (jsonData.properties && jsonData.properties.openid) {
-	
-			var openids = jsonData.properties.openid ? jsonData.properties.openid.split('\n') : []; //$NON-NLS-0$
-			for (var i = openids.length - 1; i >= 0; i--) {
-				if (openids[i] === "") {
-					openids.splice(i, 1);
-				}
-			}
-			
-			var td, tr;
-			if (openids.length) {
-				var thead = document.createElement("thead"); //$NON-NLS-0$
-				thead.classList.add("navTableHeading"); //$NON-NLS-0$
-				table.appendChild(thead);
-
-				tr = document.createElement("tr"); //$NON-NLS-0$
-				thead.appendChild(tr);
-				td = document.createElement("td"); //$NON-NLS-0$
-				td.classList.add("navColumn"); //$NON-NLS-0$
-				td.innerHTML = "<h2>" + messages['ExternalAccounts'] + "</h2>";  //$NON-NLS-0$  //$NON-NLS-1$
-				tr.appendChild(td);
-			}
-
-			for (var j = 0; j < openids.length; j++) {
-				var openid = openids[j];
-				tr = document.createElement("tr"); //$NON-NLS-0$
-				tr.classList.add(j % 2 === 0 ? "lightTreeTableRow" : "darkTreeTableRow");  //$NON-NLS-1$ //$NON-NLS-0$
-				tr.classList.add("manageOpenIdRow"); //$NON-NLS-0$
-				tr.style.verticalAlign = "baseline"; //$NON-NLS-0$
-				table.appendChild(tr);
-
-				td = document.createElement("td"); //$NON-NLS-0$
-				td.classList.add("navColumn"); //$NON-NLS-0$
-				tr.appendChild(td);
-				var span = document.createElement("span"); //$NON-NLS-0$
-				span.title = openid;
-				td.appendChild(span);
-				var textNode = document.createTextNode(openid.length > 70 ? (openid.substring(0, 65) + "...") : openid); //$NON-NLS-0$
-				span.appendChild(textNode);
-
-				td = document.createElement("td"); //$NON-NLS-0$
-				td.classList.add("navColumn"); //$NON-NLS-0$
-				tr.appendChild(td);
-				var removeLink = document.createElement("a"); //$NON-NLS-0$
-				removeLink.classList.add("removeOpenId"); //$NON-NLS-0$
-				removeLink.id = "remlink" + j; //$NON-NLS-0$
-				removeLink.innerHTML = messages['Remove'];
-				removeLink.style.visibility = "hidden"; //$NON-NLS-0$
-				removeLink.title = i18nUtil.formatMessage(messages['RemoveExternalAccount'],[openid]);
-				td.appendChild(removeLink);
-
-				removeLink.addEventListener("click", function(openid) { //$NON-NLS-0$
-					removeOpenId(openid);
-				}.bind(this, openid));
-			}
-		}
-	};
-	
-	loadUserData = function(userLocation){
-		xhr("GET", userLocation, { //$NON-NLS-0$
-			headers : {
-				"Orion-Version" : "1" //$NON-NLS-0$ //$NON-NLS-1$
-			},
-			timeout : 15000
-		}).then(function(xhrResult) {
-			loadAttachedOpenIds(JSON.parse(xhrResult.response));
-		}, function(xhrResult) {
-			console.error(xhrResult.error);
-		});
-	 };
-	
-	function onHashChange(hash) {
-		if (lastHash === hash) {
-			return;
-		}
-	
-		loadUserData(hash);
-	
-		lastHash = hash;
-	}
-	
-	
-	// this function is directly invoked by ManageOpenidsServlet, must be global
-	window.handleOpenIDResponse = function(openid) {
-		var openids = jsonData.properties.openid ? jsonData.properties.openid.split('\n') : []; //$NON-NLS-0$
-		for (var i = 0; i < openids.length; i++) {
-			if (openids[i] === openid) {
-				return;
-			}
-		}
-	
-		if (!jsonData.properties.openid) {
-			jsonData.properties.openid = openid;
-		} else {
-			jsonData.properties.openid += '\n' + openid; //$NON-NLS-0$
-		}
-	
-		xhr("PUT", jsonData.Location, { //$NON-NLS-0$
-			data: JSON.stringify(jsonData),
-			headers: {
-				"Orion-Version": "1" //$NON-NLS-0$  //$NON-NLS-1$
-			},
-			timeout: 15000
-		}).then(function(xhrResult) {
-			loadUserData(jsonData.Location);
-		}, function(xhrResult) {
-			console.error(xhrResult.error);
-		});
-	};
-	
-	function confirmOpenId(openid) {
-		if (openid !== "" && openid !== null) {
-			window.open("../mixlogin/manageopenids/openid?openid=" + encodeURIComponent(openid), "openid_popup", "width=790,height=580");  //$NON-NLS-0$  //$NON-NLS-1$  //$NON-NLS-2$
-		}
-	}
-
-	function createProviderLink(name, imageUrl, onclick) {
-		var img = document.createElement("img"); //$NON-NLS-0$
-		img.className = "loginWindow"; //$NON-NLS-0$
-		img.id = img.alt = img.title = name;
-		img.src = imageUrl;
-
-		var a = document.createElement("a"); //$NON-NLS-0$
-		a.className = "loginWindow"; //$NON-NLS-0$
-		a.onclick = onclick;
-		a.setAttribute("aria-labelledby", "addExternalAccount " + name); //$NON-NLS-0$ //$NON-NLS-1$
-		a.appendChild(img);
-		return a;
-	}
-
-	function attachExternalAccountsHeader(){
-		var openIdContainer = document.getElementById("newOpenId"); //$NON-NLS-0$
-		var h2 = document.createElement("h2"); //$NON-NLS-0$
-		h2.style.margin = "10px 5px 10px 0"; //$NON-NLS-0$
-		h2.style.cssFloat = "left";//$NON-NLS-0$
-		h2.id = "addExternalAccount";//$NON-NLS-0$
-		h2.innerHTML = messages["AddExternalAccount"];//$NON-NLS-0$
-		openIdContainer.appendChild(h2);
-	}
-
-	// Page glue code starts here
-	window.addEventListener("hashchange", function() { //$NON-NLS-0$
-		onHashChange(window.location.hash.substring(1));
-	});
-
-	onHashChange(window.location.hash.substring(1));
-	attachExternalAccountsHeader();
-
-	xhr("GET", "../mixlogin/manageopenids") //$NON-NLS-1$ //$NON-NLS-0$
-		.then(function(xhrResult) {
-			var providers = JSON.parse(xhrResult.response);
-			var providerElements = providers.map(function(provider) {
-				return createProviderLink(provider.Name, provider.Image, confirmOpenId.bind(null, provider.Url));
-			});
-			providerElements.push(createProviderLink("Mozilla Persona", "../mixloginstatic/images/persona.png", //$NON-NLS-0$ //$NON-NLS-1$
-				alert.bind(null, messages['AddPersona'])));
- 
-			var openIdContainer = document.getElementById("newOpenId"); //$NON-NLS-0$
-						
-			providerElements.forEach(function(provider) {
-				openIdContainer.appendChild(provider);
-				openIdContainer.appendChild(document.createTextNode(" ")); //$NON-NLS-0$
-			});
-		});
-});
diff --git a/bundles/org.eclipse.orion.client.ui/web/mixloginstatic/userProfilePlugin.html b/bundles/org.eclipse.orion.client.ui/web/mixloginstatic/userProfilePlugin.html
index 664b30b..237ab52 100644
--- a/bundles/org.eclipse.orion.client.ui/web/mixloginstatic/userProfilePlugin.html
+++ b/bundles/org.eclipse.orion.client.ui/web/mixloginstatic/userProfilePlugin.html
@@ -14,7 +14,7 @@
 				},
 				getDivContent: function() {
 				  	var content = {"sections" : [
-				  	                             {"id": "openids", "name": "Manage External Accounts", "type": "iframe", "data" : {"src": "../mixlogin/manageopenids", "style" : "border: 0px; width: 500px"}}
+				  	                             {"id": "openids", "name": "Manage External Accounts", "type": "iframe", "data" : {"src": "../mixlogin/manageExternalIds", "style" : "border: 0px; width: 500px"}}
 				  	                             ]
 				  	};
 				  	return content;
diff --git a/bundles/org.eclipse.orion.client.ui/web/orion/widgets/settings/UserSettings.js b/bundles/org.eclipse.orion.client.ui/web/orion/widgets/settings/UserSettings.js
index 6d3bba3..d696eb1 100644
--- a/bundles/org.eclipse.orion.client.ui/web/orion/widgets/settings/UserSettings.js
+++ b/bundles/org.eclipse.orion.client.ui/web/orion/widgets/settings/UserSettings.js
@@ -96,9 +96,9 @@
 			

 			

 			var iframe = this.iframe = document.createElement("iframe"); //$NON-NLS-0$

-			iframe.src = "../mixloginstatic/manageOpenids.html";  //$NON-NLS-0$

-			iframe.style.border = "0";  //$NON-NLS-0$

-			iframe.style.width = "500px";  //$NON-NLS-0$

+			iframe.src = "../mixloginstatic/manageExternalIds.html"; //$NON-NLS-0$

+			iframe.style.border = "0";

+			iframe.style.width = "500px";

 			lib.node( 'iFrameContent' ).appendChild(iframe); //$NON-NLS-0$

 		},

 		

@@ -250,4 +250,4 @@
 		}

 	});

 	return UserSettings;

-});
\ No newline at end of file
+});
diff --git a/bundles/org.eclipse.orion.client.users/web/profile/userservicePlugin.js b/bundles/org.eclipse.orion.client.users/web/profile/userservicePlugin.js
index 683c3a8..6d3b200 100644
--- a/bundles/org.eclipse.orion.client.users/web/profile/userservicePlugin.js
+++ b/bundles/org.eclipse.orion.client.users/web/profile/userservicePlugin.js
@@ -64,7 +64,7 @@
    				  	                                                                                            {"type": "TextBox", "props": {"id": "git_name", "readOnly" : false, "name" : "GitName"}, "label" : "Git Name:"}
    				  	                                                                                            ]
    				  	        },
-                          {"id": "openids", "name": "Manage External Accounts", "type": "iframe", "data" : {"src": "../mixloginstatic/manageOpenids.html"}}
+                          {"id": "openids", "name": "Manage External Accounts", "type": "iframe", "data" : {"src": "../mixloginstatic/manageExternalIds.html"}}
                             ]
 		};
 
diff --git a/doc/org.eclipse.orion.doc.isv/WikiDoc/Orion/Server_admin_guide/Configuring-the-server.html b/doc/org.eclipse.orion.doc.isv/WikiDoc/Orion/Server_admin_guide/Configuring-the-server.html
index 042bcd5..6990d55 100644
--- a/doc/org.eclipse.orion.doc.isv/WikiDoc/Orion/Server_admin_guide/Configuring-the-server.html
+++ b/doc/org.eclipse.orion.doc.isv/WikiDoc/Orion/Server_admin_guide/Configuring-the-server.html
@@ -105,13 +105,13 @@
 		<p>To configure the kind of authentication used by the server, set the <tt>orion.auth.name</tt> property in the 
 			<a href="#Server_configuration_file">server configuration file</a>. For example, the following line will configure the server to use simple form-based authentication:
 		</p>
-		<pre class="source-properties">orion.auth.name=FORM+OpenID
+		<pre class="source-properties">orion.auth.name=FORM+OAuth
 
 </pre>
 		<p>Valid values for this property are:</p>
 		<ul>
 			<li><code>Basic</code>: Basic HTTP authentication (not secure unless running on https)</li>
-			<li><code>FORM+OpenID</code>: User can select form-based authentication or OpenID authentication</li>
+			<li><code>FORM+OAuth</code>: User can select form-based authentication or OAuth authentication</li>
 		</ul>
 		<h2 id="Configuring_Mozilla_Persona_authentication">Configuring Mozilla Persona authentication</h2>
 		<p>Orion supports login using 
diff --git a/releng/org.eclipse.orion.client.releng/builder/scripts/orion.build.js b/releng/org.eclipse.orion.client.releng/builder/scripts/orion.build.js
index 7458ea7..bbb9589 100644
--- a/releng/org.eclipse.orion.client.releng/builder/scripts/orion.build.js
+++ b/releng/org.eclipse.orion.client.releng/builder/scripts/orion.build.js
@@ -97,7 +97,7 @@
             { name: "javascript/plugins/javascriptPluginLoader" },
             { name: "javascript/plugins/javascriptPlugin" },
             { name: "mixloginstatic/LoginWindow" },
-            { name: "mixloginstatic/manageOpenids" },
+            { name: "mixloginstatic/manageExternalIds" },
             { name: "operations/list" },
             { name: "plugins/GerritFilePlugin" },
             { name: "plugins/GitHubFilePlugin" },