Access tokens can be acquired via refresh token passed as a parameter now (previously only cookies were allowed).
diff --git a/api/src/main/java/io/mifos/identity/api/v1/client/IdentityManager.java b/api/src/main/java/io/mifos/identity/api/v1/client/IdentityManager.java
index fee00ab..e385894 100644
--- a/api/src/main/java/io/mifos/identity/api/v1/client/IdentityManager.java
+++ b/api/src/main/java/io/mifos/identity/api/v1/client/IdentityManager.java
@@ -15,7 +15,6 @@
  */
 package io.mifos.identity.api.v1.client;
 
-import io.mifos.anubis.api.v1.TokenConstants;
 import io.mifos.anubis.api.v1.client.Anubis;
 import io.mifos.anubis.api.v1.domain.ApplicationSignatureSet;
 import io.mifos.anubis.api.v1.domain.Signature;
@@ -47,6 +46,11 @@
           produces = {MediaType.ALL_VALUE})
   Authentication refresh();
 
+  @RequestMapping(value = "/token?grant_type=refresh_token", method = RequestMethod.POST,
+          consumes = {MediaType.APPLICATION_JSON_VALUE},
+          produces = {MediaType.ALL_VALUE})
+  Authentication refresh(@RequestParam("refresh_token") String refreshToken);
+
   @RequestMapping(value = "/token/_current", method = RequestMethod.DELETE,
           consumes = {MediaType.APPLICATION_JSON_VALUE},
           produces = {MediaType.ALL_VALUE})
@@ -147,11 +151,6 @@
           produces = {MediaType.ALL_VALUE})
   void deleteApplication(@PathVariable("applicationidentifier") String applicationIdentifier);
 
-  @RequestMapping(value = "/token?grant_type=refresh_token", method = RequestMethod.POST,
-          consumes = {MediaType.APPLICATION_JSON_VALUE},
-          produces = {MediaType.ALL_VALUE})
-  Authentication refresh(@CookieValue(TokenConstants.REFRESH_TOKEN_COOKIE_NAME) String refreshToken);
-
   @RequestMapping(value = "/applications/{applicationidentifier}/permissions", method = RequestMethod.POST,
           consumes = {MediaType.APPLICATION_JSON_VALUE},
           produces = {MediaType.ALL_VALUE})
diff --git a/component-test/src/main/java/AbstractComponentTest.java b/component-test/src/main/java/AbstractComponentTest.java
index ce69ea8..26761ed 100644
--- a/component-test/src/main/java/AbstractComponentTest.java
+++ b/component-test/src/main/java/AbstractComponentTest.java
@@ -14,12 +14,14 @@
  * limitations under the License.
  */
 import io.mifos.anubis.api.v1.domain.AllowedOperation;
+import io.mifos.anubis.api.v1.domain.Signature;
 import io.mifos.anubis.test.v1.TenantApplicationSecurityEnvironmentTestRule;
 import io.mifos.core.api.config.EnableApiFactory;
 import io.mifos.core.api.context.AutoGuest;
 import io.mifos.core.api.context.AutoUserContext;
 import io.mifos.core.api.util.ApiFactory;
 import io.mifos.core.api.util.UserContextHolder;
+import io.mifos.core.lang.security.RsaKeyPairFactory;
 import io.mifos.core.test.env.TestEnvironment;
 import io.mifos.core.test.fixture.TenantDataStoreContextTestRule;
 import io.mifos.core.test.fixture.cassandra.CassandraInitializer;
@@ -28,8 +30,11 @@
 import io.mifos.identity.api.v1.PermittableGroupIds;
 import io.mifos.identity.api.v1.client.IdentityManager;
 import io.mifos.identity.api.v1.domain.*;
+import io.mifos.identity.api.v1.events.ApplicationPermissionEvent;
+import io.mifos.identity.api.v1.events.ApplicationSignatureEvent;
 import io.mifos.identity.api.v1.events.EventConstants;
 import io.mifos.identity.config.IdentityServiceConfig;
+import org.apache.commons.lang.RandomStringUtils;
 import org.junit.After;
 import org.junit.Assert;
 import org.junit.ClassRule;
@@ -221,4 +226,49 @@
     }
     return new AutoUserContext(userId, authentication.getAccessToken());
   }
