2015-06-29 2 views
3

Я пытаюсь сделать маркер запроса доступа, используя документацию приведены ниже: https://developers.google.com/identity/protocols/OAuth2ServiceAccountGoogle OAuth2 учетной записи службы HTTP/REST Аутентификация

Я усиливая jsrsasign библиотеку для создания моих JWT

Для ясности я нахожусь развертывание кода в облачный код Parse.com, все выполняется отлично, за исключением отказавшего ответа от Google.

jsrsasign [http://kjur.github.io/jsrsasign/] https://kjur.github.io/jsrsasign/api/symbols/KJUR.jws.JWS.html#.sign

Parse.Cloud.define("testBase", function(request, response) { 

    var createJWT = function(){ 

    var creds = { 
     private_key_id: "532ca15e518a0<foobar>74dd81d48a9cb24", 
     private_key: "-----BEGIN PRIVATE KEY-----\nMIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcw<foobar>QCzxcu5ae3l7JXT\nZzI2kHA3lYay/2DIcC4KXqQWCMejQacRlFROftfnqRrf9qmEewH/0TMSMlOFt0G6\n9hjznhOHu3rxZcAxuK5bh7UnmoUWYksdtb+6VgCGF9Z5piTASrLxssILAUqY6EjT\nHKp3IQk6aqMqe6NhymCS/o0K9NvGA98znpv28ilD9dd5HXhfTdeGm7PDkZGIXIbR\nG+sQN8+tW46N1PaYnoz8iNGfvGk2Y04WDC2HJ590z4DAk41jbcWtnZnr/UyIJzTq\nTBjCWwAcF0qwSabf/mlWSf2S7DeCZKYNveMSN7F6meI8uYshuVoNqd95u/KGfQ4q\ns+wMdF3tAgMBAAECggEAcQ2MhnelUhisSBv3qfS/fVUdNmf/d02ExqSpz+mJkpNw\n+08qjYqbQGZKLloyVMv+f+ARm/nmKIsMXQTywBHC+nLeZ/yzFxGrJIh9VgCIfYEm\n9/IaNpZrEejfyfS/2+WeDv15pe4T+YDqe0jlsrEl2oTBQ7ApGRBqF0bZb/B4XVd3\ngZ6kya+UL5j+PSgNcaGABUfj7pDXZIRmVnWJxXSYhvvbD+SrXIhBMS3wXZ+vka1J\nkW/bwhzayu9/nI24WN7pALxf6/zB3Ewyoj5n1pnxbkvBMcK+PBiX9yAPvfH5cGQF\nQZx86L11maYpWHxufrbclow16qZHP41O+1eePGbIgQKBgQDmOY04z02RIMX32I7k\nbtokmG8qDnR8iu8dkLSRU4Ib7ZPzIBpjg9neaRib9A2fPVjyuxjvsUbob11BuklZ\nGCMu9SFV8w4LpUQ3clL+kBiGncuSmBfZWbj7uqLuzsNeeu3pihVTlkeWeagTAR36\nhi8K4IVQi5SmPF2dPiw9A8oXkQKBgQDH5j1smCFu9d+F2HIwDFXsW1wlyWhtcgfV\n70uCXdImnU25pJDARLX8vqaZp0KHIPmXLgUV/sU3oAX9NRdgV56bJTo7vwO3DATM\ntK14h7GZCKSYniOqX+3FdweNyn89qlHeAkZdvCZhGX5rOVXtlhpey7Eu8fQnPs1S\nbxd1EXRKnQKBgH+m1Yj0WLvpghskdkZuuIGmC600Cp6rol2wSI5z0SaPGoOp/zfC\neeD6QOzn602qBFHCL9dnYjuq0/iHw/ekjI2S2YMAm38Vibd8qkv/tbmecKu9rSuU\nth7No13qQyV138ioCZ8pKlRi7DBtZCPultLfHsxEOI3b1sRDHuBN45YhAoGAGbKe\niNxRx/rxvjoiC806KoVgJjdrJk63dSgrE9pNzssAF/Jw7Van8pLrxer7oXV6wJWY\n78ftwIXg3zk5BRieeiFiCBY5OwnfgBVmC42eJic3SatiuF9WqMDxhqfWja3ckmbG\ndvxeDrOBTfVz93QJddBHudo+4eCv8n33jQQuZ/0CgYEAsYXmQWOUndqBaZgho3ZV\njrRFmwiwiqJ1hqJdflBXbKlTQOpqea8QoQOQqyeMVQ1X7x3rDcHbhFSbd65GJT5j\n65B/OXrBpIBhb5u0/x6ytJhlM9sPRIL+G/m5QYnBY7dcQo6jlKxTUKHPEV/mwT2m\nt/ZxkAmz/9DKWFKtDc4ZshI\u003d\n-----END PRIVATE KEY-----\n", 
     client_email: "<foobar>[email protected]", 
     client_id: "<foobar>-t18b3hrkab6urireblm8kb4kt45c92a2.apps.googleusercontent.com", 
     type: "service_account" 
    }; 

    var header = { 
     alg:"RS256", 
     typ:"JWT" 
    }; 

    var data = { 
     iss: creds.client_email, 
     scope:"https://www.googleapis.com/auth/analytics.readonly", 
     aud:"https://www.googleapis.com/oauth2/v3/token", 
     exp: KJUR.jws.IntDate.get('now + 1hour'), 
     iat: KJUR.jws.IntDate.get('now') 
    }; 

    console.log("Preparing to generate RS256 JWT"); 
    var sJWT = KJUR.jws.JWS.sign("RS256", JSON.stringify(header), JSON.stringify(data), creds.private_key); 
    console.log("RS256 JWT generation complete:"); 

    console.log(sJWT) 
    return sJWT; 
    } 

    console.log("############################## ") 


    try{ 
     console.log("Preparing assertion...") 
     var jwt = createJWT() 
     console.log("Assertion: "+jwt); 

     var options = { 
      method: 'POST', 
      headers: { 
      'Content-Type':'application/x-www-form-urlencoded' 
      }, 
      url: "https://www.googleapis.com/oauth2/v3/token", 
      params: { 
      grant_type: "urn:ietf:params:oauth:grant-type:jwt-bearer", 

      assertion: jwt 
      } 
     }; 

     console.log("------------------------"); 
     console.log(options); 
     console.log("------------------------"); 

     Parse.Cloud.httpRequest(options).done(function(rsp){ 
      var r = (_.isString(rsp.text)) ? JSON.parse(rsp.text) : rsp.text; 
      console.log("Reponse from Google:"); 
      console.log(rsp) 
      // console.log({ body: req.body, params: req.params, query: req.query, o: options, r: r }); 
      // res.send(r); 
      response.success(r); 

     }).fail(function(err){ 
      // console.error(err); 
      console.error("Failed response from Google:") 
      console.error(err.text) 
      response.error(err); 

     }); 
    }catch(err){ 
     console.error(err); 
     response.error(err); 
    } 
}); 

Выход консоли:

I2015-06-29T19:42:17.315Z]############################## 
I2015-06-29T19:42:17.316Z]Preparing assertion... 
I2015-06-29T19:42:17.317Z]Preparing to generate RS256 JWT 
I2015-06-29T19:42:17.401Z]RS256 JWT generation complete: 
I2015-06-29T19:42:17.402Z]eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiI2MDQ4Mjk2NTQ1MzktdDE4YjNocmthYjZ1cmlyZWJsbThrYjRrdDQ1YzkyYTJAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJzY29wZSI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL2F1dGgvYW5hbHl0aWNzLnJlYWRvbmx5IiwiYXVkIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vb2F1dGgyL3YzL3Rva2VuIiwiZXhwIjoxNDM1NjEwNTM3LCJpYXQiOjE0MzU2MDY5Mzd9.nGbApndzwwtadeL2Jr2zU__JZrBZ6tYGJ17sTDksiSsFRXop_6CFAsV7fkXC6Xd-Nf3KfYzNuqGzLciQTzc9AhGNFTk_aUXU-ndMbYiVh3EpTkBI0olkS5rkgnmm3Q_yfaOswkyvMwE12RvgTTjymVzHGTZ8xC_x22Ep1n07Ap3TQn3WpeFeJlHciiwcxMTG7TsxAvHEgaqLzZ79feFmZanj6pqEH1kfZeJUQK1n3bwKtU92qpPn7b4dFtJs8I7El62HLExU1B2l7qdSyp4CRxmUPViUfWykElDZeqDzPoX38QEMDmmTgCYUXna7wJB6O0qC3aJpxkCAmzPCDkXkZQ 
I2015-06-29T19:42:17.403Z]Assertion: eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiI2MDQ4Mjk2NTQ1MzktdDE4YjNocmthYjZ1cmlyZWJsbThrYjRrdDQ1YzkyYTJAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJzY29wZSI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL2F1dGgvYW5hbHl0aWNzLnJlYWRvbmx5IiwiYXVkIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vb2F1dGgyL3YzL3Rva2VuIiwiZXhwIjoxNDM1NjEwNTM3LCJpYXQiOjE0MzU2MDY5Mzd9.nGbApndzwwtadeL2Jr2zU__JZrBZ6tYGJ17sTDksiSsFRXop_6CFAsV7fkXC6Xd-Nf3KfYzNuqGzLciQTzc9AhGNFTk_aUXU-ndMbYiVh3EpTkBI0olkS5rkgnmm3Q_yfaOswkyvMwE12RvgTTjymVzHGTZ8xC_x22Ep1n07Ap3TQn3WpeFeJlHciiwcxMTG7TsxAvHEgaqLzZ79feFmZanj6pqEH1kfZeJUQK1n3bwKtU92qpPn7b4dFtJs8I7El62HLExU1B2l7qdSyp4CRxmUPViUfWykElDZeqDzPoX38QEMDmmTgCYUXna7wJB6O0qC3aJpxkCAmzPCDkXkZQ 
I2015-06-29T19:42:17.404Z]------------------------ 
I2015-06-29T19:42:17.405Z]{"method":"POST","headers":{"Content-Type":"application/x-www-form-urlencoded"},"url":"https://www.googleapis.com/oauth2/v3/token","params":{"grant_type":"urn:ietf:params:oauth:grant-type:jwt-bearer","assertion":"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiI2MDQ4Mjk2NTQ1MzktdDE4YjNocmthYjZ1cmlyZWJsbThrYjRrdDQ1YzkyYTJAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJzY29wZSI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL2F1dGgvYW5hbHl0aWNzLnJlYWRvbmx5IiwiYXVkIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vb2F1dGgyL3YzL3Rva2VuIiwiZXhwIjoxNDM1NjEwNTM3LCJpYXQiOjE0MzU2MDY5Mzd9.nGbApndzwwtadeL2Jr2zU__JZrBZ6tYGJ17sTDksiSsFRXop_6CFAsV7fkXC6Xd-Nf3KfYzNuqGzLciQTzc9AhGNFTk_aUXU-ndMbYiVh3EpTkBI0olkS5rkgnmm3Q_yfaOswkyvMwE12RvgTTjymVzHGTZ8xC_x22Ep1n07Ap3TQn3WpeFeJlHciiwcxMTG7TsxAvHEgaqLzZ79feFmZanj6pqEH1kfZeJUQK1n3bwKtU92qpPn7b4dFtJs8I7El62HLExU1B2l7qdSyp4CRxmUPViUfWykElDZeqDzPoX38QEMDmmTgCYUXna7wJB6O0qC3aJpxkCAmzPCDkXkZQ"}} 
I2015-06-29T19:42:17.406Z]------------------------ 
I2015-06-29T19:42:17.504Z]Failed response from Google: 
I2015-06-29T19:42:17.506Z]{ 
"error": "invalid_grant", 
"error_description": "Bad Request" 
} 

