IGNITE-8201 REST: Added AUTHENTICATE command. Fixed session tokens. Added new 
tests.


Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/1cfc9897
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/1cfc9897
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/1cfc9897

Branch: refs/heads/ignite-7708
Commit: 1cfc9897f41e8d8b48510029e7b650b2ed699c9a
Parents: 737933e
Author: Alexey Kuznetsov <akuznet...@apache.org>
Authored: Tue Apr 17 11:46:45 2018 +0700
Committer: Alexey Kuznetsov <akuznet...@apache.org>
Committed: Tue Apr 17 11:46:45 2018 +0700

----------------------------------------------------------------------
 .../client/suite/IgniteClientTestSuite.java     |  6 +-
 .../JettyRestProcessorAbstractSelfTest.java     | 60 ++++++++++-----
 ...ettyRestProcessorAuthenticationSelfTest.java | 45 ++---------
 ...rocessorAuthenticationWithCredsSelfTest.java | 32 ++++++++
 ...rocessorAuthenticationWithTokenSelfTest.java | 80 ++++++++++++++++++++
 .../processors/rest/GridRestCommand.java        |  3 +
 .../processors/rest/GridRestProcessor.java      | 26 ++++---
 .../auth/AuthenticationCommandHandler.java      | 70 +++++++++++++++++
 .../rest/handlers/auth/package-info.java        | 22 ++++++
 .../http/jetty/GridJettyRestHandler.java        | 55 +++++++++++---
 10 files changed, 322 insertions(+), 77 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/1cfc9897/modules/clients/src/test/java/org/apache/ignite/internal/client/suite/IgniteClientTestSuite.java
----------------------------------------------------------------------
diff --git 
a/modules/clients/src/test/java/org/apache/ignite/internal/client/suite/IgniteClientTestSuite.java
 
b/modules/clients/src/test/java/org/apache/ignite/internal/client/suite/IgniteClientTestSuite.java
index 79fcf38..163f89a 100644
--- 
a/modules/clients/src/test/java/org/apache/ignite/internal/client/suite/IgniteClientTestSuite.java
+++ 
b/modules/clients/src/test/java/org/apache/ignite/internal/client/suite/IgniteClientTestSuite.java
@@ -49,7 +49,8 @@ import 
org.apache.ignite.internal.client.util.ClientByteUtilsTest;
 import org.apache.ignite.internal.client.util.ClientConsistentHashSelfTest;
 import org.apache.ignite.internal.client.util.ClientJavaHasherSelfTest;
 import 
org.apache.ignite.internal.processors.rest.ClientMemcachedProtocolSelfTest;
-import 
org.apache.ignite.internal.processors.rest.JettyRestProcessorAuthenticationSelfTest;
+import 
org.apache.ignite.internal.processors.rest.JettyRestProcessorAuthenticationWithCredsSelfTest;
+import 
org.apache.ignite.internal.processors.rest.JettyRestProcessorAuthenticationWithTokenSelfTest;
 import 
org.apache.ignite.internal.processors.rest.JettyRestProcessorSignedSelfTest;
 import 
org.apache.ignite.internal.processors.rest.JettyRestProcessorUnsignedSelfTest;
 import org.apache.ignite.internal.processors.rest.RestBinaryProtocolSelfTest;