+
+  private String createTestApplicationName()
+  {
+    return "test" + RandomStringUtils.randomNumeric(3) + "-v1";
+  }
+
+  static class ApplicationSignatureTestData {
+    private final String applicationIdentifier;
+    private final RsaKeyPairFactory.KeyPairHolder keyPair;
+
+    ApplicationSignatureTestData(final String applicationIdentifier, final RsaKeyPairFactory.KeyPairHolder keyPair) {
+      this.applicationIdentifier = applicationIdentifier;
+      this.keyPair = keyPair;
+    }
+
+    String getApplicationIdentifier() {
+      return applicationIdentifier;
+    }
+
+    RsaKeyPairFactory.KeyPairHolder getKeyPair() {
+      return keyPair;
+    }
+
+    String getKeyTimestamp() {
+      return keyPair.getTimestamp();
+    }
+  }
+
+  ApplicationSignatureTestData setApplicationSignature() throws InterruptedException {
+    final String testApplicationName = createTestApplicationName();
+    final RsaKeyPairFactory.KeyPairHolder keyPair = RsaKeyPairFactory.createKeyPair();
+    final Signature signature = new Signature(keyPair.getPublicKeyMod(), keyPair.getPublicKeyExp());
+
+    getTestSubject().setApplicationSignature(testApplicationName, keyPair.getTimestamp(), signature);
+
+    Assert.assertTrue(eventRecorder.wait(EventConstants.OPERATION_PUT_APPLICATION_SIGNATURE, new ApplicationSignatureEvent(testApplicationName, keyPair.getTimestamp())));
+    return new ApplicationSignatureTestData(testApplicationName, keyPair);
+  }
+
+  void createApplicationPermission(final String applicationIdentifier, final Permission permission) throws InterruptedException {
+    getTestSubject().createApplicationPermission(applicationIdentifier, permission);
+    Assert.assertTrue(eventRecorder.wait(EventConstants.OPERATION_POST_APPLICATION_PERMISSION,
+            new ApplicationPermissionEvent(applicationIdentifier,
+                    permission.getPermittableEndpointGroupIdentifier())));
+  }
 }
diff --git a/component-test/src/main/java/TestApplications.java b/component-test/src/main/java/TestApplications.java
index 94062c3..df185a6 100644
--- a/component-test/src/main/java/TestApplications.java
+++ b/component-test/src/main/java/TestApplications.java
@@ -14,22 +14,20 @@
  * limitations under the License.
  */
 
-import io.mifos.anubis.api.v1.TokenConstants;
 import io.mifos.anubis.api.v1.domain.AllowedOperation;
-import io.mifos.anubis.api.v1.domain.Signature;
 import io.mifos.anubis.token.TenantRefreshTokenSerializer;
 import io.mifos.anubis.token.TokenSerializationResult;
 import io.mifos.core.api.context.AutoUserContext;
-import io.mifos.core.api.util.FeignTargetWithCookieJar;
 import io.mifos.core.api.util.NotFoundException;
-import io.mifos.core.lang.security.RsaKeyPairFactory;
 import io.mifos.identity.api.v1.PermittableGroupIds;
-import io.mifos.identity.api.v1.client.IdentityManager;
 import io.mifos.identity.api.v1.domain.Authentication;
 import io.mifos.identity.api.v1.domain.CallEndpointSet;
 import io.mifos.identity.api.v1.domain.Permission;
 import io.mifos.identity.api.v1.domain.User;
-import io.mifos.identity.api.v1.events.*;
+import io.mifos.identity.api.v1.events.ApplicationCallEndpointSetEvent;
+import io.mifos.identity.api.v1.events.ApplicationPermissionEvent;
+import io.mifos.identity.api.v1.events.ApplicationPermissionUserEvent;
+import io.mifos.identity.api.v1.events.EventConstants;
 import org.apache.commons.lang.RandomStringUtils;
 import org.junit.Assert;
 import org.junit.Test;
