Skip to content

Commit

Permalink
Merge pull request #170 from andamian/CADC-12837
Browse files Browse the repository at this point in the history
Added support for `OpenIdPrincipals` with different issuers
  • Loading branch information
pdowler authored Jul 24, 2024
2 parents 2d178c4 + 1f8cec8 commit e00fab6
Show file tree
Hide file tree
Showing 6 changed files with 41 additions and 52 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
******************* CANADIAN ASTRONOMY DATA CENTRE *******************
************** CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES **************
*
* (c) 2014. (c) 2014.
* (c) 2024. (c) 2024.
* Government of Canada Gouvernement du Canada
* National Research Council Conseil national de recherches
* Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6
Expand Down Expand Up @@ -256,10 +256,6 @@ else if (idType.equalsIgnoreCase(IdentityType.CADC.getValue()))
{
return new NumericPrincipal(UUID.fromString(userName));
}
else if (idType.equalsIgnoreCase(IdentityType.OPENID.getValue()))
{
return new OpenIdPrincipal(userName);
}
else if (idType.equalsIgnoreCase(IdentityType.COOKIE.getValue()))
{
return new CookiePrincipal(SSOCookieManager.DEFAULT_SSO_COOKIE_NAME, userName);
Expand Down
2 changes: 1 addition & 1 deletion cadc-access-control/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ sourceCompatibility = 1.8

group = 'org.opencadc'

version = '1.1.27'
version = '1.1.29'

description = 'OpenCADC User+Group client library'
def git_url = 'https://github.com/opencadc/ac'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
******************* CANADIAN ASTRONOMY DATA CENTRE *******************
************** CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES **************
*
* (c) 2019. (c) 2019.
* (c) 2024. (c) 2024.
* Government of Canada Gouvernement du Canada
* National Research Council Conseil national de recherches
* Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6
Expand Down Expand Up @@ -103,7 +103,6 @@
import ca.nrc.cadc.auth.HttpPrincipal;
import ca.nrc.cadc.auth.IdentityType;
import ca.nrc.cadc.auth.NumericPrincipal;
import ca.nrc.cadc.auth.OpenIdPrincipal;
import ca.nrc.cadc.auth.PosixPrincipal;
import ca.nrc.cadc.date.DateUtil;

Expand Down Expand Up @@ -282,11 +281,7 @@ protected final Principal getPrincipal(Element element)

String identity = element.getText();
Principal principal;
if (type.equals(IdentityType.OPENID.getValue()))
{
principal = new OpenIdPrincipal(identity);
}
else if (type.equals(IdentityType.CADC.getValue()))
if (type.equals(IdentityType.CADC.getValue()))
{
principal = new NumericPrincipal(UUID.fromString(identity));
}
Expand Down Expand Up @@ -784,10 +779,6 @@ else if ((identity instanceof NumericPrincipal))
{
identityElement.setAttribute(TYPE, IdentityType.CADC.getValue());
}
else if ((identity instanceof OpenIdPrincipal))
{
identityElement.setAttribute(TYPE, IdentityType.OPENID.getValue());
}
else if ((identity instanceof X500Principal))
{
identityElement.setAttribute(TYPE, IdentityType.X500.getValue());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,6 @@
import ca.nrc.cadc.ac.WriterException;
import ca.nrc.cadc.auth.HttpPrincipal;
import ca.nrc.cadc.auth.NumericPrincipal;
import ca.nrc.cadc.auth.OpenIdPrincipal;
import ca.nrc.cadc.util.PropertiesReader;

/**
Expand Down Expand Up @@ -193,14 +192,6 @@ public void testReadWrite()

assertEquals(expected, actual);

// OpenID
expected = new OpenIdPrincipal("bar");
element = getElement(expected);
assertNotNull(element);

actual = getPrincipal(element);
assertNotNull(actual);

assertEquals(expected, actual);

// HTTP
Expand Down
4 changes: 2 additions & 2 deletions cadc-gms/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,13 @@ sourceCompatibility = 1.8

group = 'org.opencadc'

version = '1.0.12'
version = '1.0.13'

description = 'OpenCADC GMS API library'
def git_url = 'https://github.com/opencadc/ac'

dependencies {
compile 'org.opencadc:cadc-util:[1.10,2.0)'
compile 'org.opencadc:cadc-util:[1.11.3,2.0)'
compile 'org.opencadc:cadc-registry:[1.6,2.0)'
compile 'org.opencadc:cadc-cdp:[1.3,2.0)'

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
******************* CANADIAN ASTRONOMY DATA CENTRE *******************
************** CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES **************
*
* (c) 2023. (c) 2023.
* (c) 2024. (c) 2024.
* Government of Canada Gouvernement du Canada
* National Research Council Conseil national de recherches
* Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6
Expand Down Expand Up @@ -74,7 +74,7 @@
import ca.nrc.cadc.auth.HttpPrincipal;
import ca.nrc.cadc.auth.IdentityManager;
import ca.nrc.cadc.auth.NotAuthenticatedException;
import ca.nrc.cadc.auth.NumericPrincipal;
import ca.nrc.cadc.auth.OpenIdPrincipal;
import ca.nrc.cadc.auth.PosixPrincipal;
import ca.nrc.cadc.net.HttpGet;
import ca.nrc.cadc.reg.Standards;
Expand All @@ -90,6 +90,7 @@
import java.security.PrivilegedExceptionAction;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.NoSuchElementException;
Expand Down Expand Up @@ -125,6 +126,8 @@ public class StandardIdentityManager implements IdentityManager {
private RegistryClient reg = new RegistryClient();
private final List<String> oidcDomains = new ArrayList<>();
private URI oidcScope;

private static final String OID_OWNER_DELIM = " "; // delimiter between issuer and openID that form the owner str

public StandardIdentityManager() {
LocalAuthority loc = new LocalAuthority();
Expand All @@ -133,13 +136,13 @@ public StandardIdentityManager() {
try {
URL u = oidcIssuer.toURL();
oidcDomains.add(u.getHost());

// add known and assume trusted A&A services
String host = getProviderHostname(loc, Standards.GMS_SEARCH_10);
if (host != null) {
oidcDomains.add(host);
}

} catch (MalformedURLException ex) {
throw new InvalidConfigException("found " + key + " = " + oidcIssuer + " - expected valid URL", ex);
}
Expand Down Expand Up @@ -178,7 +181,7 @@ public Subject validate(Subject subject) throws NotAuthenticatedException {

@Override
public Subject augment(Subject subject) {
// oidc tokens: validate gets HttpPrincipal and NumericPrincipal
// oidc tokens: validate gets HttpPrincipal and OpenIdPrincipal
// cadc signed cookies/tokens: validate gets all identities
boolean hasPP = !subject.getPrincipals(PosixPrincipal.class).isEmpty();
boolean hasHP = !subject.getPrincipals(HttpPrincipal.class).isEmpty();
Expand Down Expand Up @@ -244,18 +247,25 @@ public Subject augment(Subject subject) {
@Override
public Subject toSubject(Object owner) {
Subject ret = new Subject();
OpenIdPrincipal p = null;
if (owner != null) {
UUID uuid = null;
if (owner instanceof UUID) {
uuid = (UUID) owner;
} else if (owner instanceof String) {
String sub = (String) owner;
uuid = UUID.fromString(sub);
if (owner instanceof String) {
String[] openIDComponents = ((String)owner).split(OID_OWNER_DELIM); // "issuer openID"
if (openIDComponents.length != 2) {
throw new RuntimeException("unexpected owner format: " + owner.getClass().getName() + " value: " + owner);
}
URL issuer = null;
try {
issuer = new URL(openIDComponents[0]);
} catch (MalformedURLException e) {
throw new RuntimeException(
"incorrect issuer format for owner: " + owner.getClass().getName() + " value: " + owner);
}
p = new OpenIdPrincipal(issuer, openIDComponents[1]);
} else {
throw new RuntimeException("unexpected owner type: " + owner.getClass().getName() + " value: " + owner);
}
NumericPrincipal p = new NumericPrincipal(uuid);


// effectively augment by using the current subject as a "cache" of known identities
Subject s = AuthenticationUtil.getCurrentSubject();
if (s != null) {
Expand All @@ -267,7 +277,7 @@ public Subject toSubject(Object owner) {
}
}
}

ret.getPrincipals().add(p);
// this is sufficient for some purposes, but not for output using toDisplayString (eg vospace node owner)
// TODO: use PosixMapperClient.augment() to try to add a PosixPrincipal and infer an HttpPrincipal?
Expand All @@ -278,11 +288,12 @@ public Subject toSubject(Object owner) {
@Override
public Object toOwner(Subject subject) {
// use NumericPrincipal aka OIDC sub for persistence
Set<NumericPrincipal> ps = subject.getPrincipals(NumericPrincipal.class);
Set<OpenIdPrincipal> ps = subject.getPrincipals(OpenIdPrincipal.class);
if (ps.isEmpty()) {
return null;
}
return ps.iterator().next().getUUID().toString();
OpenIdPrincipal openIdPrincipal = ps.iterator().next();
return openIdPrincipal.getIssuer().toString() + OID_OWNER_DELIM + openIdPrincipal.getName();
}

@Override
Expand All @@ -307,8 +318,8 @@ public String toDisplayString(Subject subject) {
private void validateOidcAccessToken(Subject s) {
log.debug("validateOidcAccessToken - START");
Set<AuthorizationTokenPrincipal> rawTokens = s.getPrincipals(AuthorizationTokenPrincipal.class);
log.debug("token issuer: " + oidcIssuer + " rawTokens: " + rawTokens.size());

log.debug("token issuer: " + oidcIssuer + " rawTokens: " + rawTokens.size());
if (oidcIssuer != null && !rawTokens.isEmpty()) {
URL u = getUserEndpoint();
for (AuthorizationTokenPrincipal raw : rawTokens) {
Expand All @@ -325,12 +336,12 @@ private void validateOidcAccessToken(Subject s) {
credentials = tval[1];
} else {
throw new NotAuthenticatedException(challengeType, NotAuthenticatedException.AuthError.INVALID_REQUEST,
"invalid authorization");
"invalid authorization");
}
} // else: some other challenge
} // else: some other challenge
log.debug("challenge type: " + challengeType);
log.debug("credentials: " + credentials);

// validate
if (challengeType != null && credentials != null) {
try {
Expand All @@ -345,11 +356,11 @@ private void validateOidcAccessToken(Subject s) {
String username = json.getString("preferred_username");
// TODO: register an X509 DN with IAM and see if I can get it back here

NumericPrincipal np = new NumericPrincipal(UUID.fromString(sub));
OpenIdPrincipal oip = new OpenIdPrincipal(oidcIssuer.toURL(), sub);
HttpPrincipal hp = new HttpPrincipal(username);

s.getPrincipals().remove(raw);
s.getPrincipals().add(np);
s.getPrincipals().add(oip);
s.getPrincipals().add(hp);

AuthorizationToken authToken = new AuthorizationToken(challengeType, credentials, oidcDomains, oidcScope);
Expand All @@ -372,8 +383,8 @@ private void validateOidcAccessToken(Subject s) {
}
}
}
log.debug("validateOidcAccessToken - DONE");
}
log.debug("validateOidcAccessToken - DONE");
}

private URL getUserEndpoint() {
Expand Down

0 comments on commit e00fab6

Please sign in to comment.