You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@shindig.apache.org by li...@apache.org on 2010/12/02 03:28:17 UTC

svn commit: r1041256 - in /shindig/trunk: features/src/main/javascript/features/core.io/ features/src/main/javascript/features/opensocial-jsonrpc/ features/src/main/javascript/features/osapi/ features/src/main/javascript/features/rpc/ features/src/main...

Author: lindner
Date: Thu Dec  2 02:28:16 2010
New Revision: 1041256

URL: http://svn.apache.org/viewvc?rev=1041256&view=rev
Log:
SHINDIG-606 | add OAuth 2 Draft 10 support, use it for rpc calls

Added:
    shindig/trunk/java/common/src/test/java/org/apache/shindig/auth/UrlParameterAuthenticationHandlerTest.java
Modified:
    shindig/trunk/features/src/main/javascript/features/core.io/io.js
    shindig/trunk/features/src/main/javascript/features/opensocial-jsonrpc/jsonrpccontainer.js
    shindig/trunk/features/src/main/javascript/features/osapi/jsonrpctransport.js
    shindig/trunk/features/src/main/javascript/features/rpc/rpc.js
    shindig/trunk/features/src/main/javascript/features/shindig.container/shindig-container.js
    shindig/trunk/features/src/test/javascript/features/osapi/batchtest.js
    shindig/trunk/features/src/test/javascript/features/osapi/jsonrpctransporttest.js
    shindig/trunk/features/src/test/javascript/lib/testutils.js
    shindig/trunk/java/common/conf/shindig.properties
    shindig/trunk/java/common/src/main/java/org/apache/shindig/auth/UrlParameterAuthenticationHandler.java
    shindig/trunk/php/src/gadgets/GadgetContext.php

