Begun work to validate application identifier designator for tenant token as well.
diff --git a/api/src/main/java/io/mifos/anubis/api/v1/TokenConstants.java b/api/src/main/java/io/mifos/anubis/api/v1/TokenConstants.java
index e2b2eba..d8da9fe 100644
--- a/api/src/main/java/io/mifos/anubis/api/v1/TokenConstants.java
+++ b/api/src/main/java/io/mifos/anubis/api/v1/TokenConstants.java
@@ -26,6 +26,7 @@
String JWT_SIGNATURE_TIMESTAMP_CLAIM = "/mifos.io/signatureTimestamp";
String JWT_ENDPOINT_SET_CLAIM = "/mifos.io/endpointSet";
String JWT_CONTENT_CLAIM = "/mifos.io/tokenContent";
+ String JWT_SOURCE_APPLICATION_CLAIM = "/mifos.io/sourceApplication";
String REFRESH_TOKEN_COOKIE_NAME = "org.apache.fineract.refreshToken";
}
diff --git a/library/src/main/java/io/mifos/anubis/security/AnubisAuthentication.java b/library/src/main/java/io/mifos/anubis/security/AnubisAuthentication.java
index ab7385f..65b3a7c 100644
--- a/library/src/main/java/io/mifos/anubis/security/AnubisAuthentication.java
+++ b/library/src/main/java/io/mifos/anubis/security/AnubisAuthentication.java
@@ -33,15 +33,20 @@
private final String token;
private final String userIdentifier;
private final String forApplicationName;
+ private final String sourceApplicationName;
private final Set<ApplicationPermission> applicationPermissions;
- AnubisAuthentication(final String token, final String userIdentifier, final String forApplicationName,
- final Set<ApplicationPermission> applicationPermissions) {
+ AnubisAuthentication(final String token,
+ final String userIdentifier,
+ final String forApplicationName,
+ final String sourceApplicationName,
+ final Set<ApplicationPermission> applicationPermissions) {
authenticated = true;
this.token = token;
this.userIdentifier = userIdentifier;
this.forApplicationName = forApplicationName;
+ this.sourceApplicationName = sourceApplicationName;
this.applicationPermissions = Collections.unmodifiableSet(new HashSet<>(applicationPermissions));
}
@@ -62,7 +67,7 @@
@Override
public AnubisPrincipal getPrincipal() {
- return new AnubisPrincipal(userIdentifier, forApplicationName);
+ return new AnubisPrincipal(userIdentifier, forApplicationName, sourceApplicationName);
}
@Override
diff --git a/library/src/main/java/io/mifos/anubis/security/AnubisPrincipal.java b/library/src/main/java/io/mifos/anubis/security/AnubisPrincipal.java
index 5b2a9bd..f0c0da2 100644
--- a/library/src/main/java/io/mifos/anubis/security/AnubisPrincipal.java
+++ b/library/src/main/java/io/mifos/anubis/security/AnubisPrincipal.java
@@ -24,10 +24,12 @@
public class AnubisPrincipal {
private final String user;
private final String forApplicationName;
+ private final String sourceApplicationName;
- AnubisPrincipal(String user, String forApplicationName) {
+ AnubisPrincipal(String user, String forApplicationName, String sourceApplicationName) {
this.user = user;
this.forApplicationName = forApplicationName;
+ this.sourceApplicationName = sourceApplicationName;
}
public String getUser() {
@@ -38,6 +40,10 @@
return forApplicationName;
}
+ public String getSourceApplicationName() {
+ return sourceApplicationName;
+ }
+
@Override
public boolean equals(Object o) {
if (this == o) return true;
diff --git a/library/src/main/java/io/mifos/anubis/security/GuestAuthenticator.java b/library/src/main/java/io/mifos/anubis/security/GuestAuthenticator.java
index 12b2ce4..3a2e00e 100644
--- a/library/src/main/java/io/mifos/anubis/security/GuestAuthenticator.java
+++ b/library/src/main/java/io/mifos/anubis/security/GuestAuthenticator.java
@@ -52,6 +52,11 @@
logger.info("Guest access \"authenticated\" successfully.", user);
- return new AnubisAuthentication(null, RoleConstants.GUEST_USER_IDENTIFIER, applicationName.toString(), permissions);
+ return new AnubisAuthentication(
+ null,
+ RoleConstants.GUEST_USER_IDENTIFIER,
+ applicationName.toString(),
+ applicationName.toString(),
+ permissions);
}
}
diff --git a/library/src/main/java/io/mifos/anubis/security/SystemAuthenticator.java b/library/src/main/java/io/mifos/anubis/security/SystemAuthenticator.java
index 46c01e3..70ec3e7 100644
--- a/library/src/main/java/io/mifos/anubis/security/SystemAuthenticator.java
+++ b/library/src/main/java/io/mifos/anubis/security/SystemAuthenticator.java
@@ -78,7 +78,12 @@
logger.info("System token for user {}, with key timestamp {} authenticated successfully.", user, keyTimestamp);
- return new AnubisAuthentication(TokenConstants.PREFIX + token, user, result.getBody().getAudience(), permissions);
+ return new AnubisAuthentication(
+ TokenConstants.PREFIX + token,
+ user,
+ result.getBody().getAudience(),
+ TokenType.SYSTEM.getIssuer(),
+ permissions);
}
catch (final JwtException e) {
logger.debug("token = {}", token);
diff --git a/library/src/main/java/io/mifos/anubis/security/TenantAuthenticator.java b/library/src/main/java/io/mifos/anubis/security/TenantAuthenticator.java
index bd53f33..b575de0 100644
--- a/library/src/main/java/io/mifos/anubis/security/TenantAuthenticator.java
+++ b/library/src/main/java/io/mifos/anubis/security/TenantAuthenticator.java
@@ -78,6 +78,7 @@
@SuppressWarnings("unchecked") Jwt<Header, Claims> jwt = parser.parse(token);
final String serializedTokenContent = jwt.getBody().get(TokenConstants.JWT_CONTENT_CLAIM, String.class);
+ final String sourceApplication = jwt.getBody().get(TokenConstants.JWT_SOURCE_APPLICATION_CLAIM, String.class);
final TokenContent tokenContent = gson.fromJson(serializedTokenContent, TokenContent.class);
if (tokenContent == null)
throw AmitAuthenticationException.missingTokenContent();
@@ -88,7 +89,7 @@
logger.info("Tenant token for user {}, with key timestamp {} authenticated successfully.", user, keyTimestamp);
return new AnubisAuthentication(TokenConstants.PREFIX + token,
- jwt.getBody().getSubject(), applicationNameWithVersion, permissions
+ jwt.getBody().getSubject(), applicationNameWithVersion, sourceApplication, permissions
);
}
catch (final JwtException e) {
diff --git a/library/src/main/java/io/mifos/anubis/service/PermissionSegmentMatcher.java b/library/src/main/java/io/mifos/anubis/service/PermissionSegmentMatcher.java
index 1d856e4..84dbacb 100644
--- a/library/src/main/java/io/mifos/anubis/service/PermissionSegmentMatcher.java
+++ b/library/src/main/java/io/mifos/anubis/service/PermissionSegmentMatcher.java
@@ -59,8 +59,10 @@
return true;
else if (isUserIdentifierSegment())
return requestSegment.equals(principal.getUser());
- else if (isApplicationIdentifierSegment() && acceptTokenIntendedForForeignApplication)
+ else if (acceptTokenIntendedForForeignApplication && isApplicationIdentifierSegment())
return requestSegment.equals(principal.getForApplicationName());
+ else if (!acceptTokenIntendedForForeignApplication && isApplicationIdentifierSegment())
+ return requestSegment.equals(principal.getSourceApplicationName());
else if (isParameterSegment())
return isSu;
else
diff --git a/library/src/main/java/io/mifos/anubis/token/TenantAccessTokenSerializer.java b/library/src/main/java/io/mifos/anubis/token/TenantAccessTokenSerializer.java
index 29805f9..afdcc18 100644
--- a/library/src/main/java/io/mifos/anubis/token/TenantAccessTokenSerializer.java
+++ b/library/src/main/java/io/mifos/anubis/token/TenantAccessTokenSerializer.java
@@ -50,6 +50,7 @@
private String user;
private TokenContent tokenContent;
private long secondsToLive;
+ private String sourceApplication;
public Specification setKeyTimestamp(final String keyTimestamp) {
this.keyTimestamp = keyTimestamp;
@@ -66,6 +67,11 @@
return this;
}
+ public Specification setSourceApplication(final String applicationIdentifier) {
+ this.sourceApplication = applicationIdentifier;
+ return this;
+ }
+
public Specification setTokenContent(final TokenContent tokenContent) {
this.tokenContent = tokenContent;
return this;
@@ -89,12 +95,16 @@
if (specification.privateKey == null) {
throw new IllegalArgumentException("token signature privateKey must not be null.");
}
+ if (specification.sourceApplication == null) {
+ throw new IllegalArgumentException("token signature source application must not be null.");
+ }
final JwtBuilder jwtBuilder =
Jwts.builder()
.setSubject(specification.user)
.claim(TokenConstants.JWT_SIGNATURE_TIMESTAMP_CLAIM, specification.keyTimestamp)
.claim(TokenConstants.JWT_CONTENT_CLAIM, serializedTokenContent)
+ .claim(TokenConstants.JWT_SOURCE_APPLICATION_CLAIM, specification.sourceApplication)
.setIssuer(TokenType.TENANT.getIssuer())
.setIssuedAt(new Date(issued))
.signWith(SignatureAlgorithm.RS512, specification.privateKey);
diff --git a/library/src/test/java/io/mifos/anubis/security/ApplicationPermissionTest.java b/library/src/test/java/io/mifos/anubis/security/ApplicationPermissionTest.java
index 8780f92..0061b7b 100644
--- a/library/src/test/java/io/mifos/anubis/security/ApplicationPermissionTest.java
+++ b/library/src/test/java/io/mifos/anubis/security/ApplicationPermissionTest.java
@@ -47,6 +47,7 @@
private String requestedOperation = "GET";
private String user = "Nebamun";
private String forApplication = "graincounter-v1";
+ private String sourceApplication = "identity-v1";
private boolean expectedResult = true;
private TestCase(final String caseName) {
@@ -110,7 +111,7 @@
}
AnubisPrincipal getPrincipal() {
- return new AnubisPrincipal(user, forApplication);
+ return new AnubisPrincipal(user, forApplication, sourceApplication);
}
TestCase user(final String newVal)
@@ -125,6 +126,12 @@
return this;
}
+ TestCase sourceApplication(final String newVal)
+ {
+ this.sourceApplication = newVal;
+ return this;
+ }
+
boolean getExpectedResult() {
return expectedResult;
}
@@ -222,6 +229,33 @@
.allowedOperation(AllowedOperation.CHANGE)
.requestedOperation("PUT")
.expectedResult(true));
+ ret.add(new TestCase("access token acquired from application refresh token accessing its own resource.")
+ .permittedPath("/applications/{applicationidentifier}/permissions")
+ .requestedPath("/applications/bop-v1/permissions")
+ .acceptTokenIntendedForForeignApplication(false)
+ .calledApplication("identity-v1").forApplication("identity-v1")
+ .sourceApplication("bop-v1")
+ .allowedOperation(AllowedOperation.CHANGE)
+ .requestedOperation("POST")
+ .expectedResult(true));
+ ret.add(new TestCase("access token acquired from application refresh token accessing another apps resource.")
+ .permittedPath("/applications/{applicationidentifier}/permissions")
+ .requestedPath("/applications/bop-v1/permissions")
+ .acceptTokenIntendedForForeignApplication(false)
+ .calledApplication("identity-v1").forApplication("identity-v1")
+ .sourceApplication("bee-v1")
+ .allowedOperation(AllowedOperation.CHANGE)
+ .requestedOperation("POST")
+ .expectedResult(false));
+ ret.add(new TestCase("access token acquired from application refresh token accessing sub resource not allowed.")
+ .permittedPath("/applications/{applicationidentifier}/permissions")
+ .requestedPath("/applications/bop-v1/permissions/identity__v1__roles/users/Nebamun/enabled")
+ .acceptTokenIntendedForForeignApplication(false)
+ .calledApplication("identity-v1").forApplication("identity-v1")
+ .sourceApplication("bop-v1")
+ .allowedOperation(AllowedOperation.CHANGE)
+ .requestedOperation("PUT")
+ .expectedResult(false));
return ret;
}
diff --git a/library/src/test/java/io/mifos/anubis/token/TenantAccessTokenSerializerTest.java b/library/src/test/java/io/mifos/anubis/token/TenantAccessTokenSerializerTest.java
index cd396a7..ef050ef 100644
--- a/library/src/test/java/io/mifos/anubis/token/TenantAccessTokenSerializerTest.java
+++ b/library/src/test/java/io/mifos/anubis/token/TenantAccessTokenSerializerTest.java
@@ -57,6 +57,7 @@
= new TenantAccessTokenSerializer.Specification()
.setKeyTimestamp("1234567")
.setUser(USER)
+ .setSourceApplication("doo-v1")
.setTokenContent(EXAMPLE_TOKEN_CONTENT)
.setPrivateKey(keyPairHolder.privateKey())
.setSecondsToLive(SECONDS_TO_LIVE);
@@ -95,6 +96,7 @@
final TenantAccessTokenSerializer.Specification specification
= new TenantAccessTokenSerializer.Specification()
.setUser(USER)
+ .setSourceApplication("doo-v1")
.setTokenContent(EXAMPLE_TOKEN_CONTENT)
.setPrivateKey(keyPairHolder.privateKey())
.setSecondsToLive(0);
diff --git a/test/src/main/java/io/mifos/anubis/test/v1/SystemSecurityEnvironment.java b/test/src/main/java/io/mifos/anubis/test/v1/SystemSecurityEnvironment.java
index faed373..4e00dd9 100644
--- a/test/src/main/java/io/mifos/anubis/test/v1/SystemSecurityEnvironment.java
+++ b/test/src/main/java/io/mifos/anubis/test/v1/SystemSecurityEnvironment.java
@@ -109,6 +109,7 @@
{
return tenantAccessTokenSerializer.build(new TenantAccessTokenSerializer.Specification()
.setUser(userName)
+ .setSourceApplication("test-v1")
.setTokenContent(getTokenContentForStarEndpoint(applicationNames))
.setSecondsToLive(TimeUnit.HOURS.toSeconds(10))
.setKeyTimestamp(tenantKeyTimestamp())
@@ -124,6 +125,7 @@
new TenantAccessTokenSerializer.Specification().setPrivateKey(tenantPrivateKey())
.setKeyTimestamp(tenantKeyTimestamp())
.setSecondsToLive(100)
+ .setSourceApplication("test-v1")
.setUser(userName)
.setTokenContent(generateOnePermissionTokenContent(applicationName, uri, allowedOperation))
).getToken();