Не удается понять поток OAuth для этого API

Может ли кто-нибудь помочь мне понять поток OAuth для API Академии Хана. Доступ к нему можно получить по этой ссылке: https://github.com/Khan/khan-api/wiki/Khan-Academy-API-Authentication

Я использую Скриб.

Вот рабочий код:

     OAuthService serv = new ServiceBuilder().provider(KhanApi.class)
     .apiKey("").apiSecret("")
     .build();
     Token token = new Token("", "");

     OAuthRequest req = new OAuthRequest(Verb.GET,
     "http://www.khanacademy.org/api/auth/request_token");

     serv.signRequest(token, req);

     Response resp = req.send();
     System.out.println(resp.getBody());

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

Вот две разные вещи, которые я пробовал, но у меня не получилось, и их результаты:

1)

 OAuthService serv = new ServiceBuilder().provider(KhanApi.class)
 .apiKey("***").apiSecret("***")
 .build();
 Token token = serv.getRequestToken();

результат:

Исключение в потоке "основной" org.scribe.exceptions.OAuthException: тело ответа неверно. Невозможно извлечь токен и секрет из этого:

<!DOCTYPE html>
<html>
    <head>
        <title>Login to Khan Academy</title>

        <style>
            #login-page {
                padding-top: 18px;
            }
            .providers {
                height: 100px;
            }
            .providers .provider .img-container {
                height: 80px;
            }

           .horizontal-separator .separator-text {
                background-color: white;
                margin-left: 185px;
            }
            .pw-login {
                width: 415px;
                height: auto;
                text-align: right;
            }
            .pw-login img.tree {
                float: left;
            }

        </style>


    </head>
    <body>
        <article id="login-page">
            <div id="login-inner-content">
                <form method="POST"
                    class="auth-form"
                    id="login-form"
                    action="https://khan-academy.appspot.com/login/mobileoauth">
                <h3>Login to Khan Academy</h3>
                <input type="hidden" name="oauth_map_id" value="889298340">
                <input type="hidden" name="view" value="normal">


                <ul class="providers">
                    <li class="provider action-gradient" title="Google">

            </div>
        </article>
    </body>
</html>'
    at org.scribe.extractors.TokenExtractorImpl.extract(TokenExtractorImpl.java:41)
    at org.scribe.extractors.TokenExtractorImpl.extract(TokenExtractorImpl.java:27)
    at org.scribe.oauth.OAuth10aServiceImpl.getRequestToken(OAuth10aServiceImpl.java:52)
    at com.saeid.scribe.oauth.Main.main(Main.java:117)

Ответ представляет собой строку поврежденного html-файла (сломанного в том смысле, что изображения не отображаются...)

2) Также я пробовал:

    OAuthRequest req = new OAuthRequest(Verb.GET,
            "http://www.khanacademy.org/api/auth/request_token");

    Map<String, String> parameters = generateParameters("GET",
            "http://www.khanacademy.org/api/auth/request_token");

    req.addQuerystringParameter("oauth_consumer_key", parameters.get("oauth_consumer_key"));
    req.addQuerystringParameter("oauth_nonce", parameters.get("oauth_nonce"));
    req.addQuerystringParameter("oauth_signature", parameters.get("oauth_signature"));
    req.addQuerystringParameter("oauth_signature_method", parameters.get("oauth_signature_method"));
    req.addQuerystringParameter("oauth_timestamp", parameters.get("oauth_timestamp"));
    req.addQuerystringParameter("oauth_version", parameters.get("oauth_version"));

    Response res = req.send();

результат:

OAuth error. Invalid signature. Expected signature base string: GET&http%3A%2F%2Fwww.khanacademy.org%2Fapi%2Fauth%2Frequest_token&oauth_consumer_key%3D***********%26oauth_nonce%3D1341526030%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1341526030%26oauth_version%3D1.0

Я использую ту же базовую строку для создания подписи и использую ключ потребителя в качестве ключа для метода HMAC-SHA1.

Вот как выглядит KhanAPI: import org.scribe.builder.api.DefaultApi10a; импортировать org.scribe.model.Token;

открытый класс KhanApi расширяет DefaultApi10a{

@Override
public String getAccessTokenEndpoint() {
    return "http://www.khanacademy.org/api/auth/access_token";
}

@Override
public String getAuthorizationUrl(Token arg0) {
    return "";
}

@Override
public String getRequestTokenEndpoint() {
    return "http://www.khanacademy.org/api/auth/request_token";
}

}

Может кто-нибудь мне помочь? Спасибо,


person Saeid Farivar    schedule 05.07.2012    source источник


Ответы (2)


Разве Scribe не добавляет все необходимые параметры OAuth и не выполняет подписание за вас? я смотрю на пример LinkedIn, который основан на потоке OAuth 1.0a по умолчанию, и я не вижу, чтобы он делал что-то подобное.

https://github.com/fernandezpablo85/scribe-java/blob/master/src/test/java/org/scribe/examples/LinkedInExample.java

если вам нужно вручную сформулировать URL-адрес и подписать его самостоятельно, что именно Scribe делает для вас?