@@ -37,7 +35,6 @@
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
-import java.util.concurrent.TimeUnit;
 
 /**
  * @author Myrle Krantz
@@ -71,9 +68,7 @@
       identityManagementPermission.setPermittableEndpointGroupIdentifier(PermittableGroupIds.IDENTITY_MANAGEMENT);
       identityManagementPermission.setAllowedOperations(Collections.singleton(AllowedOperation.READ));
 
-      getTestSubject().createApplicationPermission(appPlusSig.getApplicationIdentifier(), identityManagementPermission);
-      Assert.assertTrue(eventRecorder.wait(EventConstants.OPERATION_POST_APPLICATION_PERMISSION,
-              new ApplicationPermissionEvent(appPlusSig.getApplicationIdentifier(), PermittableGroupIds.IDENTITY_MANAGEMENT)));
+      createApplicationPermission(appPlusSig.getApplicationIdentifier(), identityManagementPermission);
 
       {
         final List<Permission> applicationPermissions = getTestSubject().getApplicationPermissions(appPlusSig.getApplicationIdentifier());
@@ -87,9 +82,8 @@
       roleManagementPermission.setPermittableEndpointGroupIdentifier(PermittableGroupIds.ROLE_MANAGEMENT);
       roleManagementPermission.setAllowedOperations(Collections.singleton(AllowedOperation.READ));
 
-      getTestSubject().createApplicationPermission(appPlusSig.getApplicationIdentifier(), roleManagementPermission);
-      Assert.assertTrue(eventRecorder.wait(EventConstants.OPERATION_POST_APPLICATION_PERMISSION,
-              new ApplicationPermissionEvent(appPlusSig.getApplicationIdentifier(), PermittableGroupIds.ROLE_MANAGEMENT)));
+      createApplicationPermission(appPlusSig.getApplicationIdentifier(), roleManagementPermission);
+
       {
         final List<Permission> applicationPermissions = getTestSubject().getApplicationPermissions(appPlusSig.getApplicationIdentifier());
         Assert.assertTrue(applicationPermissions.contains(identityManagementPermission));
@@ -145,10 +139,7 @@
               PermittableGroupIds.ROLE_MANAGEMENT,
               Collections.singleton(AllowedOperation.READ));
 
-      getTestSubject().createApplicationPermission(appPlusSig.getApplicationIdentifier(), identityManagementPermission);
-      Assert.assertTrue(eventRecorder.wait(EventConstants.OPERATION_POST_APPLICATION_PERMISSION,
-              new ApplicationPermissionEvent(appPlusSig.getApplicationIdentifier(),
-                      identityManagementPermission.getPermittableEndpointGroupIdentifier())));
+      createApplicationPermission(appPlusSig.getApplicationIdentifier(), identityManagementPermission);
     }
 
     final String user1Password;
@@ -274,14 +265,9 @@
                  = tenantApplicationSecurityEnvironment.createAutoSeshatContext()) {
       appPlusSig = setApplicationSignature();
 
-      getTestSubject().createApplicationPermission(appPlusSig.getApplicationIdentifier(), rolePermission);
-      getTestSubject().createApplicationPermission(appPlusSig.getApplicationIdentifier(), userPermission);
-      Assert.assertTrue(eventRecorder.wait(EventConstants.OPERATION_POST_APPLICATION_PERMISSION,
-              new ApplicationPermissionEvent(appPlusSig.getApplicationIdentifier(),
-                      rolePermission.getPermittableEndpointGroupIdentifier())));
-      Assert.assertTrue(eventRecorder.wait(EventConstants.OPERATION_POST_APPLICATION_PERMISSION,
-              new ApplicationPermissionEvent(appPlusSig.getApplicationIdentifier(),
-                      userPermission.getPermittableEndpointGroupIdentifier())));
+      createApplicationPermission(appPlusSig.getApplicationIdentifier(), rolePermission);
+      createApplicationPermission(appPlusSig.getApplicationIdentifier(), userPermission);
+
       getTestSubject().createApplicationCallEndpointSet(
               appPlusSig.getApplicationIdentifier(),
               new CallEndpointSet(CALL_ENDPOINT_SET_IDENTIFIER,
@@ -325,53 +311,11 @@
                     .setSourceApplication(appPlusSig.getApplicationIdentifier()));
 
 
-    final FeignTargetWithCookieJar<IdentityManager> identityManagerWithCookieJar
-            = apiFactory.createWithCookieJar(IdentityManager.class, testEnvironment.serverURI());
-
-    identityManagerWithCookieJar.putCookie("/token", TokenConstants.REFRESH_TOKEN_COOKIE_NAME, tokenSerializationResult.getToken());
-    final Authentication applicationAuthentication = identityManagerWithCookieJar.getFeignTarget().refresh();
+    final Authentication applicationAuthentication = getTestSubject().refresh(tokenSerializationResult.getToken());
 
     try (final AutoUserContext ignored = new AutoUserContext(userid, applicationAuthentication.getAccessToken())) {
       final List<User> users = getTestSubject().getUsers();
       Assert.assertFalse(users.isEmpty());
     }
   }
-
-  private String createTestApplicationName()
-  {
-    return "test" + RandomStringUtils.randomNumeric(3) + "-v1";
-  }
-
-  static class ApplicationSignatureTestData {
-    private final String applicationIdentifier;
-    private final RsaKeyPairFactory.KeyPairHolder keyPair;
-
-    ApplicationSignatureTestData(final String applicationIdentifier, final RsaKeyPairFactory.KeyPairHolder keyPair) {
-      this.applicationIdentifier = applicationIdentifier;
-      this.keyPair = keyPair;
-    }
-
-    String getApplicationIdentifier() {
-      return applicationIdentifier;
-    }
-
-    RsaKeyPairFactory.KeyPairHolder getKeyPair() {
-      return keyPair;
-    }
-
-    String getKeyTimestamp() {
-      return keyPair.getTimestamp();
-    }
-  }
-
-  private ApplicationSignatureTestData setApplicationSignature() throws InterruptedException {
-    final String testApplicationName = createTestApplicationName();
-    final RsaKeyPairFactory.KeyPairHolder keyPair = RsaKeyPairFactory.createKeyPair();
-    final Signature signature = new Signature(keyPair.getPublicKeyMod(), keyPair.getPublicKeyExp());
-
-    getTestSubject().setApplicationSignature(testApplicationName, keyPair.getTimestamp(), signature);
-
-    Assert.assertTrue(eventRecorder.wait(EventConstants.OPERATION_PUT_APPLICATION_SIGNATURE, new ApplicationSignatureEvent(testApplicationName, keyPair.getTimestamp())));
-    return new ApplicationSignatureTestData(testApplicationName, keyPair);
-  }
 }
diff --git a/component-test/src/main/java/TestRefreshToken.java b/component-test/src/main/java/TestRefreshToken.java
index 1ff7a3f..b6f3894 100644
--- a/component-test/src/main/java/TestRefreshToken.java
+++ b/component-test/src/main/java/TestRefreshToken.java
@@ -14,18 +14,27 @@
  * limitations under the License.
  */
 