Modified: shindig/trunk/features/src/main/javascript/features/core.io/io.js
URL: http://svn.apache.org/viewvc/shindig/trunk/features/src/main/javascript/features/core.io/io.js?rev=1041256&r1=1041255&r2=1041256&view=diff
==============================================================================
--- shindig/trunk/features/src/main/javascript/features/core.io/io.js (original)
+++ shindig/trunk/features/src/main/javascript/features/core.io/io.js Thu Dec  2 02:28:16 2010
@@ -243,7 +243,7 @@ gadgets.io = function() {
    *     'application/x-www-form-urlencoded'.
    */
   function makeXhrRequest(realUrl, proxyUrl, callback, paramData, method,
-      params, processResponseFunction, opt_contentType) {
+      params, processResponseFunction, opt_headers) {
     var xhr = makeXhr();
 
     if (proxyUrl.indexOf('//') == 0) {
@@ -256,11 +256,15 @@ gadgets.io = function() {
           null, processResponseFunction, realUrl, callback, params, xhr);
     }
     if (paramData !== null) {
-      xhr.setRequestHeader('Content-Type', opt_contentType || 'application/x-www-form-urlencoded');
-      xhr.send(paramData);
-    } else {
-      xhr.send(null);
+      var contentTypeHeader = 'Content-Type';
+      var headers = opt_headers || {};
+      if (!headers[contentTypeHeader]) headers[contentTypeHeader] = 'application/x-www-form-urlencoded';
+
+      for (var headerName in headers) {
+        xhr.setRequestHeader(headerName, headers[headerName]);
+      }
     }
+    xhr.send(paramData);
   }
 
 
@@ -441,12 +445,16 @@ gadgets.io = function() {
     },
 
     /**
-     * @private
+     * @param {string} relativeUrl url to fetch via xhr
+     * @param callback callback to call when response is received or for error
+     * @param {Object=} opt_params
+     * @param {Object=} opt_headers
+     *
      */
-    makeNonProxiedRequest: function(relativeUrl, callback, opt_params, opt_contentType) {
+    makeNonProxiedRequest: function(relativeUrl, callback, opt_params, opt_headers) {
       var params = opt_params || {};
       makeXhrRequest(relativeUrl, relativeUrl, callback, params.POST_DATA,
-          params.METHOD, params, processNonProxiedResponse, opt_contentType);
+          params.METHOD, params, processNonProxiedResponse, opt_headers);
     },
 
     /**

Modified: shindig/trunk/features/src/main/javascript/features/opensocial-jsonrpc/jsonrpccontainer.js
URL: http://svn.apache.org/viewvc/shindig/trunk/features/src/main/javascript/features/opensocial-jsonrpc/jsonrpccontainer.js?rev=1041256&r1=1041255&r2=1041256&view=diff
==============================================================================
--- shindig/trunk/features/src/main/javascript/features/opensocial-jsonrpc/jsonrpccontainer.js (original)
+++ shindig/trunk/features/src/main/javascript/features/opensocial-jsonrpc/jsonrpccontainer.js Thu Dec  2 02:28:16 2010
@@ -217,18 +217,18 @@ var JsonRpcRequestItem = function(rpc, o
       'POST_DATA' : gadgets.json.stringify(jsonBatchData)
     };
 
-    var url = [this.path_];
+    var headers = {'Content-Type':'application/json'};
+
     var token = shindig.auth.getSecurityToken();
     if (token) {
-      url.push('?st=', encodeURIComponent(token));
+      headers['Authorization'] = 'OAuth ' + token;
     }
 
-    this.sendRequest(url.join(''), sendResponse, makeRequestParams,
-        'application/json');
+    this.sendRequest(this.path_, sendResponse, makeRequestParams, headers);
   };
 
-  JsonRpcContainer.prototype.sendRequest = function(relativeUrl, callback, params, contentType) {
-    gadgets.io.makeNonProxiedRequest(relativeUrl, callback, params, contentType);
+  JsonRpcContainer.prototype.sendRequest = function(relativeUrl, callback, params, headers) {
+    gadgets.io.makeNonProxiedRequest(relativeUrl, callback, params, headers);
   };
 
   JsonRpcContainer.generateErrorResponse = function(result, requestObjects,
@@ -456,14 +456,13 @@ var JsonRpcRequestItem = function(rpc, o
       'POST_DATA' : gadgets.json.stringify(rpc)
     };
 
-    var url = [this.invalidatePath_];
+    var headers = {'Content-Type': 'application/json'};
     var token = shindig.auth.getSecurityToken();
     if (token) {
-      url.push('?st=', encodeURIComponent(token));
+      headers['Authorization'] = 'OAuth ' + token;
     }
 
-    this.sendRequest(url.join(''), null, makeRequestParams,
-        'application/json');
+    this.sendRequest(this.invalidatePath_, null, makeRequestParams, headers);
   };
 
 })();

Modified: shindig/trunk/features/src/main/javascript/features/osapi/jsonrpctransport.js
URL: http://svn.apache.org/viewvc/shindig/trunk/features/src/main/javascript/features/osapi/jsonrpctransport.js?rev=1041256&r1=1041255&r2=1041256&view=diff
==============================================================================
--- shindig/trunk/features/src/main/javascript/features/osapi/jsonrpctransport.js (original)
+++ shindig/trunk/features/src/main/javascript/features/osapi/jsonrpctransport.js Thu Dec  2 02:28:16 2010
@@ -58,14 +58,14 @@
       'METHOD' : 'POST',
       'AUTHORIZATION' : 'SIGNED'
     };
+    var headers = {'Content-Type': 'application/json'};
 
     var url = this.name;
     var token = shindig.auth.getSecurityToken();
     if (token) {
-      url += '?st=';
-      url += encodeURIComponent(token);
+      headers['Authorization'] = 'OAuth ' + token;
     }
-    gadgets.io.makeNonProxiedRequest(url, processResponse, request, 'application/json');
+    gadgets.io.makeNonProxiedRequest(url, processResponse, request, headers);
   }
 
   function init(config) {

Modified: shindig/trunk/features/src/main/javascript/features/rpc/rpc.js
URL: http://svn.apache.org/viewvc/shindig/trunk/features/src/main/javascript/features/rpc/rpc.js?rev=1041256&r1=1041255&r2=1041256&view=diff
==============================================================================
--- shindig/trunk/features/src/main/javascript/features/rpc/rpc.js (original)
+++ shindig/trunk/features/src/main/javascript/features/rpc/rpc.js Thu Dec  2 02:28:16 2010
@@ -296,7 +296,7 @@ if (!gadgets.rpc) { // make lib resilien
         //   }, 1000);
         // }
         if (rpc.c) {
-          rpc.callback = function(result) {
+          rpc['callback'] = function(result) {
             gadgets.rpc.call(rpc.f, CALLBACK_NAME, null, rpc.c, result);
           };
         }

Modified: shindig/trunk/features/src/main/javascript/features/shindig.container/shindig-container.js
URL: http://svn.apache.org/viewvc/shindig/trunk/features/src/main/javascript/features/shindig.container/shindig-container.js?rev=1041256&r1=1041255&r2=1041256&view=diff
==============================================================================
--- shindig/trunk/features/src/main/javascript/features/shindig.container/shindig-container.js (original)
+++ shindig/trunk/features/src/main/javascript/features/shindig.container/shindig-container.js Thu Dec  2 02:28:16 2010
@@ -671,7 +671,7 @@ shindig.BaseIfrGadget.prototype.queryIfr
   gadgets.io.makeNonProxiedRequest(url,
       handleJSONResponse,
       makeRequestParams,
-      'application/javascript'
+      {'Content-Type':'application/javascript'}
   );
 
   var gadget = this;

Modified: shindig/trunk/features/src/test/javascript/features/osapi/batchtest.js
URL: http://svn.apache.org/viewvc/shindig/trunk/features/src/test/javascript/features/osapi/batchtest.js?rev=1041256&r1=1041255&r2=1041256&view=diff
==============================================================================
--- shindig/trunk/features/src/test/javascript/features/osapi/batchtest.js (original)
+++ shindig/trunk/features/src/test/javascript/features/osapi/batchtest.js Thu Dec  2 02:28:16 2010
@@ -55,9 +55,9 @@ BatchTest.prototype.testAddAndExecuteOne
   var argsInCallToMakeNonProxiedRequest;
   var oldMakeRequest = gadgets.io.makeNonProxiedRequest;
   try {
-    gadgets.io.makeNonProxiedRequest = function(url, callback, params, contentType) {
+    gadgets.io.makeNonProxiedRequest = function(url, callback, params, headers) {
       argsInCallToMakeNonProxiedRequest = { url : url, callback : callback, params : params,
-        contentType : contentType};
+        headers : headers};
     };
     batch.execute(function() {});
 
@@ -86,9 +86,9 @@ BatchTest.prototype.testAddAndExecuteTwo
   var argsInCallToMakeNonProxiedRequest;
   var oldMakeRequest = gadgets.io.makeNonProxiedRequest;
   try {
-    gadgets.io.makeNonProxiedRequest = function(url, callback, params, contentType) {
+    gadgets.io.makeNonProxiedRequest = function(url, callback, params, headers) {
       argsInCallToMakeNonProxiedRequest = { url : url, callback : callback, params : params,
-        contentType : contentType};
+        headers : headers};
     };
     batch.execute(function() {});
     this.assertArgsToMakeNonProxiedRequest(argsInCallToMakeNonProxiedRequest, expectedJson);

Modified: shindig/trunk/features/src/test/javascript/features/osapi/jsonrpctransporttest.js
URL: http://svn.apache.org/viewvc/shindig/trunk/features/src/test/javascript/features/osapi/jsonrpctransporttest.js?rev=1041256&r1=1041255&r2=1041256&view=diff
==============================================================================
--- shindig/trunk/features/src/test/javascript/features/osapi/jsonrpctransporttest.js (original)
+++ shindig/trunk/features/src/test/javascript/features/osapi/jsonrpctransporttest.js Thu Dec  2 02:28:16 2010
@@ -24,11 +24,11 @@ JsonRpcTransportTest.inherits(TestCase);
 
 var lastXhr = {};
 
-JsonRpcTransportTest.prototype.dummyXhr = function(url, callback, params, contentType) {
+JsonRpcTransportTest.prototype.dummyXhr = function(url, callback, params, headers) {
   lastXhr.url = url;
   lastXhr.callback = callback;
   lastXhr.params = params;
-  lastXhr.contentType = contentType;
+  lastXhr.headers = headers;
   callback(lastXhr.result);
 };
 
@@ -235,11 +235,11 @@ JsonRpcTransportTest.inherits(TestCase);
 
 var lastXhr = {};
 
-JsonRpcTransportTest.prototype.dummyXhr = function(url, callback, params, contentType) {
+JsonRpcTransportTest.prototype.dummyXhr = function(url, callback, params, headers) {
   lastXhr.url = url;
   lastXhr.callback = callback;
   lastXhr.params = params;
-  lastXhr.contentType = contentType;
+  lastXhr.headers = headers;
   callback(lastXhr.result);
 };
 

Modified: shindig/trunk/features/src/test/javascript/lib/testutils.js
URL: http://svn.apache.org/viewvc/shindig/trunk/features/src/test/javascript/lib/testutils.js?rev=1041256&r1=1041255&r2=1041256&view=diff
==============================================================================
--- shindig/trunk/features/src/test/javascript/lib/testutils.js (original)
+++ shindig/trunk/features/src/test/javascript/lib/testutils.js Thu Dec  2 02:28:16 2010
@@ -42,7 +42,7 @@ TestCase.prototype.assertArgsToMakeNonPr
   this.assertTrue('params should be passed to makeNonProxiedRequest',
       argsInCall.params);
   this.assertEquals('Content type should match', 'application/json',
-      argsInCall.contentType);
+      argsInCall.headers['Content-Type']);
   this.assertEquals('Json for batch should match', expectedJson,
       gadgets.json.parse(argsInCall.params.POST_DATA));
 

Modified: shindig/trunk/java/common/conf/shindig.properties
URL: http://svn.apache.org/viewvc/shindig/trunk/java/common/conf/shindig.properties?rev=1041256&r1=1041255&r2=1041256&view=diff
==============================================================================
--- shindig/trunk/java/common/conf/shindig.properties (original)
+++ shindig/trunk/java/common/conf/shindig.properties Thu Dec  2 02:28:16 2010
@@ -155,3 +155,7 @@ shindig.proxy.remapInternalServerError=t
 
 # Add debug data when using VanillaCajaHtmlParser.
 vanillaCajaParser.needsDebugData=true
+
+# Allow non-SSL OAuth 2.0 bearer tokens
+org.apache.shindig.auth.oauth2-require-ssl=false
+

Modified: shindig/trunk/java/common/src/main/java/org/apache/shindig/auth/UrlParameterAuthenticationHandler.java
URL: http://svn.apache.org/viewvc/shindig/trunk/java/common/src/main/java/org/apache/shindig/auth/UrlParameterAuthenticationHandler.java?rev=1041256&r1=1041255&r2=1041256&view=diff
==============================================================================
--- shindig/trunk/java/common/src/main/java/org/apache/shindig/auth/UrlParameterAuthenticationHandler.java (original)
+++ shindig/trunk/java/common/src/main/java/org/apache/shindig/auth/UrlParameterAuthenticationHandler.java Thu Dec  2 02:28:16 2010
@@ -19,6 +19,7 @@ package org.apache.shindig.auth;
 
 import com.google.common.collect.Maps;
 import com.google.inject.Inject;
+import com.google.inject.name.Named;
 import net.oauth.OAuth;
 
 import java.util.Enumeration;
@@ -35,11 +36,14 @@ public class UrlParameterAuthenticationH
   private static final String SECURITY_TOKEN_PARAM = "st";
 
   private final SecurityTokenCodec securityTokenCodec;
-  private static final Pattern COMMAWHITESPACE = Pattern.compile("\\s*,\\s*");
+  private final Boolean oauthSSLrequired;
 
   @Inject
-  public UrlParameterAuthenticationHandler(SecurityTokenCodec securityTokenCodec) {
+  public UrlParameterAuthenticationHandler(SecurityTokenCodec securityTokenCodec,
+                                           @Named("org.apache.shindig.auth.oauth2-require-ssl")
+                                           Boolean oauthSSLrequired) {
     this.securityTokenCodec = securityTokenCodec;
+    this.oauthSSLrequired = oauthSSLrequired;
   }
 
   public String getName() {
@@ -68,32 +72,31 @@ public class UrlParameterAuthenticationH
     return this.securityTokenCodec;
   }
 
-  // From OAuthMessage
-  private static final Pattern AUTHORIZATION = Pattern.compile("\\s*(\\w*)\\s+(.*)");
-  private static final Pattern NVP = Pattern.compile("(\\S*)\\s*\\=\\s*\"([^\"]*)\"");
+  private static final Pattern AUTHORIZATION_REGEX = Pattern.compile("\\s*OAuth\\s+(\\S*)\\s*.*");
 
   protected Map<String, String> getMappedParameters(final HttpServletRequest request) {
     Map<String, String> params = Maps.newHashMap();
+    boolean isSecure = this.oauthSSLrequired ? request.isSecure() : true;
 
     // old style security token
     String token = request.getParameter(SECURITY_TOKEN_PARAM);
 
     // OAuth2 token as a param
     // NOTE: if oauth_signature_method is present then we have a OAuth 1.0 request
-    if (token == null && request.isSecure() && request.getParameter(OAuth.OAUTH_SIGNATURE_METHOD) == null) {
+    // See OAuth 2.0 Draft 10 -- 5.1.2  URI Query Parameter
+    if (token == null && isSecure && request.getParameter(OAuth.OAUTH_SIGNATURE_METHOD) == null) {
       token = request.getParameter(OAuth.OAUTH_TOKEN);
     }
 
     // token in authorization header
-    if (token == null) {
+    // See OAuth 2.0 Draft 10 -- 5.1.1 The Authorization Request Header Field
+   if (token == null && isSecure) {
       for (Enumeration<String> headers = request.getHeaders("Authorization"); headers != null && headers.hasMoreElements();) {
-        Matcher m = AUTHORIZATION.matcher(headers.nextElement());
-        if (m.matches() && "Token".equalsIgnoreCase(m.group(1))) {
-          for (String nvp : COMMAWHITESPACE.split(m.group(2))) {
-            m = NVP.matcher(nvp);
-            if (m.matches() && "token".equals(m.group(1))) {
-              token = OAuth.decodePercent(m.group(2));
-            }
+        String authorization = headers.nextElement();
+        if (authorization != null && !authorization.contains("oauth_signature_method=")) {
+          Matcher m = AUTHORIZATION_REGEX.matcher(authorization);
+          if (m.matches()) {
+            token = m.group(1);
           }
         }
       }

Added: shindig/trunk/java/common/src/test/java/org/apache/shindig/auth/UrlParameterAuthenticationHandlerTest.java
URL: http://svn.apache.org/viewvc/shindig/trunk/java/common/src/test/java/org/apache/shindig/auth/UrlParameterAuthenticationHandlerTest.java?rev=1041256&view=auto
==============================================================================
--- shindig/trunk/java/common/src/test/java/org/apache/shindig/auth/UrlParameterAuthenticationHandlerTest.java (added)
+++ shindig/trunk/java/common/src/test/java/org/apache/shindig/auth/UrlParameterAuthenticationHandlerTest.java Thu Dec  2 02:28:16 2010
@@ -0,0 +1,103 @@
+package org.apache.shindig.auth;
+
+import com.google.common.collect.ImmutableMap;
+import org.apache.shindig.common.testing.FakeHttpServletRequest;
+import org.easymock.EasyMock;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+import javax.servlet.http.HttpServletRequest;
+import java.util.Map;
+
+public class UrlParameterAuthenticationHandlerTest {
+  SecurityToken expectedToken;
+  UrlParameterAuthenticationHandler authHandler;
+  SecurityTokenCodec codec;
+  HttpServletRequest req;
+
+  @Before
+  public void setup() throws Exception {
+    expectedToken = new BasicSecurityToken(
+        "owner", "viewer", "app",
+        "domain", "appUrl", "moduleId", "container", "activeUrl", 1000L);
+    // Mock token codec
+    codec = new SecurityTokenCodec() {
+      public SecurityToken createToken(Map<String, String> tokenParameters) throws SecurityTokenException {
+        return tokenParameters == null ? null :
+               "1234".equals(tokenParameters.get(SecurityTokenCodec.SECURITY_TOKEN_NAME)) ? expectedToken : null;
+      }
+
+      public String encodeToken(SecurityToken token) throws SecurityTokenException {
+        return null;
+      }
+
+      public Long getTokenExpiration(SecurityToken token) throws SecurityTokenException {
+        return null;
+      }
+    };
+
+    authHandler = new UrlParameterAuthenticationHandler(codec, true);
+  }
+
+  @Test
+  public void testGetSecurityTokenFromRequest() throws Exception {
+    Assert.assertEquals(authHandler.getName(), AuthenticationMode.SECURITY_TOKEN_URL_PARAMETER.name());
+  }
+
+  @Test
+  public void testInvalidRequests() throws Exception {
+    // Empty request
+    req = new FakeHttpServletRequest();
+    Assert.assertNull(authHandler.getSecurityTokenFromRequest(req));
+
+    // Old behavior, no longer supported
+    req = new FakeHttpServletRequest().setHeader("Authorization", "Token token=\"1234\"");
+    Assert.assertNull(authHandler.getSecurityTokenFromRequest(req));
+  }
+
+  @Test
+  public void testSecurityToken() throws Exception {
+    // security token in request
+    req = new FakeHttpServletRequest("http://example.org/rpc?st=1234");
+    Assert.assertEquals(expectedToken, authHandler.getSecurityTokenFromRequest(req));
+  }
+
+  @Test
+  public void testOAuth1() throws Exception {
+    // An OAuth 1.0 request, we should not process this.
+    req = new FakeHttpServletRequest()
+        .setHeader("Authorization", "OAuth oauth_signature_method=\"RSA-SHA1\"");
+    SecurityToken token = authHandler.getSecurityTokenFromRequest(req);
+    Assert.assertNull(token);
+  }
+
+  @Test
+  public void testOAuth2Header() throws Exception {
+    req = new FakeHttpServletRequest("https://www.example.org/")
+        .setHeader("Authorization", "OAuth  1234");
+    Assert.assertEquals(expectedToken, authHandler.getSecurityTokenFromRequest(req));
+
+    req = new FakeHttpServletRequest("https://www.example.org/")
+        .setHeader("Authorization", "   OAuth    1234 ");
+    Assert.assertEquals(expectedToken, authHandler.getSecurityTokenFromRequest(req));
+
+    req = new FakeHttpServletRequest("https://www.example.org/")
+        .setHeader("Authorization", "OAuth 1234 x=1,y=\"2 2 2\"");
+    Assert.assertEquals(expectedToken, authHandler.getSecurityTokenFromRequest(req));
+
+    req = new FakeHttpServletRequest("http://www.example.org/")
+        .setHeader("Authorization", "OAuth 1234");
+    Assert.assertNull(authHandler.getSecurityTokenFromRequest(req));
+  }
+
+  @Test
+  public void testOAuth2Param() throws Exception
+  {
+    req = new FakeHttpServletRequest("https://www.example.com?oauth_token=1234");
+    Assert.assertEquals(expectedToken, authHandler.getSecurityTokenFromRequest(req));
+
+    req = new FakeHttpServletRequest("https://www.example.com?oauth_token=1234&oauth_signature_method=RSA-SHA1");
+    Assert.assertNull(authHandler.getSecurityTokenFromRequest(req));
+  }
+}

Modified: shindig/trunk/php/src/gadgets/GadgetContext.php
URL: http://svn.apache.org/viewvc/shindig/trunk/php/src/gadgets/GadgetContext.php?rev=1041256&r1=1041255&r2=1041256&view=diff
==============================================================================
--- shindig/trunk/php/src/gadgets/GadgetContext.php (original)
+++ shindig/trunk/php/src/gadgets/GadgetContext.php Thu Dec  2 02:28:16 2010
@@ -267,16 +267,29 @@ class GadgetContext {
    * @return string
    */
   public function getRawToken() {
-    if (! $this->rawToken) {
-        $this->rawToken = isset($_GET["st"]) ? $_GET["st"] : '';
-    }
-    if (! $this->rawToken) {
-      $this->rawToken = isset($_POST['st']) ? $_POST['st'] : '';
+    if ($this->rawToken) {
+      return $this->rawToken;
     }
 
+    $this->rawToken = isset($_GET['st']) ? $_GET['st'] :
+                      isset($_POST['st']) ? $_POST['st'] :
+                          $this->parseAuthorization($_SERVER['AUTHORIZATION']);
+
+
     return $this->rawToken;
   }
 
+  private function parseAuthorization($authHeader) {
+    if (substr($authHeader, 0, 5) != 'OAuth') {
+      return '';
+    }
+    // Ignore OAuth 1.0a
+    if (strpos($authHeader, "oauth_signature_method")) {
+      return '';
+    }
+    return trim(substr($authHeader, 6));
+  }
+
   /**
    * Extracts the 'st' token from the GET or POST params and calls the
    * signer to validate the token