Skip to content

Commit

Permalink
Merge pull request #53 from lsst-sqre/tickets/DM-30011
Browse files Browse the repository at this point in the history
[DM-30011] Support Gafaelfawr 2.0 auth
  • Loading branch information
cbanek authored May 4, 2021
2 parents 13f8af6 + 9617c92 commit 7b0fe2a
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 38 deletions.
12 changes: 7 additions & 5 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ repositories {
mavenLocal()
jcenter()

maven {
url = 'https://www.cadc-ccda.hia-iha.nrc-cnrc.gc.ca/m2repo'
}

// To obtain access to the Oracle Maven repository, put your credentials into environment variables:
// - MAVEN_ORACLE_USERNAME
// - MAVEN_ORACLE_PASSWORD
Expand All @@ -20,10 +24,6 @@ repositories {
password "${System.env.MAVEN_ORACLE_PASSWORD}"
}
}

maven {
url = 'https://www.cadc-ccda.hia-iha.nrc-cnrc.gc.ca/m2repo'
}
}

group = 'org.opencadc'
Expand Down Expand Up @@ -66,8 +66,10 @@ dependencies {
implementation 'org.opencadc:cadc-adql:[1.1.4,)'
implementation 'org.opencadc:cadc-access-control-identity:[1.0.7,)'

implementation 'com.auth0:java-jwt:3.8.1'
runtimeOnly 'org.opencadc:cadc-registry:[1.2.1,)'

// https://mvnrepository.com/artifact/com.google.code.gson/gson
implementation group: 'com.google.code.gson', name: 'gson', version: '2.8.6'
}

sourceSets {
Expand Down
80 changes: 47 additions & 33 deletions src/main/java/org/opencadc/tap/impl/AuthenticatorImpl.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
package org.opencadc.tap.impl;

import java.io.IOException;
import java.net.http.HttpClient;
import java.net.http.HttpResponse;
import java.net.http.HttpResponse.BodyHandlers;
import java.net.http.HttpRequest;
import java.net.URI;
import java.security.Principal;
import java.util.ArrayList;
import java.util.List;
Expand All @@ -15,25 +21,28 @@
import ca.nrc.cadc.auth.NumericPrincipal;
import ca.nrc.cadc.auth.BearerTokenPrincipal;

import org.apache.log4j.Logger;
import com.google.gson.Gson;
import com.google.gson.JsonObject;

import com.auth0.jwt.exceptions.JWTDecodeException;
import com.auth0.jwt.interfaces.Claim;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.auth0.jwt.JWT;
import org.apache.log4j.Logger;

/**
* Implementes the Authenticator for processing LSST JWT tokens,
* and using them to authenticate against the TAP service. Each
* JWT token is self contained and self signed, having the user
* and group information contained.
* Implementes the Authenticator for processing Gafaelfawr auth,
* and using it to authenticate against the TAP service.
*
* The token in the authorization header is used to make a call
* to Gafaelfawr to retrieve details such as the uid and uidNumber.
*
* @author cbanek
*/
public class AuthenticatorImpl implements Authenticator
{
private static final Logger log = Logger.getLogger(AuthenticatorImpl.class);

private static final String gafaelfawr_url = System.getProperty("gafaelfawr_url");

private static final HttpClient client = HttpClient.newHttpClient();

public AuthenticatorImpl()
{
}
Expand All @@ -42,45 +51,50 @@ public Subject getSubject(Subject subject)
{
log.debug("getSubject subject starts as: " + subject);

try {
List<Principal> addedPrincipals = new ArrayList<Principal>();
List<Principal> addedPrincipals = new ArrayList<Principal>();

for (Principal principal : subject.getPrincipals()) {
if (principal instanceof BearerTokenPrincipal) {
BearerTokenPrincipal tp = (BearerTokenPrincipal) principal;

for (Principal principal : subject.getPrincipals()) {
if (principal instanceof BearerTokenPrincipal) {
BearerTokenPrincipal tp = (BearerTokenPrincipal) principal;
DecodedJWT jwt = JWT.decode(tp.getName());
HttpRequest request = HttpRequest.newBuilder(
URI.create(gafaelfawr_url))
.header("Accept", "application/json")
.header("Authorization", "bearer " + tp.getName())
.build();

Map<String, Claim> claims = jwt.getClaims();
String uid = jwt.getClaim("uid").asString();
Integer uidNumber = Integer.valueOf(jwt.getClaim("uidNumber").asString());
String[] scopes = jwt.getClaim("scope").asString().split(" ");
try {
HttpResponse<String> response = client.send(request, BodyHandlers.ofString());
String body = response.body();

log.debug("Found this in the token:");
log.debug("uid = " + uid);
log.debug("uidNumber = " + uidNumber);
Gson gson = new Gson();
JsonObject authData = gson.fromJson(body, JsonObject.class);

for (String scope : scopes) {
log.debug("scope = " + scope);
}
String username = authData.getAsJsonPrimitive("username").getAsString();
int uid = authData.getAsJsonPrimitive("uid").getAsInt();

X500Principal xp = new X500Principal("CN=" + uid);
X500Principal xp = new X500Principal("CN=" + username);
addedPrincipals.add(xp);

HttpPrincipal hp = new HttpPrincipal(uid);
HttpPrincipal hp = new HttpPrincipal(username);
addedPrincipals.add(hp);

UUID uuid = new UUID(0L, (long) uidNumber);
UUID uuid = new UUID(0L, (long) uid);
NumericPrincipal np = new NumericPrincipal(uuid);
addedPrincipals.add(np);
} catch (InterruptedException e) {
log.warn("InterruptedException thrown while getting info from Gafaelfawr");
log.warn(e);
} catch (IOException e) {
log.warn("IOException while getting info from Gafaelfawr");
log.warn(e);
}
}

subject.getPrincipals().addAll(addedPrincipals);
subject.getPublicCredentials().add(AuthMethod.TOKEN);
} catch (JWTDecodeException exception) {
log.debug("Exception decoding JWT: " + exception);
}

subject.getPrincipals().addAll(addedPrincipals);
subject.getPublicCredentials().add(AuthMethod.TOKEN);

log.debug("getSubject's new subject is " + subject);
return subject;
}
Expand Down

0 comments on commit 7b0fe2a

Please sign in to comment.