0 votes
by (220 points)
edited by

Hi,

Google recently started to enforce OAuth 2.0 authentication for IMAP, and give "Authentication failure" if not correctly provided.


Information about IMAP headers can be found here:

">https://developers.google.com/gmail/xoauth2_protocol

How to implement this with Rebex Secure Mail?


What I tried was to change my original code from:


imapClient.Login(username, password);


to:


imapClient.Login(accessToken, ImapAuthentication.OAuth20);


But I get the ImapException
"Unexpected continuation request received from the server."

Applies to: Rebex Secure Mail
by (144k points)
edited

It looks like Imap.Login method can't properly handle an OAUTH2 error response. We will fix this and let you know when a hotfix is available.

In the meantime, you can determine the error from a communication log created using Imap object's LogWriter property.

In the log, locate the response:

2014-08-08 14:25:16.509 INFO Imap(1)[1] Command: R00002 AUTHENTICATE XOAUTH2 dXNlcj1zb21ldXNlckBleGFtcGxlLmNvbQFhdXRoPUJlYXJlcio0IzUmxja0JoZEhSaGRtbHpkR0V1WTI5dENnPT0BAQo=
2014-08-08 14:25:16.509 DEBUG Imap(1)[1] Info: State changed from 'Sending' to 'Reading'.
2014-08-08 14:25:16.538 INFO Imap(1)[1] Response: + eyJzdGF0dXMiOiI0MDAiLCJzY2hlbWVzIjoiQmVhcmVyIiwic2NvcGUiOiJodHRwczovL21haWwuZ29vZ2xlLmNvbS8ifQ==

Use Convert.FromBase64 to decode it and Encoding.ToString to convert it to a string:

byte[] val = Convert.FromBase64String("eyJzdGF0dXMiOiI0MDAiLCJzY2hlbWVzIjoiQmVhcmVyIiwic2NvcGUiOiJodHRwczovL21haWwuZ29vZ2xlLmNvbS8ifQ==");
string text = System.Text.Encoding.UTF8.GetString(val);
Console.WriteLine(text);

Please let us know what this actually reveals.

by (220 points)
edited

Hi, I get the exact same response as you do, and I also get the same response if I provide a random string as access token.

Base64 decoded: {"status":"400","schemes":"Bearer","scope":"https://mail.google.com/"}

Using the OAuth 2.0 procedure, I get a successful response from Google, an Access Token, a Refresh Token and a time saying that the access token is valid for an hour.

Do I need to do something with the access token before I pass it to the Login method? So far I've tried to pass it both as the original string from Google, and as a Base64 string, with same result.

by (144k points)
edited

The OAUTH token has to be 'preparad' before calling the Login method - please see Ivan's answer for details.

1 Answer

+1 vote
by (520 points)
edited by
 
Best answer

Update: Rebex Secure Mail 2014 R3 handles OAUTH2 error responses and reports more meaningful errors than previous versions.

Update 2: See also our How to authenticate to Gmail with Rebex Secure Mail using OAuth 2.0 blog post.

Imap.Login method can't properly handle an OAUTH2 error responses yet. This will be solved in the next release. In the meantime, you can use a hotfix (trial version - let us know if you need a full version).

However, an OAUTH token has to be 'prepared' like this before calling the Login method:


var pattern = string.Format("user={0}{1}auth=Bearer {2}{1}{1}", yourEmail, '\x1', yourAccessToken);

var xoauthtoken = Convert.ToBase64String(Encoding.ASCII.GetBytes(pattern));

imap.Login(xoauthtoken, ImapAuthentication.OAuth20);

for more information check this resource

...