Окончательное решение Импортируйте учетные данные учетной записи Google службы JSON-файл (переименован в Google-сервис-счет- credentials.js), сгенерируйте jwt, примените jwt как тело в Parse.Request вместо params.

var fs = require('fs'); 
var moment = require('moment'); 
var _ = require('underscore'); 
var KJUR = require("cloud/lib/jsrsasign/npm/lib/jsrsasign.js"); 
var googleServiceAccountCredentials = JSON.parse(fs.readFileSync('cloud/google-service-account-credentials.js')); 


var createJWT = function(args, credentials){ 

    var header = { 
    alg:"RS256", 
    typ:"JWT" 
    }; 

    var now = moment().unix(); 

    var defaults = { 
    iss: credentials.client_email, 
    scope:"https://www.googleapis.com/auth/analytics.readonly", 
    aud:"https://www.googleapis.com/oauth2/v3/token", 
    exp: now + (15*60), 
    iat: now 
    }; 

    var data = {}; 

    _.extend(data, defaults, args); 

    var sJWT = KJUR.jws.JWS.sign("RS256", JSON.stringify(header), JSON.stringify(data), credentials.private_key); 
    return sJWT; 
}; 

Parse.Cloud.define("testBase", function(request, response) { 


    try{ 
     var now = moment().unix(); 

     var options = { 
      method: 'POST', 
      headers: { 
      'Content-Type':'application/x-www-form-urlencoded' 
      }, 
      url: "https://www.googleapis.com/oauth2/v3/token", 
      body: { 
      grant_type: encodeURI("urn:ietf:params:oauth:grant-type:jwt-bearer"), 
      assertion: createJWT({ 
       exp: now + (60*60), 
       iat: now 
      }, googleServiceAccountCredentials) 
      } 
     }; 

     Parse.Cloud.httpRequest(options).done(function(rsp){ 
      var r = (_.isString(rsp.text)) ? JSON.parse(rsp.text) : rsp.text; 
      console.log("Reponse from Google:"); 
      console.log(r.access_token); 
      console.log(r.expires_in); 
      console.log(r.token_type); 
      response.success(r); 

     }).fail(function(err){ 
      console.error("Failed response from Google:") 
      console.error(err.text) 
      response.error(err); 

     }); 
    }catch(err){ 
     console.error(err); 
     response.error(err); 
    } 
}); 
+0

Поскольку ошибка говорит недействителен грант, вполне возможно, что значение grant_type вы отправляете не в кодировке URL. Используйте encodeURI в строке и попробуйте. Это должно сделать это –

+0

Если я сломаю файл grant_type, он отбрасывает гораздо более ясный ответ об ошибке (пример того, что я добавляю в конце 2): { «error»: «invalid_request», «error_description»: «Недопустимый тип_данных: urn : ietf: params: oauth: grant-type: jwt-bearer2 " } –

+0

Вы пытались encodeURI (" urn: ietf: params: oauth: grant-type: jwt-bearer ") в качестве значения параметра grant_type? –

ответ

2

Используйте тело вместо Params в параметрах запроса