LinkedIn抄写OAuth库无法访问LinkedIn帐户

时间:2011-07-05 23:50:30

标签: android oauth linkedin

我正在编写一个概念验证应用,使用scribe OAuth库连接到LinkedIn。

我可以获得请求令牌,但无法将其替换为访问令牌。我一再收到oauth_problem=permission_unknown回复,尽管点击LinkedIn上的'允许',当我被要求进行身份验证时,我被重定向到了。

我已经注册了一个回调,以便当LinkedIn将用户重定向到我的回调时,我的身份验证活动将恢复,并且在onResume中我提取请求令牌和PIN码以用于获取访问令牌,这部分至少似乎是按计划工作。

我的代码在这里:

package com.rockrobot.example.scribelinkedin;

import org.scribe.builder.ServiceBuilder;
import org.scribe.builder.api.LinkedInApi;
import org.scribe.model.OAuthRequest;
import org.scribe.model.Response;
import org.scribe.model.Token;
import org.scribe.model.Verb;
import org.scribe.model.Verifier;
import org.scribe.oauth.OAuthService;
import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.widget.Toast;

public class loginexample extends Activity {
    private static OAuthService service;
    private Token requestToken;
    private Verifier verifier;
    private static final String PROTECTED_RESOURCE_URL = "http://api.linkedin.com/v1/people/~/connections:(id,last-name)";
    private static Boolean authInProgress = false;

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        if ( ! authInProgress ) {
            authInProgress = true;
            service = new ServiceBuilder()
                .provider(LinkedInApi.class)
                .apiKey("XXXXX")
                .apiSecret("YYYYY")
                .callback("callback://whodunit")
                .build();

            System.out.println("=== LinkedIn's OAuth Workflow ===");
            System.out.println();

            // Obtain the Request Token
            System.out.println("Fetching the Request Token...");
            requestToken = service.getRequestToken();
            System.out.println("Got the Request Token!");
            System.out.println();

            System.out.println("Now go and authorize Scribe here:");
            System.out.println(service.getAuthorizationUrl(requestToken));

            Toast.makeText(this, "Please authorize " + getString(R.string.app_name), Toast.LENGTH_LONG).show();

            startActivity (new Intent ( Intent.ACTION_VIEW, Uri.parse(service.getAuthorizationUrl(requestToken))));
        }
    }

    @Override
    protected void onResume() {  
        super.onResume();  
        if (this.getIntent()!=null && this.getIntent().getData()!=null){  
            Uri uri = this.getIntent().getData();  
            if (uri != null && uri.toString().startsWith("callback://whodunit")) {
                verifier = new Verifier ( uri.getQueryParameter("oauth_verifier") );
                    // Trade the Request Token and Verfier for the Access Token
                requestToken = service.getRequestToken();
                    System.out.println("Trading the Request Token for an Access Token...");
                    System.out.println(" ---> Request Token: " + requestToken.getToken());
                    System.out.println(" ---> Request Token Secret: " + requestToken.getSecret());
                    System.out.println(" ---> Verifier: " + verifier.getValue());
                    Token accessToken = service.getAccessToken(requestToken, verifier);
                    System.out.println("Got the Access Token!");
                    System.out.println("(if you're curious it looks like this: " + accessToken + " )");
                    System.out.println();

                    // Now let's go and ask for a protected resource!
                    System.out.println("Now we're going to access a protected resource...");
                    OAuthRequest request = new OAuthRequest(Verb.GET, PROTECTED_RESOURCE_URL);
                    service.signRequest(accessToken, request);
                    Response response = request.send();
                    System.out.println("Got it! Lets see what we found...");
                    System.out.println();
                    System.out.println(response.getBody());

                    System.out.println();
                    System.out.println("Thats it man! Go and build something awesome with Scribe! :)");
            }  
        }

    } 
}

我的清单的相关摘录在这里:

    <activity android:name=".loginexample"
              android:label="@string/app_name">
        <intent-filter>
            <action android:name="android.intent.action.VIEW"></action>
            <category android:name="android.intent.category.BROWSABLE"></category>
            <category android:name="android.intent.category.DEFAULT"></category>
            <data android:host="whodunit" android:scheme="callback"></data>
        </intent-filter>
    </activity>

最后,我的logcat在这里:

07-05 23:39:58.204: INFO/System.out(300): === LinkedIn's OAuth Workflow ===
07-05 23:39:58.204: INFO/System.out(300): Fetching the Request Token...
07-05 23:39:59.284: INFO/System.out(300): Body = oauth_token=88d888e9-f05b-4b3e-ae64-97c4878cbf06&oauth_token_secret=d5685691-0ff7-4c60-954c-62b9cf16028b&oauth_callback_confirmed=true&xoauth_request_auth_url=https%3A%2F%2Fapi.linkedin.com%2Fuas%2Foauth%2Fauthorize&oauth_expires_in=599
07-05 23:39:59.284: INFO/System.out(300): Got the Request Token!
07-05 23:39:59.284: INFO/System.out(300): Now go and authorize Scribe here:
07-05 23:39:59.294: INFO/System.out(300): https://api.linkedin.com/uas/oauth/authorize?oauth_token=88d888e9-f05b-4b3e-ae64-97c4878cbf06
07-05 23:39:59.354: INFO/ActivityManager(59): Starting activity: Intent { act=android.intent.action.VIEW dat=https://api.linkedin.com/uas/oauth/authorize?oauth_token=88d888e9-f05b-4b3e-ae64-97c4878cbf06 cmp=com.android.browser/.BrowserActivity }
07-05 23:39:59.484: INFO/ActivityManager(59): Start proc com.android.browser for activity com.android.browser/.BrowserActivity: pid=306 uid=10019 gids={3003, 1015}
07-05 23:39:59.964: INFO/ActivityManager(59): Displayed activity com.rockrobot.example.scribelinkedin/.loginexample: 3404 ms (total 3404 ms)
07-05 23:40:00.894: INFO/ActivityThread(306): Publishing provider browser: com.android.browser.BrowserProvider
07-05 23:40:03.914: INFO/ActivityManager(59): Displayed activity com.android.browser/.BrowserActivity: 4440 ms (total 4440 ms)
07-05 23:40:05.744: INFO/ActivityManager(59): Starting activity: Intent { act=android.intent.action.VIEW cat=[android.intent.category.BROWSABLE] dat=https://www.linkedin.com/uas/oauth/authorize?oauth_token=88d888e9-f05b-4b3e-ae64-97c4878cbf06 cmp=com.android.browser/.BrowserActivity }
07-05 23:40:14.414: INFO/ActivityManager(59): Process com.android.email (pid 245) has died.
07-05 23:40:19.294: INFO/ActivityManager(59): Starting activity: Intent { act=android.intent.action.VIEW cat=[android.intent.category.BROWSABLE] dat=callback://whodunit?oauth_token=88d888e9-f05b-4b3e-ae64-97c4878cbf06&oauth_verifier=41304 cmp=com.rockrobot.example.scribelinkedin/.loginexample }
07-05 23:40:20.564: INFO/System.out(300): Body = oauth_token=5362f57e-d5b5-4007-a166-d02d21e80a4d&oauth_token_secret=b4d263ec-f29f-4e8b-876b-5c7a6280900f&oauth_callback_confirmed=true&xoauth_request_auth_url=https%3A%2F%2Fapi.linkedin.com%2Fuas%2Foauth%2Fauthorize&oauth_expires_in=599
07-05 23:40:20.564: INFO/System.out(300): Trading the Request Token for an Access Token...
07-05 23:40:20.564: INFO/System.out(300):  ---> Request Token: 5362f57e-d5b5-4007-a166-d02d21e80a4d
07-05 23:40:20.564: INFO/System.out(300):  ---> Request Token Secret: b4d263ec-f29f-4e8b-876b-5c7a6280900f
07-05 23:40:20.564: INFO/System.out(300):  ---> Verifier: 41304
07-05 23:40:21.464: INFO/System.out(300): Body = oauth_problem=permission_unknown
07-05 23:40:21.514: ERROR/AndroidRuntime(300): FATAL EXCEPTION: main
07-05 23:40:21.514: ERROR/AndroidRuntime(300): java.lang.RuntimeException: Unable to resume activity {com.rockrobot.example.scribelinkedin/com.rockrobot.example.scribelinkedin.loginexample}: org.scribe.exceptions.OAuthException: Response body is incorrect. Can't extract token and secret from this: 'oauth_problem=permission_unknown'
07-05 23:40:21.514: ERROR/AndroidRuntime(300):     at android.app.ActivityThread.performResumeActivity(ActivityThread.java:3128)
07-05 23:40:21.514: ERROR/AndroidRuntime(300):     at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:3143)
07-05 23:40:21.514: ERROR/AndroidRuntime(300):     at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2684)
07-05 23:40:21.514: ERROR/AndroidRuntime(300):     at android.app.ActivityThread.access$2300(ActivityThread.java:125)
07-05 23:40:21.514: ERROR/AndroidRuntime(300):     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2033)
07-05 23:40:21.514: ERROR/AndroidRuntime(300):     at android.os.Handler.dispatchMessage(Handler.java:99)
07-05 23:40:21.514: ERROR/AndroidRuntime(300):     at android.os.Looper.loop(Looper.java:123)
07-05 23:40:21.514: ERROR/AndroidRuntime(300):     at android.app.ActivityThread.main(ActivityThread.java:4627)
07-05 23:40:21.514: ERROR/AndroidRuntime(300):     at java.lang.reflect.Method.invokeNative(Native Method)
07-05 23:40:21.514: ERROR/AndroidRuntime(300):     at java.lang.reflect.Method.invoke(Method.java:521)
07-05 23:40:21.514: ERROR/AndroidRuntime(300):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)
07-05 23:40:21.514: ERROR/AndroidRuntime(300):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)
07-05 23:40:21.514: ERROR/AndroidRuntime(300):     at dalvik.system.NativeStart.main(Native Method)
07-05 23:40:21.514: ERROR/AndroidRuntime(300): Caused by: org.scribe.exceptions.OAuthException: Response body is incorrect. Can't extract token and secret from this: 'oauth_problem=permission_unknown'
07-05 23:40:21.514: ERROR/AndroidRuntime(300):     at org.scribe.extractors.TokenExtractorImpl.extract(TokenExtractorImpl.java:42)
07-05 23:40:21.514: ERROR/AndroidRuntime(300):     at org.scribe.extractors.TokenExtractorImpl.extract(TokenExtractorImpl.java:27)
07-05 23:40:21.514: ERROR/AndroidRuntime(300):     at org.scribe.oauth.OAuth10aServiceImpl.getAccessToken(OAuth10aServiceImpl.java:67)
07-05 23:40:21.514: ERROR/AndroidRuntime(300):     at com.rockrobot.example.scribelinkedin.loginexample.onResume(loginexample.java:78)
07-05 23:40:21.514: ERROR/AndroidRuntime(300):     at android.app.Instrumentation.callActivityOnResume(Instrumentation.java:1149)
07-05 23:40:21.514: ERROR/AndroidRuntime(300):     at android.app.Activity.performResume(Activity.java:3823)
07-05 23:40:21.514: ERROR/AndroidRuntime(300):     at android.app.ActivityThread.performResumeActivity(ActivityThread.java:3118)
07-05 23:40:21.514: ERROR/AndroidRuntime(300):     ... 12 more
07-05 23:40:21.684: WARN/ActivityManager(59):   Force finishing activity com.rockrobot.example.scribelinkedin/.loginexample
07-05 23:40:21.684: WARN/ActivityManager(59):   Force finishing activity com.android.browser/.BrowserActivity
07-05 23:40:22.454: WARN/ActivityManager(59): Activity pause timeout for HistoryRecord{44f81be8 com.rockrobot.example.scribelinkedin/.loginexample}
07-05 23:40:24.675: INFO/ActivityManager(59): Process com.rockrobot.example.scribelinkedin (pid 300) has died.
07-05 23:40:24.694: INFO/WindowManager(59): WIN DEATH: Window{450717b8 com.rockrobot.example.scribelinkedin/com.rockrobot.example.scribelinkedin.loginexample paused=false}
07-05 23:40:24.914: WARN/InputManagerService(59): Starting input on non-focused client com.android.internal.view.IInputMethodClient$Stub$Proxy@4509ce80 (uid=10019 pid=306)

正如你在logcat中看到的那样,我得到了一个oauth令牌和token_secret,但是我无法将这些用于访问令牌,而是继续收到oauth_problem=permission_unknown错误。

我知道LinkedIn声称与他们实施OAuth相当strict,我似乎无法看到我出错的地方 - 也许我已经盯着它看了太久了,是你们进来的地方。

有人有什么想法吗? OAuth并不简单,但我不敢相信这也很复杂。我可能错过了一些显而易见的东西,但却无法弄清楚它是什么。

1 个答案:

答案 0 :(得分:4)

在您的onResume方法中,您获得了一个新的请求令牌,但验证码来自您在onCreate方法中获得的请求令牌。因此,您尝试使用第二个请求令牌获取访问令牌,但验证码对应于第一个请求令牌 - 因此,您不会获得访问令牌。有意义吗?

如果你从onResume方法中取出requestToken = service.getRequestToken();,那么这应该可以正常运行,因为其他一切看起来都是正确的。