person Jeffrey Blattman    schedule 05.07.2012
comment
Спасибо за ответ. да вы правы, я тоже пробовал писца. проблема в том, что поставщик API не предоставил URL-адрес аутентификации, необходимый для реализации класса API. Не могли бы вы взглянуть на поток присяги их API и сообщить мне, что вы понимаете? - person Saeid Farivar; 06.07.2012
comment
Вы говорите, что ваш провайдер API поддерживает только двухсторонний oauth? если так, я не думаю, что Scribe поддерживает это (легко). вы на собственном опыте понимаете, почему OAuth 2.0 не требует подписи... сложно разобраться. - person Jeffrey Blattman; 06.07.2012
comment
Я предполагаю, что это должен быть двуногий, я не уверен, хотя я только новичок. Вот поток: вам нужно перенаправить пользователя на URL-адрес с такими параметрами, как Consumer_key, oauth_signatuer,... затем он должен перенаправить пользователя на веб-страницу, на которой пользователь может ввести свою конфиденциальность. тогда браузер вернет URL-адрес с токеном запроса и секретом ..... это то, что я использую для этого Scribe? - person Saeid Farivar; 06.07.2012
comment
Вы используете Scribe или нет? кажется, вы используете некоторые классы из какого-то API OAuth, но вы также говорите, что подписываете его вручную. либо используйте Scribe и позвольте ему добавить параметры для вас, либо создайте и отправьте запрос вручную (например, используя http-клиент apache). вполне вероятно, что все, что отправляется, на самом деле представляет собой смесь параметров, добавленных Scribe, и ваших собственных, что определенно приведет к неправильной подписи. - person Jeffrey Blattman; 06.07.2012
comment
То, что я описал, взято из их документации по API для OAuth. На самом деле я пытался сам отправить параметры, но мне это не удалось. прямо сейчас я предполагаю, что Scribe делает это для меня, хотя я не уверен, какие значения отправляет Scribe и отличаются ли они от того, что ожидает этот API или нет .... когда я использую Scribe, я получаю html-код, который я предполагаю, что неправильный ответ, потому что я не вижу изображений, а ссылки не работают. Предположительно, после успешного входа в систему я должен получить токен запроса для дальнейших процессов, которые я не получаю никаких параметров... - person Saeid Farivar; 06.07.2012
comment
я не думаю, что вы понимаете. вы используете Scribe, и Scribe (пытается) добавить все эти параметры за вас. вам не нужно добавлять их, если вы используете Scribe. либо используйте Scribe и позвольте ему добавить их для вас, либо не используйте Scribe и добавьте их вручную. если вы делаете запрос с помощью класса OAuthRequest, вы используете Scribe. вам нужно использовать HTTP-библиотеку более низкого уровня, такую ​​​​как HTTP-клиент apache или java.net, если вы хотите добавить эти параметры вручную. - person Jeffrey Blattman; 06.07.2012
comment
Понятно. сейчас мой код выглядит так: OAuthService serv = new ServiceBuilder().provider(KhanApi.class) .apiKey().apiSecret() .build(); Поэтому я не добавляю никаких параметров. затем я пытаюсь получить токен запроса с помощью Token token = serv.getRequestToken(); который выдает исключение, как я уже упоминал в своем вопросе. - person Saeid Farivar; 06.07.2012
comment
Вы можете опубликовать свой файл KhanApi.java? Кроме того, вы проверили правильность значений ключа и секрета API? - person Jeffrey Blattman; 06.07.2012
comment
еще раз, какой код ответа от неудачного HTTP-запроса? это, вероятно, в исключении. - person Jeffrey Blattman; 06.07.2012
comment
Я обновил вопрос. Это не ошибка http. это исключение, вызванное запуском getRequestToken(). - person Saeid Farivar; 06.07.2012
comment
сломанный HTML должен сообщать об ошибке HTTP. вам нужно видеть, что сервер говорит в ответ на Scribe. - person Jeffrey Blattman; 06.07.2012
comment
хорошо, теперь вот код, который я попробовал сейчас OAuthService serv = new ServiceBuilder().provider(KhanApi.class) .apiKey().apiSecret() .build() ; Токен токен = новый токен (, ); OAuthRequest req = new OAuthRequest(Verb.GET, khanacademy.org/api/auth/request_token); serv.signRequest (токен, запрос); Ответ resp = req.send(); System.out.println(соответственно.getBody()); Кажется, что ответ - это сама форма входа.... - person Saeid Farivar; 06.07.2012
comment
Кажется, это трехсторонний поток присяги... Если это форма входа, я должен перенаправить пользователя на нее для аутентификации. то, согласно документации API, после успешного входа пользователя в систему я смогу получить токен запроса... - person Saeid Farivar; 06.07.2012
comment
Спасибо @Jeffrey. Мне удалось получить токен запроса... Я обновлю вопрос рабочим кодом.... - person Saeid Farivar; 06.07.2012

Этот API возвращает ожидаемую базовую строку, и это здорово. Вы можете запустить scribe в режиме отладки и посмотреть, какую базовую строку вы генерируете, например:

 OAuthService serv = new ServiceBuilder().provider(KhanApi.class)
 .apiKey("***").apiSecret("***")
 .debug()
 .build();
person Pablo Fernandez    schedule 06.07.2012
comment
Спасибо за ответ. Я использую режим отладки, чтобы увидеть ожидаемую базовую строку, или есть способ ее распечатать? - person Saeid Farivar; 06.07.2012