Transporting the application source of a refresh token to its access token, and validating that application's permission.
diff --git a/component-test/src/main/java/AbstractComponentTest.java b/component-test/src/main/java/AbstractComponentTest.java
index 26761ed..e246a96 100644
--- a/component-test/src/main/java/AbstractComponentTest.java
+++ b/component-test/src/main/java/AbstractComponentTest.java
@@ -200,6 +200,13 @@
     return permission;
   }
 
+  Permission buildApplicationSelfPermission() {
+    final Permission permission = new Permission();
+    permission.setAllowedOperations(AllowedOperation.ALL);
+    permission.setPermittableEndpointGroupIdentifier(PermittableGroupIds.APPLICATION_SELF_MANAGEMENT);
+    return permission;
+  }
+
   String createRoleManagementRole() throws InterruptedException {
     return createRole(buildRolePermission());
   }
@@ -208,6 +215,10 @@
     return createRole(buildSelfPermission());
   }
 
+  String createApplicationSelfManagementRole() throws InterruptedException {
+    return createRole(buildApplicationSelfPermission());
+  }
+
   String createRole(final Permission... permission) throws InterruptedException {
     final String roleIdentifier = generateRoleIdentifier();
     final Role role = buildRole(roleIdentifier, permission);
diff --git a/component-test/src/main/java/TestApplications.java b/component-test/src/main/java/TestApplications.java
index df185a6..a4e5a77 100644
--- a/component-test/src/main/java/TestApplications.java
+++ b/component-test/src/main/java/TestApplications.java
@@ -318,4 +318,69 @@
       Assert.assertFalse(users.isEmpty());
     }
   }
+
+  @Test
+  public void applicationIssuedRefreshTokenToCreatePermissionRequest() throws InterruptedException {
+    final ApplicationSignatureTestData appPlusSig;
+    try (final AutoUserContext ignored
+                 = tenantApplicationSecurityEnvironment.createAutoSeshatContext()) {
+      appPlusSig = setApplicationSignature();
+      createApplicationPermission(appPlusSig.getApplicationIdentifier(), buildApplicationSelfPermission());
+    }
+
+    final String userid;
+    final String userid2;
+    final String userPassword;
+    try (final AutoUserContext ignored = loginAdmin()) {
+
+      final String roleId = createApplicationSelfManagementRole();
+
+      userPassword = RandomStringUtils.randomAlphanumeric(5);
+      userid = createUserWithNonexpiredPassword(userPassword, roleId);
+      userid2 = createUserWithNonexpiredPassword(userPassword, roleId);
+
+    }
+
+    try (final AutoUserContext ignored = loginUser(userid, userPassword)) {
+      getTestSubject().setApplicationPermissionEnabledForUser(appPlusSig.getApplicationIdentifier(), PermittableGroupIds.APPLICATION_SELF_MANAGEMENT, userid, true);
+    }
+
+
+    final TokenSerializationResult tokenSerializationResult =
+            new TenantRefreshTokenSerializer().build(new TenantRefreshTokenSerializer.Specification()
+                    .setUser(userid)
+                    .setSecondsToLive(30)
+                    .setKeyTimestamp(appPlusSig.getKeyTimestamp())
+                    .setPrivateKey(appPlusSig.getKeyPair().privateKey())
+                    .setSourceApplication(appPlusSig.getApplicationIdentifier()));
+
+
+    final Authentication applicationAuthentication = getTestSubject().refresh(tokenSerializationResult.getToken());
+
+    try (final AutoUserContext ignored = new AutoUserContext(userid, applicationAuthentication.getAccessToken())) {
+      final Permission rolePermission = buildRolePermission();
+      createApplicationPermission(appPlusSig.getApplicationIdentifier(), rolePermission);
+
+      final List<Permission> appPermissions = getTestSubject().getApplicationPermissions(
+              appPlusSig.getApplicationIdentifier());
+
+      Assert.assertTrue(appPermissions.contains(rolePermission));
+
+      try {
+        getTestSubject().setApplicationPermissionEnabledForUser(appPlusSig.getApplicationIdentifier(), rolePermission.getPermittableEndpointGroupIdentifier(), userid2, true);
+        Assert.fail("This call to create enable permission for another user should've failed.");
+      }
+      catch (final NotFoundException ignored2) {
+
+      }
+
+      try {
+        createApplicationPermission("madeupname-v1", rolePermission);
+        Assert.fail("This call to create application permission should've failed.");
+      }
+      catch (final NotFoundException ignored2) {
+
+      }
+    }
+  }
 }
