在javascript / node.js中连接到Gmail IMAP API

Connecting to the Gmail IMAP API in javascript/node.js

我正试图通过它的IMAPAPI连接到Gmail。我使用的是BrunoMorency的节点imap库。为了创建OAuth_签名、时间戳和nonce,我使用了另一个库。

更具体地说:资源所有者已经对消费者进行了身份验证。所以我有一个访问令牌+秘密。当然,我还有消费者的秘密+代币。所以我想用这里描述的XAUTH机制登录(标题:SASL初始客户机请求)。

执行代码时,我得到一个错误:

1
Error while executing request: Invalid credentials d43if2188869web.36

我想知道我做错了什么。实际上,可能还有更多的原因。错误的base64编码(尽管编码可能是正确的,因为不同的编码会有不同的错误,但我敢肯定这不是)、错误的签名计算(更新:我现在用http://oauth.net/core/1.0a/sig_base_example测试了这个问题)、nonce calculating或其他方法。

我可以在Java应用程序中使用相同的凭据(消费者+源代码所有者)进行身份验证,因此凭证最可能不是错误的原因(只是错误的编码/签名计算)。

最后是代码。我遗漏了消费者的钥匙+秘密,也没有因为明显的原因而泄露来源所有者的令牌+秘密)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
var oauth_version ="1.0";
var oauth_timestamp = OAuth.timestamp();
var oauth_nonce = OAuth.nonce(6); //random nonce?

var oauth_consumer_key ="NOTFORYOU"; //validated
var oauth_consumer_secret ="NOTFORYOU"; //validated
var oauth_token ="NOTFORYOU"; //validated
var oauth_token_secret ="NOTFORYOU"; //validated
var email ="NOTFORYOU"; //validated

var oauth_signature_method ="HMAC-SHA1";
var method ="GET";
var action ="https://mail.google.com/b/"
    +email
    +"/imap/"; //gmail's request url

//signature
var oauth_signature_method ="HMAC-SHA1"; //from https://developers.google.com/google-apps/gmail/oauth_protocol

//example values for validating signature from     http://oauth.net/core/1.0a/#sig_base_example
oauth_consumer_key="dpf43f3p2l4k3l03";
oauth_nonce="kllo9940pd9333jh";
oauth_signature_method="HMAC-SHA1";
oauth_timestamp="1191242096";
oauth_token="nnch734d00sl2jdk";
oauth_version="1.0";
action="http://photos.example.net/photos?file=vacation.jpg&size=original";
method="GET";

//signature
var signature_basestring_parameters = {
    oauth_version: oauth_version
    , oauth_consumer_key: oauth_consumer_key
    , oauth_timestamp: oauth_timestamp
    , oauth_nonce: oauth_nonce
    , oauth_token: oauth_token
    , oauth_signature_method: oauth_signature_method
}

//var signature_basestring = oauth_consumer_key+"&"+oauth_token_secret;
var signature_basestring = OAuth.SignatureMethod.getBaseString({method: method, action: action, parameters: signature_basestring_parameters});

var methodName = oauth_signature_method;
var signer = OAuth.SignatureMethod.newMethod(methodName, {
                    consumerSecret: oauth_consumer_secret,
                    tokenSecret: oauth_token_secret
                }
                   );
console.log("signature_basestring=["+signature_basestring+"]");

var oauth_signature = signer.getSignature(signature_basestring);

console.log("oauth_signature=["+oauth_signature+"]");

oauth_signature=OAuth.percentEncode(oauth_signature);

console.log("(escaped) oauth_signature=["+oauth_signature+"]"); //prints out tR3%2BTy81lMeYAr%2FFid0kMTYa%2FWM%3D as in the [example](http://oauth.net/core/1.0a/#sig_base_example)

//base-string
var baseStringDecoded = "GET"
    +""
    +"https://mail.google.com/b/"+email+"/imap/"
    +""
    +"oauth_consumer_key=""+oauth_consumer_key+"","
    +"oauth_nonce=""+oauth_nonce+"","
    +"oauth_signature=""+oauth_signature+"","
    +"oauth_signature_method=""+oauth_signature_method+"","
    +"oauth_timestamp=""+oauth_timestamp+"","
    +"oauth_token=""+oauth_token+"","
    +"oauth_version=""+oauth_version+""";

var baseString = Base64.encode(  //base64 from http://www.webtoolkit.info/javascript-base64.html
    baseStringDecoded
);


//create imap connection
var imap = new ImapConnection({
                  host: 'imap.gmail.com',
                  port: 993,
                  secure: true,
                  debug: true,
                  xoauth: baseString
              });

更新:我找到了一个如何生成基签名字符串的示例。基于此,我更改了我的代码。因此,现在我得到了与示例中相同的签名结果(为签名生成基字符串、计算签名值、编码签名值的百分比)。这意味着我(即使用的OAuth库)最有可能以正确的方式计算OAuth_签名,而其他事情却出现了问题。


我终于成功了。最后,我的问题是,我更改了OAuth.js中用于测试OAuth示例的密钥,将它改回原来的版本完成了任务。

所以上面的示例现在应该可以在gmail imap api上进行身份验证了。


如果您认为它与编码相关,请查看如何在node.js中进行base64编码?对于节点的bas64而不是webtoolkit。