Проверка подписанных запросов от контекстного гаджета Gmail

Итак, я использую gadgets.io.makeRequest(url, callback, params) для отправки запросов из контекстного гаджета Gmail и проверки этих запросов на стороне сервера.

Чтобы уточнить, я использую следующие параметры makeRequest на стороне гаджета:

params[gadgets.io.RequestParameters.CONTENT_TYPE] = gadgets.io.ContentType.DOM;
params[gadgets.io.RequestParameters.AUTHORIZATION] = gadgets.io.AuthorizationType.SIGNED;
params["OAUTH_SERVICE_NAME"] = "HMAC";
params[gadgets.io.RequestParameters.METHOD] = gadgets.io.MethodType.GET;

Я получил ConsumerKey и ConsumerSecret гаджета с сайта https://www.google.com/gadgets/directory/verify
Согласно документации Google, запрос подписывается контейнером в соответствии с Процесс подписи OAuth Метод HMAC-SHA1.

На стороне сервера я получаю следующий запрос:

http://my.dev.machine.com/blapage.aspx?oauth_body_hash=2jmj7l5rSw0yVb/vlWAYkK/YBwk=&opensocial_owner_id=103030060674287937707&opensocial_viewer_id=103030060674287937707&opensocial_app_id=103129310198020657787&opensocial_app_url=http://my.dev.machine.com/gadget.xml&oauth_version=1,0&oauth_timestamp=1284403586&oauth_nonce=6436223395511631796&opensocial_container=HTTP://mail.google.com&oauth_consumer_key=419336943235&oauth_signature_method=HMAC-SHA1&oauth_signature=bshZj9XOXECdYiyR1J8Etnadv5c=»отн=

Затем я подписываю этот запрос в соответствии с той же спецификацией OAuth, которую должен использовать Google, но подписи не совпадают.

Я уже пытался подписать запрос, используя 2 разные библиотеки:

  1. Наша доморощенная библиотека .Net, которая используется для подписи запросов на авторизацию Gmail IMAP OAuth (которая использует тот же метод подписи, и там он работает просто отлично).
  2. Одна из предоставленных библиотек opensocial (http://code.google.com/p/opensocial-net-client/)

Обе библиотеки производят аналогичные базовые строки подписи. Однако, как ни странно, они производят разные подписи, и ни одна из этих подписей не совпадает с той, которую отправил Google в параметре oauth_signature!

Уважаемые разработчики гаджетов, надеюсь, кому-то из вас повезло больше, чем мне, и этот метод проверки подписи заработал. Пожалуйста, скажите мне, что я делаю неправильно здесь.

Заранее спасибо,
буру


person buru    schedule 15.09.2010    source источник
comment
взгляните на это, он имеет дело с проблемой, похожей на urs google.com/support/forum/p/apps-apis/   -  person ACP    schedule 21.09.2010
comment
@Pandiya Chendur, к сожалению, я являюсь автором темы на справочном форуме GoogleApps API...   -  person buru    schedule 21.09.2010


Ответы (2)


Я успешно использовал это:

public Boolean ValidateSignature(String method, Uri url)
        {
            String normalizedUrl, normalizedRequestParameters;

            List<QueryParameter> parameters = new List<QueryParameter>();
            parameters.AddRange(GetQueryParameters(url.Query));

            var sigParam = parameters.Find(p => p.Name == OAuthSignatureKey);
            if (sigParam == null)
                return false;
            var expected = sigParam.Value;

            parameters.Remove(parameters.Find(p => p.Name == OAuthSignatureKey));
            parameters.Sort(new QueryParameterComparer());

            normalizedUrl = string.Format("{0}://{1}", url.Scheme, url.Host);
            if (!((url.Scheme == "http" && url.Port == 80) || (url.Scheme == "https" && url.Port == 443)))
            {
                normalizedUrl += ":" + url.Port;
            }
            normalizedUrl += url.AbsolutePath;
            normalizedRequestParameters = NormalizeRequestParameters(parameters);

            StringBuilder signatureBase = new StringBuilder();
            signatureBase.AppendFormat("{0}&", method.ToUpper());
            signatureBase.AppendFormat("{0}&", UrlEncode(normalizedUrl));
            signatureBase.AppendFormat("{0}", UrlEncode(normalizedRequestParameters));

            HMACSHA1 hmacsha1 = new HMACSHA1();
            hmacsha1.Key = Encoding.ASCII.GetBytes(string.Format("{0}&{1}", UrlEncode(ConsumerSecret), ""));//string.IsNullOrEmpty(tokenSecret) ? "" : UrlEncode(tokenSecret)));

            var computed = GenerateSignatureUsingHash(signatureBase.ToString(), hmacsha1);
            return expected == UrlEncode(computed);
        } 

вместе с кодом вы можете найти здесь: http://oauth.googlecode.com/svn/code/csharp/OAuthBase.cs

EDIT: при выполнении запросов и отправке параметров через get или post это не работало. Кажется, проблема в том, что Gmail сортирует параметры с прописными буквами первыми. Я использовал только параметры нижнего регистра, но вы можете легко исправить код, чтобы убедиться, что верхний регистр стоит перед строчными.

person Daniel    schedule 19.05.2011

Метод Дэниэлса отлично работает с одним небольшим изменением.

  • GetQueryParameters нужна реализация для получения всех параметров запроса. Реализация в OAuthBase возвращает только те, у которых нет префикса «oauth_».

Моя основная проблема заключалась в том, что гаджет, выполняющий вызов, использовал gadgets.io.makeRequest для «http://myserver.com», но страница обработки была «http://myserver.com/default.aspx». Подпись не прошла проверку из-за этой разницы. Вызов http://myserver.com/default.aspx с использованием gadgets.io.makeRequest из гаджета решил проблему.

person 0E322070    schedule 06.09.2011