diff --git a/src/main/java/org/broad/igv/batch/CommandListener.java b/src/main/java/org/broad/igv/batch/CommandListener.java
index 5b3f6fffca..6cad61678a 100755
--- a/src/main/java/org/broad/igv/batch/CommandListener.java
+++ b/src/main/java/org/broad/igv/batch/CommandListener.java
@@ -37,7 +37,6 @@
import org.broad.igv.ui.IGV;
import org.broad.igv.ui.util.MessageUtils;
import org.broad.igv.ui.util.UIUtilities;
-import org.broad.igv.util.HttpUtils;
import org.broad.igv.util.StringUtils;
import java.awt.*;
@@ -228,7 +227,7 @@ private void processClientSession(CommandExecutor cmdExe) throws IOException {
if (params.containsKey("error")) {
sendTextResponse(out, "Error authorizing IGV: " + params.get("error"));
} else if (params.containsKey("code")) {
- provider.setAuthorizationCode(params.get("code"));
+ provider.fetchAccessToken(params.get("code"));
sendTextResponse(out, "Authorization successful. You may close this tab.");
} else if (params.containsKey("token")) {
// Very doubtful this is ever called -- its not a normal OAuth flow
diff --git a/src/main/java/org/broad/igv/oauth/OAuthProvider.java b/src/main/java/org/broad/igv/oauth/OAuthProvider.java
index 50b36d43f9..92105ad1c0 100644
--- a/src/main/java/org/broad/igv/oauth/OAuthProvider.java
+++ b/src/main/java/org/broad/igv/oauth/OAuthProvider.java
@@ -21,9 +21,9 @@
import java.awt.*;
import java.io.IOException;
import java.net.*;
+import java.security.NoSuchAlgorithmException;
import java.time.Duration;
import java.util.*;
-import java.util.prefs.Preferences;
public class OAuthProvider {
@@ -33,7 +33,6 @@ public class OAuthProvider {
private String appIdURI;
public static String findString = null;
public static String replaceString = null;
- private static final String REFRESH_TOKEN_KEY = "oauth_refresh_token";
private String state; // "RFC6749: An opaque value used by the client to maintain state"
private String redirectURI;
private String clientId;
@@ -42,6 +41,9 @@ public class OAuthProvider {
private String tokenEndpoint;
private String accessToken;
private String refreshToken;
+ private String codeChallenge;
+ private String codeVerifier;
+ private String codeChallengeMethod;
private long expirationTime; // in milliseconds
private String scope;
private String[] hosts;
@@ -61,39 +63,39 @@ public OAuthProvider(JsonObject obj) throws IOException {
}
// Mandatory attributes, fail hard if not present
- try {
- clientId = obj.get("client_id").getAsString();
- authEndpoint = obj.has("auth_uri") ?
- obj.get("auth_uri").getAsString() :
- obj.get("authorization_endpoint").getAsString();
- tokenEndpoint = obj.has("token_uri") ?
- obj.get("token_uri").getAsString() :
- obj.get("token_endpoint").getAsString();
-
- } catch (Exception e) {
- log.error(e);
- throw new IOException("oauthConfig is missing crucial attributes such as: client_id, " +
- "authorization_endpoint/auth_uri or token_endpoint/token_uri");
+ if (!(obj.has("client_id") &&
+ (obj.has("auth_uri") || obj.has("authorization_endpoint")) &&
+ (obj.has("token_uri") || obj.has("token_endpoint")) &&
+ obj.has("client_secret"))) {
+ throw new RuntimeException("oauthConfig is missing crucial attributes such as: client_id, client_secret, " +
+ "authorization_endpoint/auth_uri, or token_endpoint/token_uri.");
}
- String portNumber = PreferencesManager.getPreferences().getPortNumber();
- redirectURI = "http://localhost:" + portNumber + "/oauthCallback";;
-
- // Optional or custom attributes, fail on runtime, depending on identity provider configuration
+ clientId = obj.get("client_id").getAsString();
+ authEndpoint = obj.has("auth_uri") ?
+ obj.get("auth_uri").getAsString() :
+ obj.get("authorization_endpoint").getAsString();
+ tokenEndpoint = obj.has("token_uri") ?
+ obj.get("token_uri").getAsString() :
+ obj.get("token_endpoint").getAsString();
clientSecret = obj.has("client_secret") ? obj.get("client_secret").getAsString() : null;
- setAuthProvider(obj.has("auth_provider") ? obj.get("auth_provider").getAsString() : authProvider);
- // app ID URI is a Microsoft
- appIdURI = obj.has("app_id_uri") ?
- obj.get("app_id_uri").getAsString() :
- obj.has("resource") ? obj.get("resource").getAsString() : null;
-
-
- findString = obj.has("find_string") ? obj.get("find_string").getAsString() : null;
- replaceString = obj.has("replace_string") ? obj.get("replace_string").getAsString() : null;
+ // Optional attributes
+ if (obj.has("auth_provider")) {
+ authProvider = obj.get("auth_provider").getAsString();
+ }
if (obj.has("scope")) {
scope = obj.get("scope").getAsString();
+ } else if (isGoogle()) {
+ String gsScope = "https://www.googleapis.com/auth/devstorage.read_only";
+ String emailScope = "https://www.googleapis.com/auth/userinfo.email";
+ scope = gsScope + "%20" + emailScope;
+
}
+ appIdURI = obj.has("app_id_uri") ? // Microsoft Azure.
+ obj.get("app_id_uri").getAsString() :
+ obj.has("resource") ? obj.get("resource").getAsString() : null;
+
if (obj.has("hosts")) {
// hosts element may be an array or a single string - put in hosts array either way
JsonElement hostsElement = obj.get("hosts");
@@ -108,14 +110,12 @@ public OAuthProvider(JsonObject obj) throws IOException {
}
}
- // Special Google properties
- if (isGoogle()) {
- if (scope == null) {
- String gsScope = "https://www.googleapis.com/auth/devstorage.read_only";
- String emailScope = "https://www.googleapis.com/auth/userinfo.email";
- scope = gsScope + "%20" + emailScope;
- }
- }
+ String portNumber = PreferencesManager.getPreferences().getPortNumber();
+ redirectURI = "http://localhost:" + portNumber + "/oauthCallback";
+
+ // Deprecated properties -- for backward compatibility
+ findString = obj.has("find_string") ? obj.get("find_string").getAsString() : null;
+ replaceString = obj.has("replace_string") ? obj.get("replace_string").getAsString() : null;
}
public String getState() {
@@ -134,26 +134,38 @@ public String getState() {
*/
public void openAuthorizationPage() throws IOException, URISyntaxException {
- String url;
-
// If the port listener is not on, try starting it
if (!CommandListener.isListening()) {
CommandListener.start();
}
- // if the listener is not active, prompt the user
- // for the access token
+ // if the listener is not active, prompt the user for the access token
if (!CommandListener.isListening()) {
- String ac = MessageUtils.showInputDialog("The IGV port listener is required for OAuth authentication. If you have an access token enter it here.");
+ String ac = MessageUtils.showInputDialog(
+ "The IGV port listener is off and is required for OAuth authentication through IGV
. " +
+ "If you have an access token obtained by other means enter it here.");
if (ac != null) {
setAccessToken(ac);
}
} else {
+ // Generate PKCE challenge and verifier
+ codeVerifier = PKCEUtils.generateCodeVerifier();
+ try {
+ codeChallenge = PKCEUtils.generateCodeChallange(codeVerifier);
+ codeChallengeMethod = "S256";
+ } catch (NoSuchAlgorithmException e) {
+ codeChallenge = codeVerifier;
+ codeChallengeMethod = "plain";
+ log.error("Error encoding PKCE challenge", e);
+ }
- url = authEndpoint + "?state=" + state +
+ String url = authEndpoint +
+ "?state=" + state +
"&redirect_uri=" + URLEncoder.encode(redirectURI, "utf-8") +
"&client_id=" + clientId +
- "&response_type=code";
+ "&response_type=code" +
+ "&code_challenge=" + codeChallenge +
+ "&code_challenge_method=" + codeChallengeMethod;
if (scope != null) {
url += "&scope=" + scope;
@@ -174,7 +186,7 @@ public void openAuthorizationPage() throws IOException, URISyntaxException {
}
// Called from port listener (org.broad.igv.batch.CommandListener) upon receiving the oauth request with a "code" parameter
- public void setAuthorizationCode(String authorizationCode) throws IOException {
+ public void fetchAccessToken(String authorizationCode) throws IOException {
URL url = HttpUtils.createURL(tokenEndpoint);
@@ -184,10 +196,13 @@ public void setAuthorizationCode(String authorizationCode) throws IOException {
if (clientSecret != null) {
params.put("client_secret", clientSecret);
}
+ params.put("state", state);
params.put("redirect_uri", redirectURI);
params.put("grant_type", "authorization_code");
+ params.put("code_verifier", codeVerifier);
+
- // set the resource if it necessary for the auth provider dwm08
+ // set the resource if necessary for the auth provider
if (appIdURI != null) {
params.put("resource", appIdURI);
}
@@ -197,11 +212,10 @@ public void setAuthorizationCode(String authorizationCode) throws IOException {
String res = HttpUtils.getInstance().doPost(url, params);
JsonParser parser = new JsonParser();
- setResponse(parser.parse(res).getAsJsonObject());
-
+ response = parser.parse(res).getAsJsonObject();
accessToken = response.get("access_token").getAsString();
refreshToken = response.get("refresh_token").getAsString();
- expirationTime = System.currentTimeMillis() + (response.get("expires_in").getAsInt() * 1000);
+ expirationTime = System.currentTimeMillis() + response.get("expires_in").getAsInt() * 1000;
// Populate this class with user profile attributes
if (response.has("id_token")) {
@@ -241,13 +255,14 @@ public void setAccessToken(String accessToken) {
*/
private void refreshAccessToken() throws IOException {
- // properties moved to early init dwm08
- //if (clientId == null) fetchOauthProperties();
+ log.debug("Refresh access token");
Map params = new HashMap();
params.put("refresh_token", refreshToken);
params.put("client_id", clientId);
- params.put("client_secret", clientSecret);
+ if (clientSecret != null) {
+ params.put("client_secret", clientSecret);
+ }
params.put("grant_type", "refresh_token");
// set the resource if it necessary for the auth provider dwm08
@@ -258,16 +273,17 @@ private void refreshAccessToken() throws IOException {
// Poke the token refresh endpoint to get new access key
URL url = HttpUtils.createURL(tokenEndpoint);
- String response = HttpUtils.getInstance().doPost(url, params);
+ String responseString = HttpUtils.getInstance().doPost(url, params);
JsonParser parser = new JsonParser();
+ response = parser.parse(responseString).getAsJsonObject();
- setResponse(parser.parse(response).getAsJsonObject());
- JsonObject obj = getResponse();
-
- JsonPrimitive atprim = obj.getAsJsonPrimitive("access_token");
+ JsonPrimitive atprim = response.getAsJsonPrimitive("access_token");
if (atprim != null) {
- accessToken = obj.getAsJsonPrimitive("access_token").getAsString();
- expirationTime = System.currentTimeMillis() + (obj.getAsJsonPrimitive("expires_in").getAsInt() * 1000);
+ accessToken = response.getAsJsonPrimitive("access_token").getAsString();
+ if (response.has("refresh_token")) {
+ refreshToken = response.getAsJsonPrimitive("refresh_token").getAsString();
+ }
+ expirationTime = System.currentTimeMillis() + response.getAsJsonPrimitive("expires_in").getAsInt() * 1000;
} else {
// Refresh token has failed, reauthorize from scratch
reauthorize();
@@ -331,36 +347,6 @@ public Duration getExpirationTime() {
return expiration;
}
- public class AuthStateEvent {
- boolean authenticated;
- String authProvider;
- String userName;
- String email;
-
- // Assuming that if this event is called, we are indeed autz/authn'd
- public AuthStateEvent(boolean authenticated, String authProvider, String userName) {
- this.authenticated = authenticated;
- this.authProvider = authProvider;
- this.userName = userName;
- }
-
- public boolean isAuthenticated() {
- return authenticated;
- }
-
- public String getAuthProvider() {
- return authProvider;
- }
-
- public String getUserName() {
- return userName;
- }
-
- public String getEmail() {
- return currentUserEmail;
- }
- }
-
public boolean isLoggedIn() {
return accessToken != null;
}
@@ -369,22 +355,18 @@ public String getCurrentUserName() {
return currentUserName != null ? currentUserName : (currentUserEmail != null ? currentUserEmail : currentUserID);
}
+ public String getCurrentUserEmail() {
+ return currentUserEmail;
+ }
public void logout() {
accessToken = null;
refreshToken = null;
expirationTime = -1;
currentUserName = null;
- removeRefreshToken();
+ IGVEventBus.getInstance().post(new AuthStateEvent(false, this.authProvider, null));
}
- private void removeRefreshToken() {
- try {
- Preferences.userRoot().remove(REFRESH_TOKEN_KEY);
- } catch (Exception e) {
- log.error("Error removing oauth refresh token", e);
- }
- }
/**
* If not logged in, attempt to login
@@ -443,12 +425,39 @@ public JsonObject getResponse() {
return response;
}
- public void setResponse(JsonObject res) {
- response = res;
- }
-
public void setAuthProvider(String authProvider) {
this.authProvider = authProvider;
}
+ public String getAuthProvider() {
+ return authProvider;
+ }
+
+ public static class AuthStateEvent {
+ boolean authenticated;
+ String authProvider;
+ String userName;
+
+ // Assuming that if this event is called, we are indeed autz/authn'd
+ public AuthStateEvent(boolean authenticated, String authProvider, String userName) {
+ this.authenticated = authenticated;
+ this.authProvider = authProvider;
+ this.userName = userName;
+ }
+
+ public boolean isAuthenticated() {
+ return authenticated;
+ }
+
+ public String getAuthProvider() {
+ return authProvider;
+ }
+
+ public String getUserName() {
+ return userName;
+ }
+ }
}
+
+
+
diff --git a/src/main/java/org/broad/igv/oauth/OAuthUtils.java b/src/main/java/org/broad/igv/oauth/OAuthUtils.java
index 4ee4439cef..3463a058b9 100644
--- a/src/main/java/org/broad/igv/oauth/OAuthUtils.java
+++ b/src/main/java/org/broad/igv/oauth/OAuthUtils.java
@@ -32,14 +32,15 @@
import org.broad.igv.DirectoryManager;
import org.broad.igv.prefs.PreferencesManager;
import org.broad.igv.ui.IGVMenuBar;
+import org.broad.igv.ui.util.MessageUtils;
import org.broad.igv.util.AmazonUtils;
-import org.broad.igv.util.GoogleUtils;
import org.broad.igv.util.HttpUtils;
import java.io.*;
import java.net.URL;
import java.net.URLConnection;
+import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
@@ -88,11 +89,17 @@ public OAuthProvider getAWSProvider() {
return awsProvider;
}
- public OAuthProvider getGooleProvider() throws IOException {
+ public OAuthProvider getGoogleProvider() {
if (googleProvider == null) {
- loadDefaultOauthProperties();
- if (IGVMenuBar.getInstance() != null) {
- IGVMenuBar.getInstance().enableGoogleMenu(true);
+ try {
+ log.info("Loading Google oAuth properties");
+ googleProvider = loadDefaultOauthProperties();
+ if (IGVMenuBar.getInstance() != null) {
+ IGVMenuBar.getInstance().enableGoogleMenu(true);
+ }
+ } catch (IOException e) {
+ log.error("Error loading Google oAuth properties", e);
+ MessageUtils.showErrorMessage("Error loading Google oAuth properties", e);
}
}
return googleProvider;
@@ -129,13 +136,11 @@ private void fetchOauthProperties() throws IOException {
*
* @throws IOException
*/
- public void loadDefaultOauthProperties() throws IOException {
- if (googleProvider == null) {
- String json = loadAsString(PROPERTIES_URL);
- JsonParser parser = new JsonParser();
- JsonObject obj = parser.parse(json).getAsJsonObject();
- googleProvider = parseProviderObject(obj);
- }
+ public OAuthProvider loadDefaultOauthProperties() throws IOException {
+ String json = loadAsString(PROPERTIES_URL);
+ JsonParser parser = new JsonParser();
+ JsonObject obj = parser.parse(json).getAsJsonObject();
+ return parseProviderObject(obj);
}
/**
@@ -208,6 +213,7 @@ private OAuthProvider parseProviderObject(JsonObject obj) throws IOException {
/**
* Called during authorization flow from CommandListener
+ *
* @param state
* @return
* @throws IOException
@@ -225,7 +231,7 @@ public OAuthProvider getProviderForState(String state) throws IOException {
public OAuthProvider getProviderForURL(URL url) throws IOException {
for (OAuthProvider provider : providerCache.values()) {
if (provider.appliesToUrl(url)) {
- if(provider.isGoogle()) {
+ if (provider.isGoogle()) {
IGVMenuBar.getInstance().enableGoogleMenu(true);
}
return provider;
@@ -234,6 +240,10 @@ public OAuthProvider getProviderForURL(URL url) throws IOException {
return null;
}
+ public Collection getAllProviders() {
+ return providerCache.values();
+ }
+
/**
* Open an input stream for reading a local or remote file.
*
diff --git a/src/main/java/org/broad/igv/oauth/PKCEUtils.java b/src/main/java/org/broad/igv/oauth/PKCEUtils.java
new file mode 100644
index 0000000000..8353ecf284
--- /dev/null
+++ b/src/main/java/org/broad/igv/oauth/PKCEUtils.java
@@ -0,0 +1,27 @@
+package org.broad.igv.oauth;
+
+import java.io.UnsupportedEncodingException;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.security.SecureRandom;
+import java.util.Base64;
+
+
+// Credit: https://www.appsdeveloperblog.com/pkce-code-verifier-and-code-challenge-in-java/
+public class PKCEUtils {
+
+ public static String generateCodeVerifier() throws UnsupportedEncodingException {
+ SecureRandom secureRandom = new SecureRandom();
+ byte[] codeVerifier = new byte[32];
+ secureRandom.nextBytes(codeVerifier);
+ return Base64.getUrlEncoder().withoutPadding().encodeToString(codeVerifier);
+ }
+
+ public static String generateCodeChallange(String codeVerifier) throws UnsupportedEncodingException, NoSuchAlgorithmException {
+ byte[] bytes = codeVerifier.getBytes("US-ASCII");
+ MessageDigest messageDigest = MessageDigest.getInstance("SHA-256");
+ messageDigest.update(bytes, 0, bytes.length);
+ byte[] digest = messageDigest.digest();
+ return Base64.getUrlEncoder().withoutPadding().encodeToString(digest);
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/org/broad/igv/ui/IGVMenuBar.java b/src/main/java/org/broad/igv/ui/IGVMenuBar.java
index 1eaeef9c75..1537a7fcd6 100644
--- a/src/main/java/org/broad/igv/ui/IGVMenuBar.java
+++ b/src/main/java/org/broad/igv/ui/IGVMenuBar.java
@@ -36,6 +36,7 @@
import org.broad.igv.event.IGVEventObserver;
import org.broad.igv.feature.genome.GenomeManager;
import org.broad.igv.feature.genome.GenomeUtils;
+import org.broad.igv.prefs.IGVPreferences;
import org.broad.igv.track.AttributeManager;
import org.broad.igv.track.Track;
import org.broad.igv.util.GoogleUtils;
@@ -182,24 +183,19 @@ private List createMenus() {
// Create a placehold Google menu. If not explicitly enabled it will remain invisible until triggered
// by loading a protected Google resource
- googleMenu = new JMenu("Google");
- menus.add(googleMenu);
- boolean enabled = PreferencesManager.getPreferences().getAsBoolean(ENABLE_GOOGLE_MENU);
- googleMenu.setVisible(enabled);
-
- if (enabled) {
- try {
- enableGoogleMenu(enabled);
- } catch (IOException e) {
- log.error("Error creating google menu: " + e.getMessage());
- }
+ try {
+ googleMenu = createGoogleMenu();
+ boolean enabled = PreferencesManager.getPreferences().getAsBoolean(ENABLE_GOOGLE_MENU);
+ enableGoogleMenu(enabled);
+ menus.add(googleMenu);
+ } catch (IOException e) {
+ log.error("Error creating google menu: " + e.getMessage());
}
try {
AWSMenu = createAWSMenu();
AWSMenu.setVisible(AmazonUtils.isAwsProviderPresent());
menus.add(AWSMenu);
-
} catch (IOException e) {
log.error("Error creating the Amazon AWS menu: " + e.getMessage());
AWSMenu.setVisible(false);
@@ -1025,82 +1021,72 @@ public void menuCanceled(MenuEvent e) {
return menu;
}
- /**
- * The Google menu is enabled dynamically to defer loading of oAuth properties until needed.
- * *
- * @return
- * @throws IOException
- */
- public void enableGoogleMenu(boolean enable) throws IOException {
-
- if(!enable) {
- googleMenu.setVisible(false);
- return;
- } else if (googleMenu.isVisible()) {
- // Already visible.
- return;
- }
+ private JMenu createGoogleMenu() {
+ googleMenu = new JMenu("Google");
+ final JMenuItem login = new JMenuItem("Login ... ");
+ login.addActionListener(e -> {
+ try {
+ OAuthUtils.getInstance().getGoogleProvider().openAuthorizationPage();
+ } catch (Exception ex) {
+ MessageUtils.showErrorMessage("Error fetching oAuth tokens. See log for details", ex);
+ log.error("Error fetching oAuth tokens", ex);
+ }
- googleMenu.setVisible(true);
- final OAuthProvider oauth = OAuthUtils.getInstance().getGooleProvider();
+ });
+ googleMenu.add(login);
- if (oauth != null) {
+ final JMenuItem logout = new JMenuItem("Logout ");
+ logout.addActionListener(e -> {
+ OAuthUtils.getInstance().getGoogleProvider().logout();
+ GoogleUtils.setProjectID(null);
+ });
+ googleMenu.add(logout);
- boolean isLoggedIn = oauth.isLoggedIn();
+ final JMenuItem projectID = new JMenuItem("Enter Project ID ...");
+ projectID.addActionListener(e -> GoogleUtils.enterGoogleProjectID());
+ googleMenu.add(projectID);
- final JMenuItem login = new JMenuItem("Login ... ");
- login.addActionListener(e -> {
- try {
- oauth.openAuthorizationPage();
- } catch (Exception ex) {
- MessageUtils.showErrorMessage("Error fetching oAuth tokens. See log for details", ex);
- log.error("Error fetching oAuth tokens", ex);
+ googleMenu.addMenuListener(new MenuListener() {
+ @Override
+ public void menuSelected(MenuEvent e) {
+ OAuthProvider oauth = OAuthUtils.getInstance().getGoogleProvider();
+ boolean loggedIn = oauth.isLoggedIn();
+ if (loggedIn && oauth.getCurrentUserName() != null) {
+ login.setText(oauth.getCurrentUserName());
+ } else {
+ login.setText("Login ...");
}
+ login.setEnabled(!loggedIn);
+ logout.setEnabled(loggedIn);
+ }
- });
- login.setEnabled(!isLoggedIn);
- googleMenu.add(login);
+ @Override
+ public void menuDeselected(MenuEvent e) {
+ }
- final JMenuItem logout = new JMenuItem("Logout ");
- logout.addActionListener(e -> {
- oauth.logout();
- GoogleUtils.setProjectID(null);
- });
- logout.setEnabled(isLoggedIn);
- googleMenu.add(logout);
-
- final JMenuItem projectID = new JMenuItem("Enter Project ID ...");
- projectID.addActionListener(e -> GoogleUtils.enterGoogleProjectID());
- googleMenu.add(projectID);
-
- googleMenu.addMenuListener(new MenuListener() {
- @Override
- public void menuSelected(MenuEvent e) {
- boolean loggedIn = oauth.isLoggedIn();
- if (loggedIn && oauth.getCurrentUserName() != null) {
- login.setText(oauth.getCurrentUserName());
- } else {
- login.setText("Login ...");
- }
- login.setEnabled(!loggedIn);
- logout.setEnabled(loggedIn);
- }
+ @Override
+ public void menuCanceled(MenuEvent e) {
- @Override
- public void menuDeselected(MenuEvent e) {
+ }
- }
+ });
- @Override
- public void menuCanceled(MenuEvent e) {
+ return googleMenu;
+ }
- }
- });
- }
+ /**
+ * The Google menu is enabled dynamically to defer loading of oAuth properties until needed.
+ * *
+ *
+ * @return
+ * @throws IOException
+ */
+ public void enableGoogleMenu(boolean enable) throws IOException {
+ googleMenu.setVisible(enable);
}
// public void enableRemoveGenomes() {
diff --git a/src/main/java/org/broad/igv/ui/util/ApplicationStatusBar.java b/src/main/java/org/broad/igv/ui/util/ApplicationStatusBar.java
index 952411d4ed..4eb3b4f8f5 100644
--- a/src/main/java/org/broad/igv/ui/util/ApplicationStatusBar.java
+++ b/src/main/java/org/broad/igv/ui/util/ApplicationStatusBar.java
@@ -30,6 +30,7 @@
import org.broad.igv.event.StopEvent;
import org.broad.igv.logging.*;
import org.broad.igv.oauth.OAuthProvider;
+import org.broad.igv.oauth.OAuthUtils;
import org.broad.igv.ui.FontManager;
import org.broad.igv.event.IGVEventBus;
import org.broad.igv.event.IGVEventObserver;
@@ -157,16 +158,23 @@ public void enableStopButton(boolean enable) {
@Override
public void receiveEvent(Object event) {
- if(event instanceof OAuthProvider.AuthStateEvent) {
- boolean isAuthed = ((OAuthProvider.AuthStateEvent) event).isAuthenticated();
- String authProvider = ((OAuthProvider.AuthStateEvent) event).getAuthProvider();
- String userName = ((OAuthProvider.AuthStateEvent) event).getUserName();
- String email = ((OAuthProvider.AuthStateEvent) event).getEmail();
-
- if (isAuthed) {
- setMessage3("Logged in as: " + email + " via " + authProvider);
- } else {
- setMessage3("");
+ if (event instanceof OAuthProvider.AuthStateEvent) {
+
+ String msg = "";
+ for (OAuthProvider provider : OAuthUtils.getInstance().getAllProviders()) {
+ if (provider.isLoggedIn()) {
+ if(msg.length() == 0) {
+ msg += "Logged in as: ";
+ } else {
+ msg += "; ";
+ }
+ String user = provider.getCurrentUserEmail();
+ if(user == null || user.length() == 0) {
+ user = provider.getCurrentUserName();
+ }
+ msg += user + " via " + provider.getAuthProvider();
+ }
+ setMessage3(msg);
}
}
}
diff --git a/src/main/java/org/broad/igv/util/HttpUtils.java b/src/main/java/org/broad/igv/util/HttpUtils.java
index 78410909f1..349c9b3701 100644
--- a/src/main/java/org/broad/igv/util/HttpUtils.java
+++ b/src/main/java/org/broad/igv/util/HttpUtils.java
@@ -320,7 +320,10 @@ public String doPost(URL url, Map params) throws IOException {
conn.getOutputStream().write(postDataBytes);
StringBuilder response = new StringBuilder();
+ System.out.println(conn.getResponseMessage());
Reader in = new BufferedReader(new InputStreamReader(conn.getInputStream(), "UTF-8"));
+
+
for (int c; (c = in.read()) >= 0; ) {
response.append((char) c);
}
@@ -854,7 +857,7 @@ else if (code >= 400) {
} else if (code == 401) {
OAuthProvider provider = OAuthUtils.getInstance().getProviderForURL(url);
if(provider == null && GoogleUtils.isGoogleURL(url.toExternalForm())) {
- provider = OAuthUtils.getInstance().getGooleProvider();
+ provider = OAuthUtils.getInstance().getGoogleProvider();
}
if (provider != null && retries == 0) {
if (!provider.isLoggedIn()) {