Implemented OAuth2 request token with resource owner password grant.
Change-Id: I516d5adf0091d711ff183470b3f0de8a6e502270
diff --git a/full/src/test/java/de/ids_mannheim/korap/web/controller/OAuth2ClientControllerTest.java b/full/src/test/java/de/ids_mannheim/korap/web/controller/OAuth2ClientControllerTest.java
index 6e1904b..66d610f 100644
--- a/full/src/test/java/de/ids_mannheim/korap/web/controller/OAuth2ClientControllerTest.java
+++ b/full/src/test/java/de/ids_mannheim/korap/web/controller/OAuth2ClientControllerTest.java
@@ -53,7 +53,7 @@
}
}
}
-
+
private ClientResponse testRegisterConfidentialClient ()
throws KustvaktException {
@@ -121,6 +121,29 @@
testDeregisterPublicClient(clientId);
}
+ @Test
+ public void testRegisterNativeClient () throws UniformInterfaceException,
+ ClientHandlerException, KustvaktException {
+ OAuth2ClientJson json = new OAuth2ClientJson();
+ json.setName("NativeClient");
+ json.setType(OAuth2ClientType.PUBLIC);
+ json.setUrl("http://korap.ids-mannheim.de/native");
+ json.setRedirectURI("https://korap.ids-mannheim.de/native/redirect");
+
+ ClientResponse response = resource().path("oauth2").path("client")
+ .path("register")
+ .header(Attributes.AUTHORIZATION,
+ handler.createBasicAuthorizationHeaderValue(username,
+ "pass"))
+ .header(HttpHeaders.X_FORWARDED_FOR, "149.27.0.32")
+ .header(HttpHeaders.CONTENT_TYPE, ContentType.APPLICATION_JSON)
+ .entity(json).post(ClientResponse.class);
+
+ assertEquals(Status.OK.getStatusCode(), response.getStatus());
+
+ //EM: need to check native
+ }
+
private void testDeregisterPublicClient (String clientId)
throws UniformInterfaceException, ClientHandlerException,
KustvaktException {
@@ -178,13 +201,13 @@
String entity = response.getEntity(String.class);
assertEquals(Status.UNAUTHORIZED.getStatusCode(), response.getStatus());
-
+
JsonNode node = JsonUtils.readTree(entity);
assertEquals(OAuthError.TokenResponse.INVALID_CLIENT,
node.at("/error").asText());
assertEquals("Invalid client credentials.",
node.at("/error_description").asText());
-
+
checkWWWAuthenticateHeader(response);
}
}
diff --git a/full/src/test/java/de/ids_mannheim/korap/web/controller/OAuth2ControllerTest.java b/full/src/test/java/de/ids_mannheim/korap/web/controller/OAuth2ControllerTest.java
index 46671ff..956e3ed 100644
--- a/full/src/test/java/de/ids_mannheim/korap/web/controller/OAuth2ControllerTest.java
+++ b/full/src/test/java/de/ids_mannheim/korap/web/controller/OAuth2ControllerTest.java
@@ -48,6 +48,109 @@
.entity(form).post(ClientResponse.class);
}
+ private ClientResponse testRequestTokenPublicClient (
+ MultivaluedMap<String, String> form)
+ throws UniformInterfaceException, ClientHandlerException,
+ KustvaktException {
+ return resource().path("oauth2").path("token")
+ .header(HttpHeaders.X_FORWARDED_FOR, "149.27.0.32")
+ .header(HttpHeaders.CONTENT_TYPE,
+ ContentType.APPLICATION_FORM_URLENCODED)
+ .entity(form).post(ClientResponse.class);
+ }
+
+ @Test
+ public void testRequestTokenPasswordGrantConfidential ()
+ throws UniformInterfaceException, ClientHandlerException,
+ KustvaktException {
+ MultivaluedMap<String, String> form = new MultivaluedMapImpl();
+ form.add("grant_type", "password");
+
+ ClientResponse response = testRequestTokenConfidentialClient(form);
+ String entity = response.getEntity(String.class);
+
+ JsonNode node = JsonUtils.readTree(entity);
+ assertNotNull(node.at("/access_token").asText());
+ assertNotNull(node.at("/refresh_token").asText());
+ assertEquals(TokenType.BEARER.toString(),
+ node.at("/token_type").asText());
+ assertNotNull(node.at("/expires_in").asText());
+ }
+
+ @Test
+ public void testRequestTokenConfidentialMissingSecret ()
+ throws UniformInterfaceException, ClientHandlerException,
+ KustvaktException {
+
+ MultivaluedMap<String, String> form = new MultivaluedMapImpl();
+ form.add("grant_type", "password");
+ form.add("client_id", "fCBbQkAyYzI4NzUxMg==");
+
+ ClientResponse response = testRequestTokenPublicClient(form);
+ assertEquals(Status.UNAUTHORIZED.getStatusCode(), response.getStatus());
+
+ String entity = response.getEntity(String.class);
+ JsonNode node = JsonUtils.readTree(entity);
+ assertEquals(OAuthError.TokenResponse.INVALID_CLIENT,
+ node.at("/error").asText());
+ }
+
+ @Test
+ public void testRequestTokenPasswordGrantPublic ()
+ throws UniformInterfaceException, ClientHandlerException,
+ KustvaktException {
+ MultivaluedMap<String, String> form = new MultivaluedMapImpl();
+ form.add("grant_type", "password");
+ form.add("client_id", "iBr3LsTCxOj7D2o0A5m");
+
+ ClientResponse response = testRequestTokenPublicClient(form);
+ String entity = response.getEntity(String.class);
+
+ JsonNode node = JsonUtils.readTree(entity);
+ assertNotNull(node.at("/access_token").asText());
+ assertNotNull(node.at("/refresh_token").asText());
+ assertEquals(TokenType.BEARER.toString(),
+ node.at("/token_type").asText());
+ assertNotNull(node.at("/expires_in").asText());
+ }
+
+ @Test
+ public void testRequestTokenPasswordGrantMissingClientId ()
+ throws UniformInterfaceException, ClientHandlerException,
+ KustvaktException {
+ MultivaluedMap<String, String> form = new MultivaluedMapImpl();
+ form.add("grant_type", "password");
+
+ ClientResponse response = testRequestTokenPublicClient(form);
+ String entity = response.getEntity(String.class);
+ assertEquals(Status.BAD_REQUEST.getStatusCode(), response.getStatus());
+
+ JsonNode node = JsonUtils.readTree(entity);
+ assertEquals(OAuthError.TokenResponse.INVALID_REQUEST,
+ node.at("/error").asText());
+ assertEquals("client_id is missing",
+ node.at("/error_description").asText());
+ }
+
+ @Test
+ public void testRequestTokenPasswordGrantNonNative ()
+ throws UniformInterfaceException, ClientHandlerException,
+ KustvaktException {
+ MultivaluedMap<String, String> form = new MultivaluedMapImpl();
+ form.add("grant_type", "password");
+ form.add("client_id", "8bIDtZnH6NvRkW2Fq==");
+
+ ClientResponse response = testRequestTokenPublicClient(form);
+ String entity = response.getEntity(String.class);
+ assertEquals(Status.BAD_REQUEST.getStatusCode(), response.getStatus());
+
+ JsonNode node = JsonUtils.readTree(entity);
+ assertEquals(OAuthError.TokenResponse.UNAUTHORIZED_CLIENT,
+ node.at("/error").asText());
+ assertEquals("Password grant is not allowed for third party clients",
+ node.at("/error_description").asText());
+ }
+
@Test
public void testRequestTokenClientCredentialsGrant ()
throws UniformInterfaceException, ClientHandlerException,
diff --git a/full/src/test/java/de/ids_mannheim/korap/web/controller/UserGroupControllerTest.java b/full/src/test/java/de/ids_mannheim/korap/web/controller/UserGroupControllerTest.java
index 5da4c40..17b2b51 100644
--- a/full/src/test/java/de/ids_mannheim/korap/web/controller/UserGroupControllerTest.java
+++ b/full/src/test/java/de/ids_mannheim/korap/web/controller/UserGroupControllerTest.java
@@ -654,7 +654,7 @@
JsonNode node = JsonUtils.readTree(entity);
assertEquals(Status.BAD_REQUEST.getStatusCode(), response.getStatus());
- assertEquals(StatusCodes.MISSING_ARGUMENT,
+ assertEquals(StatusCodes.MISSING_PARAMETER,
node.at("/errors/0/0").asInt());
assertEquals("groupId", node.at("/errors/0/1").asText());
assertEquals("0", node.at("/errors/0/2").asText());
@@ -844,7 +844,7 @@
String entity = response.getEntity(String.class);
JsonNode node = JsonUtils.readTree(entity);
- assertEquals(StatusCodes.MISSING_ARGUMENT,
+ assertEquals(StatusCodes.MISSING_PARAMETER,
node.at("/errors/0/0").asInt());
assertEquals("groupId", node.at("/errors/0/1").asText());
assertEquals("0", node.at("/errors/0/2").asText());
diff --git a/full/src/test/java/de/ids_mannheim/korap/web/controller/VirtualCorpusControllerTest.java b/full/src/test/java/de/ids_mannheim/korap/web/controller/VirtualCorpusControllerTest.java
index ad2874a..42f36ae 100644
--- a/full/src/test/java/de/ids_mannheim/korap/web/controller/VirtualCorpusControllerTest.java
+++ b/full/src/test/java/de/ids_mannheim/korap/web/controller/VirtualCorpusControllerTest.java
@@ -689,7 +689,7 @@
String entity = response.getEntity(String.class);
JsonNode node = JsonUtils.readTree(entity);
assertEquals(Status.BAD_REQUEST.getStatusCode(), response.getStatus());
- assertEquals(StatusCodes.MISSING_ARGUMENT,
+ assertEquals(StatusCodes.MISSING_PARAMETER,
node.at("/errors/0/0").asInt());
assertEquals("vcId", node.at("/errors/0/1").asText());
}
diff --git a/full/src/test/resources/kustvakt-test.conf b/full/src/test/resources/kustvakt-test.conf
index c99ee5e..b26384b 100644
--- a/full/src/test/resources/kustvakt-test.conf
+++ b/full/src/test/resources/kustvakt-test.conf
@@ -43,13 +43,20 @@
## options referring to the security module!
-## token expiration time in minutes!
+## OAuth
+### (see de.ids_mannheim.korap.constant.AuthenticationMethod for possible
+### oauth.password.authentication values)
+oauth.password.authentication = TEST
+oauth.native.client.host=korap.ids-mannheim.de
+
+# JWT
+security.jwt.issuer=korap.ids-mannheim.de
+
+## token expiration
security.longTokenTTL = 1D
security.tokenTTL = 9S
security.shortTokenTTL = 5S
-security.jwt.issuer=korap.ids-mannheim.de
-
## specifies the user data field that is used to salt user passwords
security.passcode.salt=salt