Skip to content

Commit

Permalink
oauth code cleanup
Browse files Browse the repository at this point in the history
  • Loading branch information
jrobinso committed Sep 18, 2023
1 parent b5b9fd1 commit 9fa2491
Show file tree
Hide file tree
Showing 8 changed files with 279 additions and 62 deletions.
16 changes: 8 additions & 8 deletions examples/oauth/oauth-config-amazon.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@
"project_id": "igv",
"auth_provider": "Amazon",
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
"aws_region": "ap-southeast-2",
"aws_region": "us-east-1",
"scope": "email%20openid%20profile",
"client_id": "3f4ujenfmr77tg12iofbebpkoh",
"client_secret": "en1q6638m4dogrr6erhosetim67sjilc6htjnfmf6ljk2q3j9og",
"authorization_endpoint": "https://igv-demo.auth.ap-southeast-2.amazoncognito.com/login",
"token_endpoint": "https://igv-demo.auth.ap-southeast-2.amazoncognito.com/token",
"aws_cognito_fed_pool_id": "ap-southeast-2:15b7bf93-18ca-40d5-99e9-38b4eb69363e",
"aws_cognito_pool_id": "ap-southeast-2_IYMvlZzmv",
"aws_cognito_role_arn": "arn:aws:iam::YOUR_AWS_ACCOUNT:role/YOUR_Cognito_igvAuth_Role"
"client_id": "eu7vd09a3dsfasdfd7r4kjomqg",
"client_secret": "s2416djkq5liigbrjdhktdsdgerefktsv04f9p810a3nc9",
"authorization_endpoint": "https://igv-demo.auth.us-east-1.amazoncognito.com/login",
"token_endpoint": "https://igv-demo.auth.us-east-1.amazoncognito.com/token",
"aws_cognito_fed_pool_id": "us-east-1:2926325e-0938-4dfc-840a-fa8a3e4f63f7",
"aws_cognito_pool_id": "us-east-1_v98erojsdkfj",
"aws_cognito_role_arn": "arn:aws:iam::3940820579:role/Cognito_igvAuth_Role"
}
2 changes: 1 addition & 1 deletion src/main/java/org/broad/igv/Globals.java
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ public class Globals {
private static boolean testing = false;
public static int CONNECT_TIMEOUT = 20000; // 20 seconds
public static int READ_TIMEOUT = 1000 * 3 * 60; // 3 minutes
public static int TOKEN_EXPIRE_GRACE_TIME = 1000 * 1 * 60; // 1 minute
public static int TOKEN_EXPIRE_GRACE_TIME = 1000 * 60; // 1 minute

/**
* Field description
Expand Down
6 changes: 2 additions & 4 deletions src/main/java/org/broad/igv/batch/CommandListener.java
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,6 @@ private void processClientSession(CommandExecutor cmdExe) throws IOException {

// Detect oauth callback
if (command.equals("/oauthCallback")) {

OAuthProvider provider = OAuthUtils.getInstance().getProviderForState(params.get("state"));
if (params.containsKey("error")) {
sendTextResponse(out, "Error authorizing IGV: " + params.get("error"));
Expand All @@ -237,12 +236,11 @@ private void processClientSession(CommandExecutor cmdExe) throws IOException {
} else {
sendTextResponse(out, "Unsuccessful authorization response: " + inputLine);
}


if (PreferencesManager.getPreferences().getAsBoolean(Constants.PORT_ENABLED) == false) {
// Turn off port
halt();
}

} else {
// Process the request.
result = processGet(command, params, cmdExe); // Send no response if result is "OK".
Expand Down Expand Up @@ -312,7 +310,7 @@ private void closeSockets() {
private static final String NO_CACHE = "Cache-Control: no-cache, no-store";
private static final String ACCESS_CONTROL_ALLOW_ORIGIN = "Access-Control-Allow-Origin: *";
private static final String ACCESS_CONTROL_ALLOW_HEADERS = "Access-Control-Allow-Headers: access-control-allow-origin";

private void sendTextResponse(PrintWriter out, String result) {
sendHTTPResponse(out, result, "text/html", "GET");
}
Expand Down
40 changes: 24 additions & 16 deletions src/main/java/org/broad/igv/oauth/OAuthProvider.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ public class OAuthProvider {

private static Logger log = LogManager.getLogger(OAuthProvider.class);

private static int TOKEN_EXPIRE_GRACE_TIME = 1000 * 60; // 1 minute

private String authProvider = "";
private String appIdURI;
public static String findString = null;
Expand Down Expand Up @@ -65,8 +67,7 @@ public OAuthProvider(JsonObject obj) throws IOException {
// Mandatory attributes, fail hard if not present
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"))) {
(obj.has("token_uri") || obj.has("token_endpoint")))) {
throw new RuntimeException("oauthConfig is missing crucial attributes such as: client_id, client_secret, " +
"authorization_endpoint/auth_uri, or token_endpoint/token_uri.");
}
Expand Down Expand Up @@ -110,8 +111,26 @@ public OAuthProvider(JsonObject obj) throws IOException {
}
}

String portNumber = PreferencesManager.getPreferences().getPortNumber();
redirectURI = "http://localhost:" + portNumber + "/oauthCallback";
if (obj.has("redirect_uris")) {
JsonArray urisArray = obj.get("redirect_uris").getAsJsonArray();
redirectURI = urisArray.get(0).getAsString();
} else if (obj.has("redirect_uri")) {
redirectURI = obj.get("redirect_uri").getAsString();
} else {
String portNumber = PreferencesManager.getPreferences().getPortNumber();
redirectURI = "http://localhost:" + portNumber + "/oauthCallback";
}

// Generate PKCE challenge and verifier
codeVerifier = PKCEUtils.generateCodeVerifier();
try {
codeChallenge = PKCEUtils.generateCodeChallange(codeVerifier);
codeChallengeMethod = "S256";
} catch (Exception e) {
codeChallenge = codeVerifier;
codeChallengeMethod = "plain";
log.error("Error encoding PKCE challenge", e);
}

// Deprecated properties -- for backward compatibility
findString = obj.has("find_string") ? obj.get("find_string").getAsString() : null;
Expand Down Expand Up @@ -148,16 +167,6 @@ public void openAuthorizationPage() throws IOException, URISyntaxException {
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);
}

String url = authEndpoint +
"?state=" + state +
Expand Down Expand Up @@ -201,7 +210,6 @@ public void fetchAccessToken(String authorizationCode) throws IOException {
params.put("grant_type", "authorization_code");
params.put("code_verifier", codeVerifier);


// set the resource if necessary for the auth provider
if (appIdURI != null) {
params.put("resource", appIdURI);
Expand Down Expand Up @@ -324,7 +332,7 @@ public JsonObject fetchUserProfile(JsonObject jwt_payload) {
public String getAccessToken() {

// Check expiration time, with 1 minute cushion
if (accessToken == null || (System.currentTimeMillis() > (expirationTime - Globals.TOKEN_EXPIRE_GRACE_TIME))) {
if (accessToken == null || (System.currentTimeMillis() > (expirationTime - TOKEN_EXPIRE_GRACE_TIME))) {
log.debug("Refreshing access token!");
if (refreshToken != null) {
try {
Expand Down
5 changes: 0 additions & 5 deletions src/main/java/org/broad/igv/oauth/OAuthURLForm.java
Original file line number Diff line number Diff line change
Expand Up @@ -50,11 +50,6 @@ public static void open(Frame owner, String url) {

}


public static void main(String[] args) {

open(null, "https://docs.oracle.com/javase/tutorial/displayCode.html?code=https://docs.oracle.com/javase/tutorial/uiswing/examples/layout/BoxLayoutDemoProject/src/layout/BoxLayoutDemo.java");
}
}


59 changes: 32 additions & 27 deletions src/main/java/org/broad/igv/oauth/OAuthUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -73,39 +73,17 @@ public static synchronized OAuthUtils getInstance() {
private OAuthUtils() {
try {
providerCache = new LinkedHashMap<>(); // Ordered (linked) map is important
fetchOauthProperties();
fetchOauthConfigs();
} catch (Exception e) {
log.error("Error fetching oAuth properties", e);
}
}

/**
* Called by AWS code only
* Fetch user-configured oAuth configurations, if any*
* @throws IOException
*/
public OAuthProvider getAWSProvider() {
if (awsProvider == null) {
throw new RuntimeException("AWS Oauth is not configured");
}
return awsProvider;
}

public OAuthProvider getGoogleProvider() {
if (googleProvider == null) {
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;
}

private void fetchOauthProperties() throws IOException {
private void fetchOauthConfigs() throws IOException {

// Load a provider config specified in preferences
String provisioningURL = PreferencesManager.getPreferences().getProvisioningURL();
Expand All @@ -131,12 +109,39 @@ private void fetchOauthProperties() throws IOException {
}
}

/**
* Called by AWS code only
*/
public OAuthProvider getAWSProvider() {
if (awsProvider == null) {
throw new RuntimeException("AWS Oauth is not configured");
}
return awsProvider;
}

public OAuthProvider getGoogleProvider() {
if (googleProvider == null) {
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;
}


/**
* Load the default (Google) oAuth properties
*
* @throws IOException
*/
public OAuthProvider loadDefaultOauthProperties() throws IOException {
private OAuthProvider loadDefaultOauthProperties() throws IOException {
String json = loadAsString(PROPERTIES_URL);
JsonParser parser = new JsonParser();
JsonObject obj = parser.parse(json).getAsJsonObject();
Expand Down
Loading

0 comments on commit 9fa2491

Please sign in to comment.