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()) {