diff --git a/service/src/main/java/io/mifos/identity/internal/command/handler/AuthenticationCommandHandler.java b/service/src/main/java/io/mifos/identity/internal/command/handler/AuthenticationCommandHandler.java
index b674b4e..3dd9c43 100644
--- a/service/src/main/java/io/mifos/identity/internal/command/handler/AuthenticationCommandHandler.java
+++ b/service/src/main/java/io/mifos/identity/internal/command/handler/AuthenticationCommandHandler.java
@@ -277,7 +277,8 @@
     final TokenSerializationResult accessToken = getAuthenticationResponse(
             user.getIdentifier(),
             tokenPermissions,
-            privateSignature);
+            privateSignature,
+            sourceApplicationName);
 
     return new AuthenticationCommandResponse(
             accessToken.getToken(), DateConverter.toIsoString(accessToken.getExpiration()),
@@ -326,7 +327,8 @@
   private TokenSerializationResult getAuthenticationResponse(
           final String userIdentifier,
           final Set<TokenPermission> tokenPermissions,
-          final PrivateSignatureEntity privateSignatureEntity) {
+          final PrivateSignatureEntity privateSignatureEntity,
+          final String sourceApplication) {
 
     final PrivateKey privateKey = new RsaPrivateKeyBuilder()
           .setPrivateKeyExp(privateSignatureEntity.getPrivateKeyExp())
@@ -339,7 +341,8 @@
               .setPrivateKey(privateKey)
               .setTokenContent(new TokenContent(new ArrayList<>(tokenPermissions)))
               .setSecondsToLive(accessTtl)
-              .setUser(userIdentifier);
+              .setUser(userIdentifier)
+              .setSourceApplication(sourceApplication);
 
       return tenantAccessTokenSerializer.build(x);
   }
diff --git a/service/src/main/java/io/mifos/identity/internal/command/handler/Provisioner.java b/service/src/main/java/io/mifos/identity/internal/command/handler/Provisioner.java
index 2353947..ecf1c61 100644
--- a/service/src/main/java/io/mifos/identity/internal/command/handler/Provisioner.java
+++ b/service/src/main/java/io/mifos/identity/internal/command/handler/Provisioner.java
@@ -120,10 +120,13 @@
       createPermittablesGroup(PermittableGroupIds.ROLE_MANAGEMENT, "/roles/*", "/permittablegroups/*");
       createPermittablesGroup(PermittableGroupIds.IDENTITY_MANAGEMENT, "/users/*");
       createPermittablesGroup(PermittableGroupIds.SELF_MANAGEMENT, "/users/{useridentifier}/password", "/applications/*/permissions/*/users/{useridentifier}/enabled");
+      createPermittablesGroup(PermittableGroupIds.APPLICATION_SELF_MANAGEMENT, "/applications/{applicationidentifier}/permissions");
 
       final List<PermissionType> permissions = new ArrayList<>();
       permissions.add(fullAccess(PermittableGroupIds.ROLE_MANAGEMENT));
       permissions.add(fullAccess(PermittableGroupIds.IDENTITY_MANAGEMENT));
+      permissions.add(fullAccess(PermittableGroupIds.SELF_MANAGEMENT));
+      permissions.add(fullAccess(PermittableGroupIds.APPLICATION_SELF_MANAGEMENT));
 
       final RoleEntity suRole = new RoleEntity();
       suRole.setIdentifier(IdentityConstants.SU_ROLE);
diff --git a/service/src/main/java/io/mifos/identity/rest/ApplicationRestController.java b/service/src/main/java/io/mifos/identity/rest/ApplicationRestController.java
index 8c83a9c..a3529aa 100644
--- a/service/src/main/java/io/mifos/identity/rest/ApplicationRestController.java
+++ b/service/src/main/java/io/mifos/identity/rest/ApplicationRestController.java
@@ -22,6 +22,7 @@
 import io.mifos.anubis.api.v1.validation.ValidKeyTimestamp;
 import io.mifos.core.command.gateway.CommandGateway;
 import io.mifos.core.lang.ServiceException;
+import io.mifos.identity.api.v1.PermittableGroupIds;
 import io.mifos.identity.api.v1.domain.Permission;
 import io.mifos.identity.internal.command.CreateApplicationPermissionCommand;
 import io.mifos.identity.internal.command.DeleteApplicationCommand;
@@ -112,7 +113,7 @@
           consumes = {MediaType.ALL_VALUE},
           produces = {MediaType.APPLICATION_JSON_VALUE})
   @Permittable(value = AcceptedTokenType.SYSTEM)
-  @Permittable(groupId = io.mifos.identity.api.v1.PermittableGroupIds.APPLICATION_SELF_MANAGEMENT)
+  @Permittable(value = AcceptedTokenType.TENANT, permittedEndpoint = "applications/{applicationidentifier}/permissions", groupId = PermittableGroupIds.APPLICATION_SELF_MANAGEMENT)
   public @ResponseBody
   ResponseEntity<Void>
   createApplicationPermission(@PathVariable("applicationidentifier") @Nonnull String applicationIdentifier,
@@ -127,6 +128,7 @@
           consumes = {MediaType.ALL_VALUE},
           produces = {MediaType.APPLICATION_JSON_VALUE})
   @Permittable(value = AcceptedTokenType.SYSTEM)
+  @Permittable(value = AcceptedTokenType.TENANT, permittedEndpoint = "applications/{applicationidentifier}/permissions", groupId = PermittableGroupIds.APPLICATION_SELF_MANAGEMENT)
   public @ResponseBody
   ResponseEntity<List<Permission>>
   getApplicationPermissions(@PathVariable("applicationidentifier") @Nonnull String applicationIdentifier) {