+import io.mifos.anubis.api.v1.TokenConstants;
+import io.mifos.anubis.token.TenantRefreshTokenSerializer;
+import io.mifos.anubis.token.TokenSerializationResult;
 import io.mifos.core.api.context.AutoUserContext;
+import io.mifos.core.api.util.FeignTargetWithCookieJar;
 import io.mifos.core.api.util.InvalidTokenException;
+import io.mifos.core.api.util.NotFoundException;
 import io.mifos.core.test.domain.TimeStampChecker;
 import io.mifos.core.test.env.TestEnvironment;
 import io.mifos.core.test.fixture.TenantDataStoreTestContext;
+import io.mifos.identity.api.v1.client.IdentityManager;
 import io.mifos.identity.api.v1.domain.Authentication;
 import io.mifos.identity.api.v1.domain.Password;
+import io.mifos.identity.api.v1.domain.Permission;
+import io.mifos.identity.api.v1.domain.User;
 import org.junit.Assert;
 import org.junit.BeforeClass;
 import org.junit.Test;
 
 import java.time.Duration;
+import java.util.List;
 import java.util.concurrent.TimeUnit;
 
 /**
@@ -109,4 +118,65 @@
     postRefreshAccessTokenTimeStampChecker.assertCorrect(refreshedAuthentication.getAccessTokenExpiration());
     refreshTokenTimeStampChecker.assertCorrect(refreshedAuthentication.getRefreshTokenExpiration());
   }
+
+  @Test
+  public void bothRefreshMethodsShouldProduceSamePermissions() throws InterruptedException {
+    final Permission userPermission = buildUserPermission();
+    final ApplicationSignatureTestData appPlusSig;
+    try (final AutoUserContext ignored
+                 = tenantApplicationSecurityEnvironment.createAutoSeshatContext()) {
+      appPlusSig = setApplicationSignature();
+      createApplicationPermission(appPlusSig.getApplicationIdentifier(), userPermission);
+    }
+
+    try (final AutoUserContext ignored = loginAdmin()) {
+      getTestSubject().setApplicationPermissionEnabledForUser(
+              appPlusSig.getApplicationIdentifier(),
+              userPermission.getPermittableEndpointGroupIdentifier(),
+              ADMIN_IDENTIFIER,
+              true);
+    }
+
+    final TenantRefreshTokenSerializer refreshTokenSerializer = new TenantRefreshTokenSerializer();
+
+    final TokenSerializationResult tokenSerializationResult =
+            refreshTokenSerializer.build(new TenantRefreshTokenSerializer.Specification()
+                    .setUser(ADMIN_IDENTIFIER)
+                    .setSecondsToLive(30)
+                    .setKeyTimestamp(appPlusSig.getKeyTimestamp())
+                    .setPrivateKey(appPlusSig.getKeyPair().privateKey())
+                    .setSourceApplication(appPlusSig.getApplicationIdentifier()));
+
+    final FeignTargetWithCookieJar<IdentityManager> identityManagerWithCookieJar
+            = apiFactory.createWithCookieJar(IdentityManager.class, testEnvironment.serverURI());
+
+    identityManagerWithCookieJar.putCookie("/token", TokenConstants.REFRESH_TOKEN_COOKIE_NAME, tokenSerializationResult.getToken());
+
+    final Authentication applicationAuthenticationViaCookie = identityManagerWithCookieJar.getFeignTarget().refresh();
+
+    final Authentication applicationAuthenticationViaParam = getTestSubject().refresh(tokenSerializationResult.getToken());
+
+    try (final AutoUserContext ignored = new AutoUserContext(ADMIN_IDENTIFIER, applicationAuthenticationViaCookie.getAccessToken()))
+    {
+      checkAccessToUsersAndOnlyUsers();
+    }
+
+    try (final AutoUserContext ignored = new AutoUserContext(ADMIN_IDENTIFIER, applicationAuthenticationViaParam.getAccessToken()))
+    {
+      checkAccessToUsersAndOnlyUsers();
+    }
+
+  }
+
+  private void checkAccessToUsersAndOnlyUsers() {
+    final List<User> users = getTestSubject().getUsers();
+    Assert.assertFalse(users.isEmpty());
+
+    try {
+      getTestSubject().getRoles();
+      Assert.fail("Shouldn't be able to get roles with token for application for which roles are not permitted.");
+    }
+    catch (final NotFoundException ignored2) { }
+  }
+
 }
diff --git a/service/src/main/java/io/mifos/identity/rest/AuthorizationRestController.java b/service/src/main/java/io/mifos/identity/rest/AuthorizationRestController.java
index c214b8e..c1ff8f5 100644
--- a/service/src/main/java/io/mifos/identity/rest/AuthorizationRestController.java
+++ b/service/src/main/java/io/mifos/identity/rest/AuthorizationRestController.java
@@ -39,6 +39,7 @@
 import org.springframework.web.bind.annotation.*;
 import org.springframework.web.util.WebUtils;
 
+import javax.annotation.Nullable;
 import javax.servlet.http.Cookie;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
@@ -82,10 +83,11 @@
       final HttpServletRequest request,
       @RequestParam("grant_type") final String grantType,
       @RequestParam(value = "username", required = false) final String username,
-      @RequestParam(value = "password", required = false) final String password) throws InterruptedException {
+      @RequestParam(value = "password", required = false) final String password,
+      @RequestParam(value = "refresh_token", required = false) final String refreshTokenParam) throws InterruptedException {
     switch (grantType) {
       case "refresh_token": {
-        final String refreshToken = getRefreshToken(request);
+        final String refreshToken = getRefreshToken(refreshTokenParam, request);
 
         try {
           final AuthenticationCommandResponse authenticationCommandResponse
@@ -134,7 +136,10 @@
     return ResponseEntity.ok().build();
   }
 
-  private String getRefreshToken(final HttpServletRequest request) {
+  private String getRefreshToken(final @Nullable String refreshTokenParam, final HttpServletRequest request) {
+    if (refreshTokenParam != null)
+      return refreshTokenParam;
+
     final Cookie refreshTokenCookie = WebUtils.getCookie(request, TokenConstants.REFRESH_TOKEN_COOKIE_NAME);
     if (refreshTokenCookie == null)
       throw ServiceException.badRequest("One (and only one) refresh token cookie must be included in the request if the grant_type is refresh_token");