@@ -87,7 +88,8 @@ public class IgniteClientTestSuite extends TestSuite {
         // Test jetty rest processor
         suite.addTestSuite(JettyRestProcessorSignedSelfTest.class);
         suite.addTestSuite(JettyRestProcessorUnsignedSelfTest.class);
-        suite.addTestSuite(JettyRestProcessorAuthenticationSelfTest.class);
+        
suite.addTestSuite(JettyRestProcessorAuthenticationWithCredsSelfTest.class);
+        
suite.addTestSuite(JettyRestProcessorAuthenticationWithTokenSelfTest.class);
 
         // Test TCP rest processor with original memcache client.
         suite.addTestSuite(ClientMemcachedProtocolSelfTest.class);

http://git-wip-us.apache.org/repos/asf/ignite/blob/1cfc9897/modules/clients/src/test/java/org/apache/ignite/internal/processors/rest/JettyRestProcessorAbstractSelfTest.java
----------------------------------------------------------------------
diff --git 
a/modules/clients/src/test/java/org/apache/ignite/internal/processors/rest/JettyRestProcessorAbstractSelfTest.java
 
b/modules/clients/src/test/java/org/apache/ignite/internal/processors/rest/JettyRestProcessorAbstractSelfTest.java
index 5dc44c4..e36447b 100644
--- 
a/modules/clients/src/test/java/org/apache/ignite/internal/processors/rest/JettyRestProcessorAbstractSelfTest.java
+++ 
b/modules/clients/src/test/java/org/apache/ignite/internal/processors/rest/JettyRestProcessorAbstractSelfTest.java
@@ -294,14 +294,19 @@ public abstract class JettyRestProcessorAbstractSelfTest 
extends AbstractRestPro
 
     /**
      * @param content Content to check.
+     * @return JSON node with actual response.
      */
-    private JsonNode jsonCacheOperationResponse(String content, boolean bulk) 
throws IOException {
+    protected JsonNode assertResponseSucceeded(String content, boolean bulk) 
throws IOException {
         assertNotNull(content);
         assertFalse(content.isEmpty());
 
         JsonNode node = JSON_MAPPER.readTree(content);
 
-        assertEquals(bulk, node.get("affinityNodeId").isNull());
+        JsonNode affNode = node.get("affinityNodeId");
+
+        if (affNode != null)
+            assertEquals(bulk, affNode.isNull());
+
         assertEquals(STATUS_SUCCESS, node.get("successStatus").asInt());
         assertTrue(node.get("error").isNull());
 
@@ -315,7 +320,7 @@ public abstract class JettyRestProcessorAbstractSelfTest 
extends AbstractRestPro
      * @param res Response.
      */
     private void assertCacheOperation(String content, Object res) throws 
IOException {
-        JsonNode ret = jsonCacheOperationResponse(content, false);
+        JsonNode ret = assertResponseSucceeded(content, false);
 
         assertEquals(String.valueOf(res), ret.isObject() ? ret.toString() : 
ret.asText());
     }
@@ -325,7 +330,7 @@ public abstract class JettyRestProcessorAbstractSelfTest 
extends AbstractRestPro
      * @param res Response.
      */
     private void assertCacheBulkOperation(String content, Object res) throws 
IOException {
-        JsonNode ret = jsonCacheOperationResponse(content, true);
+        JsonNode ret = assertResponseSucceeded(content, true);
 
         assertEquals(String.valueOf(res), ret.asText());
     }
@@ -334,7 +339,7 @@ public abstract class JettyRestProcessorAbstractSelfTest 
extends AbstractRestPro
      * @param content Content to check.
      */
     private void assertCacheMetrics(String content) throws IOException {
-        JsonNode ret = jsonCacheOperationResponse(content, true);
+        JsonNode ret = assertResponseSucceeded(content, true);
 
         assertTrue(ret.isObject());
     }
@@ -349,7 +354,7 @@ public abstract class JettyRestProcessorAbstractSelfTest 
extends AbstractRestPro
 
         JsonNode node = JSON_MAPPER.readTree(content);
 
-        assertEquals(0, node.get("successStatus").asInt());
+        assertEquals(STATUS_SUCCESS, node.get("successStatus").asInt());
         assertTrue(node.get("error").isNull());
 
         assertNotSame(securityEnabled(), node.get("sessionToken").isNull());
@@ -367,7 +372,7 @@ public abstract class JettyRestProcessorAbstractSelfTest 
extends AbstractRestPro
 
         JsonNode node = JSON_MAPPER.readTree(content);
 
-        assertEquals(0, node.get("successStatus").asInt());
+        assertEquals(STATUS_SUCCESS, node.get("successStatus").asInt());
         assertTrue(node.get("error").isNull());
         assertFalse(node.get("response").isNull());
 
@@ -403,7 +408,7 @@ public abstract class JettyRestProcessorAbstractSelfTest 
extends AbstractRestPro
      * @throws IOException If failed.
      */
     private void checkJson(String json, Person p) throws IOException {
-        JsonNode res = jsonCacheOperationResponse(json, false);
+        JsonNode res = assertResponseSucceeded(json, false);
 
         assertEquals(p.id.intValue(), res.get("id").asInt());
         assertEquals(p.getOrganizationId().intValue(), 
res.get("orgId").asInt());
@@ -455,7 +460,7 @@ public abstract class JettyRestProcessorAbstractSelfTest 
extends AbstractRestPro
 
         info("Get command result: " + ret);
 
-        JsonNode res = jsonCacheOperationResponse(ret, false);
+        JsonNode res = assertResponseSucceeded(ret, false);
 
         assertEquals("Alex", res.get("NAME").asText());
         assertEquals(300, res.get("SALARY").asInt());
@@ -476,7 +481,7 @@ public abstract class JettyRestProcessorAbstractSelfTest 
extends AbstractRestPro
 
         info("Get command result: " + ret);
 
-        JsonNode json = jsonCacheOperationResponse(ret, false);
+        JsonNode json = assertResponseSucceeded(ret, false);
         assertEquals(ref1.name, json.get("name").asText());
 
         ref2.ref(ref1);
@@ -552,7 +557,7 @@ public abstract class JettyRestProcessorAbstractSelfTest 
extends AbstractRestPro
 
         info("Get command result: " + ret);
 
-        JsonNode res = jsonCacheOperationResponse(ret, false);
+        JsonNode res = assertResponseSucceeded(ret, false);
 
         assertEquals(p.id, res.get("id").asInt());
         assertEquals(p.name, res.get("name").asText());
@@ -637,7 +642,7 @@ public abstract class JettyRestProcessorAbstractSelfTest 
extends AbstractRestPro
 
         info("Get command result: " + ret);
 
-        JsonNode res = jsonCacheOperationResponse(ret, false);
+        JsonNode res = assertResponseSucceeded(ret, false);
 
         assertEquals(t.getKey(), res.get("key").asText());
         assertEquals(t.getValue(), res.get("value").asText());
@@ -775,11 +780,11 @@ public abstract class JettyRestProcessorAbstractSelfTest 
extends AbstractRestPro
 
         info("Get all command result: " + ret);
 
-        JsonNode res = jsonCacheOperationResponse(ret, true);
+        JsonNode res = assertResponseSucceeded(ret, true);
 
         assertTrue(res.isObject());
 
-        assertTrue(entries.equals(JSON_MAPPER.treeToValue(res, Map.class)));
+        assertEquals(entries, JSON_MAPPER.treeToValue(res, Map.class));
     }
 
     /**
@@ -973,10 +978,25 @@ public abstract class JettyRestProcessorAbstractSelfTest 
extends AbstractRestPro
         assertCacheOperation(ret, true);
     }
 
+    /** */
+    private void failIgnite_5874() {
+        DataStorageConfiguration dsCfg = 
ignite(0).configuration().getDataStorageConfiguration();
+
+        if (dsCfg.getDefaultDataRegionConfiguration().isPersistenceEnabled())
+            fail("IGNITE-5874");
+
+        for (DataRegionConfiguration dataRegCfg : 
dsCfg.getDataRegionConfigurations()) {
+            if (dataRegCfg.isPersistenceEnabled())
+                fail("IGNITE-5874");
+        }
+    }
+
     /**
      * @throws Exception If failed.
      */
     public void testPutWithExpiration() throws Exception {
+        failIgnite_5874();
+
         String ret = content(DEFAULT_CACHE_NAME, GridRestCommand.CACHE_PUT,
             "key", "putKey",
             "val", "putVal",
@@ -1013,6 +1033,8 @@ public abstract class JettyRestProcessorAbstractSelfTest 
extends AbstractRestPro
      * @throws Exception If failed.
      */
     public void testAddWithExpiration() throws Exception {
+        failIgnite_5874();
+
         String ret = content(DEFAULT_CACHE_NAME, GridRestCommand.CACHE_ADD,
             "key", "addKey",
             "val", "addVal",
@@ -1100,7 +1122,7 @@ public abstract class JettyRestProcessorAbstractSelfTest 
extends AbstractRestPro
         assertNull(jcache().localPeek("rmvKey2"));
         assertNull(jcache().localPeek("rmvKey3"));
         assertNull(jcache().localPeek("rmvKey4"));
-        assertTrue(jcache().localSize() == 0);
+        assertEquals(0, jcache().localSize());
 
         assertCacheBulkOperation(ret, true);
     }
@@ -1152,6 +1174,8 @@ public abstract class JettyRestProcessorAbstractSelfTest 
extends AbstractRestPro
      * @throws Exception If failed.
      */
     public void testReplaceWithExpiration() throws Exception {
+        failIgnite_5874();
+
         jcache().put("replaceKey", "replaceVal");
 
         assertEquals("replaceVal", jcache().get("replaceKey"));
@@ -1353,20 +1377,20 @@ public abstract class 
JettyRestProcessorAbstractSelfTest extends AbstractRestPro
             assertNotNull(keyClasses);
             assertFalse(keyClasses.isNull());
 
-            
assertTrue(meta.keyClasses().equals(JSON_MAPPER.treeToValue(keyClasses, 
Map.class)));
+            assertEquals(meta.keyClasses(), 
JSON_MAPPER.treeToValue(keyClasses, Map.class));
 
             JsonNode valClasses = item.get("valClasses");
 
             assertNotNull(valClasses);
             assertFalse(valClasses.isNull());
 
-            
assertTrue(meta.valClasses().equals(JSON_MAPPER.treeToValue(valClasses, 
Map.class)));
+            assertEquals(meta.valClasses(), 
JSON_MAPPER.treeToValue(valClasses, Map.class));
 
             JsonNode fields = item.get("fields");
 
             assertNotNull(fields);
             assertFalse(fields.isNull());
-            assertTrue(meta.fields().equals(JSON_MAPPER.treeToValue(fields, 
Map.class)));
+            assertEquals(meta.fields(), JSON_MAPPER.treeToValue(fields, 
Map.class));
 
             JsonNode indexesByType = item.get("indexes");
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/1cfc9897/modules/clients/src/test/java/org/apache/ignite/internal/processors/rest/JettyRestProcessorAuthenticationSelfTest.java
----------------------------------------------------------------------
diff --git 
a/modules/clients/src/test/java/org/apache/ignite/internal/processors/rest/JettyRestProcessorAuthenticationSelfTest.java
 
b/modules/clients/src/test/java/org/apache/ignite/internal/processors/rest/JettyRestProcessorAuthenticationSelfTest.java
index ca62091..27b8c03 100644
--- 
a/modules/clients/src/test/java/org/apache/ignite/internal/processors/rest/JettyRestProcessorAuthenticationSelfTest.java
+++ 
b/modules/clients/src/test/java/org/apache/ignite/internal/processors/rest/JettyRestProcessorAuthenticationSelfTest.java
@@ -24,7 +24,6 @@ import 
org.apache.ignite.configuration.DataStorageConfiguration;
 import org.apache.ignite.configuration.IgniteConfiguration;
 import 
org.apache.ignite.internal.processors.authentication.IgniteAccessControlException;
 import 
org.apache.ignite.internal.processors.authentication.IgniteAuthenticationProcessor;
-import org.apache.ignite.internal.util.typedef.F;
 import org.apache.ignite.internal.util.typedef.internal.U;
 import org.apache.ignite.testframework.GridTestUtils;
 
@@ -33,18 +32,12 @@ import static org.apache.ignite.configuration.WALMode.NONE;
 /**
  * Test REST with enabled authentication.
  */
-public class JettyRestProcessorAuthenticationSelfTest extends 
JettyRestProcessorUnsignedSelfTest {
+public abstract class JettyRestProcessorAuthenticationSelfTest extends 
JettyRestProcessorUnsignedSelfTest {
     /** */
-    private static final String DFLT_LOGIN = "ignite";
+    protected static final String DFLT_USER = "ignite";
 
     /** */
-    private static final String DFLT_PWD = "ignite";
-
-    /** */
-    private String login = DFLT_LOGIN;
-
-    /** */
-    private String pwd = DFLT_PWD;
+    protected static final String DFLT_PWD = "ignite";
 
     /** {@inheritDoc} */
     @Override protected void beforeTestsStarted() throws Exception {
@@ -54,11 +47,8 @@ public class JettyRestProcessorAuthenticationSelfTest 
extends JettyRestProcessor
     }
 
     /** {@inheritDoc} */
-    @Override protected void beforeTest() throws Exception {
-        super.beforeTest();
-
-        login = DFLT_LOGIN;
-        pwd = DFLT_PWD;
+    @Override protected boolean securityEnabled() {
+        return true;
     }
 
     /** {@inheritDoc} */
@@ -97,32 +87,13 @@ public class JettyRestProcessorAuthenticationSelfTest 
extends JettyRestProcessor
         return cfg;
     }
 
-    /** {@inheritDoc} */
-    @Override protected String restUrl() {
-        String url = super.restUrl();
-
-        if (!F.isEmpty(login)) {
-            url += "ignite.login=" + login;
-
-            if (!F.isEmpty(pwd))
-                url += "&ignite.password=" + pwd;
-
-            url += '&';
-        }
-
-        return url;
-    }
-
     /**
      * @throws Exception If failed.
      */
-    public void testMissingCredentials() throws Exception {
-        login = null;
-        pwd = null;
-
-        String ret = content(null, GridRestCommand.VERSION);
+    public void testAuthenticationCommand() throws Exception {
+        String ret = content(null, GridRestCommand.AUTHENTICATE);
 
-        assertResponseContainsError(ret, "The user name or password is 
incorrect");
+        assertResponseSucceeded(ret, false);
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/ignite/blob/1cfc9897/modules/clients/src/test/java/org/apache/ignite/internal/processors/rest/JettyRestProcessorAuthenticationWithCredsSelfTest.java
----------------------------------------------------------------------
diff --git 
a/modules/clients/src/test/java/org/apache/ignite/internal/processors/rest/JettyRestProcessorAuthenticationWithCredsSelfTest.java
 
b/modules/clients/src/test/java/org/apache/ignite/internal/processors/rest/JettyRestProcessorAuthenticationWithCredsSelfTest.java
new file mode 100644
index 0000000..c75e8a9
--- /dev/null
+++ 
b/modules/clients/src/test/java/org/apache/ignite/internal/processors/rest/JettyRestProcessorAuthenticationWithCredsSelfTest.java
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.processors.rest;
+
+/**
+ * Test REST with enabled authentication and credentials in each request.
+ */
+public class JettyRestProcessorAuthenticationWithCredsSelfTest extends 
JettyRestProcessorAuthenticationSelfTest {
+    /** {@inheritDoc} */
+    @Override protected String restUrl() {
+        String url = super.restUrl();
+
+        url += "ignite.login=" + DFLT_USER + "&ignite.password=" + DFLT_PWD + 
"&";
+
+        return url;
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/1cfc9897/modules/clients/src/test/java/org/apache/ignite/internal/processors/rest/JettyRestProcessorAuthenticationWithTokenSelfTest.java
----------------------------------------------------------------------
diff --git 
a/modules/clients/src/test/java/org/apache/ignite/internal/processors/rest/JettyRestProcessorAuthenticationWithTokenSelfTest.java
 
b/modules/clients/src/test/java/org/apache/ignite/internal/processors/rest/JettyRestProcessorAuthenticationWithTokenSelfTest.java
new file mode 100644
index 0000000..5c046af
--- /dev/null
+++ 
b/modules/clients/src/test/java/org/apache/ignite/internal/processors/rest/JettyRestProcessorAuthenticationWithTokenSelfTest.java
@@ -0,0 +1,80 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.processors.rest;
+
+import org.apache.ignite.internal.util.typedef.F;
+
+/**
+ * Test REST with enabled authentication and token.
+ */
+public class JettyRestProcessorAuthenticationWithTokenSelfTest extends 
JettyRestProcessorAuthenticationSelfTest {
+    /** */
+    private String tok = "";
+
+    /** {@inheritDoc} */
+    @Override protected void beforeTest() throws Exception {
+        super.beforeTest();
+
+        // Authenticate and extract token.
+        if (F.isEmpty(tok)) {
+            String ret = content(null, GridRestCommand.AUTHENTICATE,
+                "user", DFLT_USER,
+                "password", DFLT_PWD);
+
+            int p1 = ret.indexOf("sessionToken");
+            int p2 = ret.indexOf('"', p1 + 16);
+
+            tok = ret.substring(p1 + 15, p2);
+        }
+    }
+
+    /** {@inheritDoc} */
+    @Override protected String restUrl() {
+        String url = super.restUrl();
+
+        if (!F.isEmpty(tok))
+            url += "sessionToken=" + tok + "&";
+
+        return url;
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testInvalidSessionToken() throws Exception {
+        tok = null;
+
+        String ret = content(null, GridRestCommand.VERSION);
+
+        assertResponseContainsError(ret, "Failed to handle request - session 
token not found or invalid");
+
+        tok = "InvalidToken";
+
+        ret = content(null, GridRestCommand.VERSION);
+
+        assertResponseContainsError(ret, "Failed to handle request - session 
token not found or invalid");
+
+        tok = "26BE027D32CC42329DEC92D517B44E9E";
+
+        ret = content(null, GridRestCommand.VERSION);
+
+        assertResponseContainsError(ret, "Failed to handle request - unknown 
session token (maybe expired session)");
+
+        tok = null; // Cleanup token for next tests.
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/1cfc9897/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/GridRestCommand.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/GridRestCommand.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/GridRestCommand.java
index 0b9a662..265fe40 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/GridRestCommand.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/GridRestCommand.java
@@ -169,6 +169,9 @@ public enum GridRestCommand {
     CLUSTER_CURRENT_STATE("currentstate"),
 
     /** */
+    AUTHENTICATE("authenticate"),
+
+    /** */
     ADD_USER("adduser"),
 
     /** */

http://git-wip-us.apache.org/repos/asf/ignite/blob/1cfc9897/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/GridRestProcessor.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/GridRestProcessor.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/GridRestProcessor.java
index 4b8497e..da5e5c2 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/GridRestProcessor.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/GridRestProcessor.java
@@ -45,6 +45,7 @@ import 
org.apache.ignite.internal.processors.GridProcessorAdapter;
 import 
org.apache.ignite.internal.processors.authentication.AuthorizationContext;
 import 
org.apache.ignite.internal.processors.rest.client.message.GridClientTaskResultBean;
 import 
org.apache.ignite.internal.processors.rest.handlers.GridRestCommandHandler;
+import 
org.apache.ignite.internal.processors.rest.handlers.auth.AuthenticationCommandHandler;
 import 
org.apache.ignite.internal.processors.rest.handlers.cache.GridCacheCommandHandler;
 import 
org.apache.ignite.internal.processors.rest.handlers.cluster.GridChangeStateCommandHandler;
 import 
org.apache.ignite.internal.processors.rest.handlers.datastructures.DataStructuresCommandHandler;
@@ -81,6 +82,7 @@ import org.apache.ignite.plugin.security.SecurityPermission;
 import org.apache.ignite.thread.IgniteThread;
 
 import static 
org.apache.ignite.IgniteSystemProperties.IGNITE_REST_START_ON_CLIENT;
+import static 
org.apache.ignite.internal.processors.rest.GridRestCommand.AUTHENTICATE;
 import static 
org.apache.ignite.internal.processors.rest.GridRestResponse.STATUS_AUTH_FAILED;
 import static 
org.apache.ignite.internal.processors.rest.GridRestResponse.STATUS_FAILED;
 import static 
org.apache.ignite.internal.processors.rest.GridRestResponse.STATUS_SECURITY_CHECK_FAILED;
@@ -230,10 +232,11 @@ public class GridRestProcessor extends 
GridProcessorAdapter {
             try {
                 ses = session(req);
             }
+            catch (IgniteAuthenticationException e) {
+                return new GridFinishedFuture<>(new 
GridRestResponse(STATUS_AUTH_FAILED, e.getMessage()));
+            }
             catch (IgniteCheckedException e) {
-                GridRestResponse res = new GridRestResponse(STATUS_FAILED, 
e.getMessage());
-
-                return new GridFinishedFuture<>(res);
+                return new GridFinishedFuture<>(new 
GridRestResponse(STATUS_FAILED, e.getMessage()));
             }
 
             assert ses != null;
@@ -284,9 +287,9 @@ public class GridRestProcessor extends GridProcessorAdapter 
{
                             throw new IgniteAuthenticationException("The user 
name or password is incorrect");
 
                         ses.authCtx = ctx.authentication().authenticate(login, 
pwd);
-
-                        req.authorizationContext(ses.authCtx);
                     }
+
+                    req.authorizationContext(ses.authCtx);
                 }
                 catch (IgniteCheckedException e) {
                     return new GridFinishedFuture<>(new 
GridRestResponse(STATUS_AUTH_FAILED, e.getMessage()));
@@ -341,7 +344,7 @@ public class GridRestProcessor extends GridProcessorAdapter 
{
 
                 assert res != null;
 
-                if (ctx.security().enabled() && !failed)
+                if ((authenticationEnabled || securityEnabled) && !failed)
                     res.sessionTokenBytes(req.sessionToken());
 
                 interceptResponse(res, req);
@@ -362,6 +365,10 @@ public class GridRestProcessor extends 
GridProcessorAdapter {
 
         while (true) {
             if (F.isEmpty(sesTok) && clientId == null) {
+                // TODO: In IGNITE 3.0 we should check credentials only for 
AUTHENTICATE command.
+                if (ctx.authentication().enabled() && req.command() != 
AUTHENTICATE && req.credentials() == null)
+                    throw new IgniteAuthenticationException("Failed to handle 
request - session token not found or invalid");
+
                 Session ses = Session.random();
 
                 UUID oldSesId = clientId2SesId.put(ses.clientId, ses.sesId);
@@ -451,10 +458,7 @@ public class GridRestProcessor extends 
GridProcessorAdapter {
         try {
             sesExpTime = 
System.getProperty(IgniteSystemProperties.IGNITE_REST_SESSION_TIMEOUT);
 
-            if (sesExpTime != null)
-                sesExpTime0 = Long.valueOf(sesExpTime) * 1000;
-            else
-                sesExpTime0 = DEFAULT_SES_TIMEOUT;
+            sesExpTime0 = sesExpTime != null ? Long.valueOf(sesExpTime) * 1000 
: DEFAULT_SES_TIMEOUT;
         }
         catch (NumberFormatException ignore) {
             U.warn(log, "Failed parsing IGNITE_REST_SESSION_TIMEOUT system 
variable [IGNITE_REST_SESSION_TIMEOUT="
@@ -504,6 +508,7 @@ public class GridRestProcessor extends GridProcessorAdapter 
{
             addHandler(new QueryCommandHandler(ctx));
             addHandler(new GridLogCommandHandler(ctx));
             addHandler(new GridChangeStateCommandHandler(ctx));
+            addHandler(new AuthenticationCommandHandler(ctx));
             addHandler(new UserActionCommandHandler(ctx));
 
             // Start protocols.
@@ -860,6 +865,7 @@ public class GridRestProcessor extends GridProcessorAdapter 
{
             case CLUSTER_CURRENT_STATE:
             case CLUSTER_ACTIVE:
             case CLUSTER_INACTIVE:
+            case AUTHENTICATE:
             case ADD_USER:
             case REMOVE_USER:
             case UPDATE_USER:

http://git-wip-us.apache.org/repos/asf/ignite/blob/1cfc9897/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/handlers/auth/AuthenticationCommandHandler.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/handlers/auth/AuthenticationCommandHandler.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/handlers/auth/AuthenticationCommandHandler.java
new file mode 100644
index 0000000..aa9bbbd
--- /dev/null
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/handlers/auth/AuthenticationCommandHandler.java
@@ -0,0 +1,70 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.processors.rest.handlers.auth;
+
+import java.util.Collection;
+import org.apache.ignite.internal.GridKernalContext;
+import org.apache.ignite.internal.IgniteInternalFuture;
+import org.apache.ignite.internal.processors.rest.GridRestCommand;
+import org.apache.ignite.internal.processors.rest.GridRestResponse;
+import 
org.apache.ignite.internal.processors.rest.handlers.GridRestCommandHandlerAdapter;
+import org.apache.ignite.internal.processors.rest.request.GridRestRequest;
+import org.apache.ignite.internal.util.future.GridFinishedFuture;
+import org.apache.ignite.internal.util.typedef.internal.U;
+
+import static 
org.apache.ignite.internal.processors.rest.GridRestCommand.AUTHENTICATE;
+
+/**
+ * Authentication handler.
+ */
+public class AuthenticationCommandHandler extends 
GridRestCommandHandlerAdapter {
+    /** Commands. */
+    private static final Collection<GridRestCommand> SUPPORTED_COMMANDS = 
U.sealList(AUTHENTICATE);
+
+    /**
+     * @param ctx Context.
+     */
+    public AuthenticationCommandHandler(GridKernalContext ctx) {
+        super(ctx);
+    }
+
+    /** {@inheritDoc} */
+    @Override public Collection<GridRestCommand> supportedCommands() {
+        return SUPPORTED_COMMANDS;
+    }
+
+    /** {@inheritDoc} */
+    @Override public IgniteInternalFuture<GridRestResponse> 
handleAsync(GridRestRequest req) {
+        assert req != null;
+
+        if (log.isDebugEnabled())
+            log.debug("Handling topology REST request: " + req);
+
+        try {
+            if (log.isDebugEnabled())
+                log.debug("Handled topology REST request [req=" + req + ']');
+
+            return new GridFinishedFuture<>(new GridRestResponse(true));
+        }
+        catch (Throwable e) {
+            log.error("Failed to handle REST request [req=" + req + ']', e);
+
+            return new GridFinishedFuture<>(e);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/1cfc9897/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/handlers/auth/package-info.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/handlers/auth/package-info.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/handlers/auth/package-info.java
new file mode 100644
index 0000000..1d58218
--- /dev/null
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/handlers/auth/package-info.java
@@ -0,0 +1,22 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * <!-- Package description. -->
+ * REST authentication command.
+ */
+package org.apache.ignite.internal.processors.rest.handlers.auth;

http://git-wip-us.apache.org/repos/asf/ignite/blob/1cfc9897/modules/rest-http/src/main/java/org/apache/ignite/internal/processors/rest/protocols/http/jetty/GridJettyRestHandler.java
----------------------------------------------------------------------
diff --git 
a/modules/rest-http/src/main/java/org/apache/ignite/internal/processors/rest/protocols/http/jetty/GridJettyRestHandler.java
 
b/modules/rest-http/src/main/java/org/apache/ignite/internal/processors/rest/protocols/http/jetty/GridJettyRestHandler.java
index b3fbddd..99a8844 100644
--- 
a/modules/rest-http/src/main/java/org/apache/ignite/internal/processors/rest/protocols/http/jetty/GridJettyRestHandler.java
+++ 
b/modules/rest-http/src/main/java/org/apache/ignite/internal/processors/rest/protocols/http/jetty/GridJettyRestHandler.java
@@ -86,6 +86,12 @@ public class GridJettyRestHandler extends AbstractHandler {
     private static final String CHARSET = StandardCharsets.UTF_8.name();
 
     /** */
+    private static final String  USER_PARAM = "user";
+
+    /** */
+    private static final String  PWD_PARAM = "password";
+
+    /** */
     private static final String  CACHE_NAME_PARAM = "cacheName";
 
     /** */
@@ -100,10 +106,10 @@ public class GridJettyRestHandler extends AbstractHandler 
{
     /** */
     private static final String WRITE_SYNCHRONIZATION_MODE_PARAM = 
"writeSynchronizationMode";
 
-    /** */
+    /**@deprecated Should be replaced with AUTHENTICATION + token in IGNITE 
3.0 */
     private static final String IGNITE_LOGIN = "ignite.login";
 
-    /** */
+    /**@deprecated Should be replaced with AUTHENTICATION + token in IGNITE 
3.0 */
     private static final String IGNITE_PASSWORD = "ignite.password";
 
     /** */
@@ -731,6 +737,12 @@ public class GridJettyRestHandler extends AbstractHandler {
                 break;
             }
 
+            case AUTHENTICATE: {
+                restReq = new GridRestRequest();
+
+                break;
+            }
+
             case ADD_USER:
             case REMOVE_USER:
             case UPDATE_USER: {
@@ -840,12 +852,9 @@ public class GridJettyRestHandler extends AbstractHandler {
 
         restReq.command(cmd);
 
-        if (params.containsKey(IGNITE_LOGIN) || 
params.containsKey(IGNITE_PASSWORD)) {
-            SecurityCredentials cred = new SecurityCredentials(
-                (String)params.get(IGNITE_LOGIN), 
(String)params.get(IGNITE_PASSWORD));
-
-            restReq.credentials(cred);
-        }
+        // TODO: In IGNITE 3.0 we should check credentials only for 
AUTHENTICATE command.
+        if (!credentials(params, IGNITE_LOGIN, IGNITE_PASSWORD, restReq))
+            credentials(params, USER_PARAM, PWD_PARAM, restReq);
 
         String clientId = (String)params.get("clientId");
 
@@ -870,8 +879,13 @@ public class GridJettyRestHandler extends AbstractHandler {
         String sesTokStr = (String)params.get("sessionToken");
 
         try {
-            if (sesTokStr != null)
-                restReq.sessionToken(U.hexString2ByteArray(sesTokStr));
+            if (sesTokStr != null) {
+                // Token is a UUID encoded as 16 bytes as HEX.
+                byte[] bytes = U.hexString2ByteArray(sesTokStr);
+
+                if (bytes.length == 16)
+                    restReq.sessionToken(bytes);
+            }
         }
         catch (IllegalArgumentException ignored) {
             // Ignore invalid session token.
@@ -881,6 +895,27 @@ public class GridJettyRestHandler extends AbstractHandler {
     }
 
     /**
+     *
+     * @param params Parameters.
+     * @param userParam Parameter name to take user name.
+     * @param pwdParam Parameter name to take password.
+     * @param restReq Request to add credentials if any.
+     * @return {@code true} If params contains credentials.
+     */
+    private boolean credentials(Map<String, Object> params, String userParam, 
String pwdParam, GridRestRequest restReq) {
+        boolean hasCreds = params.containsKey(userParam) || 
params.containsKey(pwdParam);
+
+        if (hasCreds) {
+            SecurityCredentials cred = new 
SecurityCredentials((String)params.get(userParam),
+                (String)params.get(pwdParam));
+
+            restReq.credentials(cred);
+        }
+
+        return hasCreds;
+    }
+
+    /**
      * Gets values referenced by sequential keys, e.g. {@code key1...keyN}.
      *
      * @param type Optional value type.

Reply via email to