我正在编写一个概念验证应用,使用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并不简单,但我不敢相信这也很复杂。我可能错过了一些显而易见的东西,但却无法弄清楚它是什么。
答案 0 :(得分:4)
在您的onResume
方法中,您获得了一个新的请求令牌,但验证码来自您在onCreate
方法中获得的请求令牌。因此,您尝试使用第二个请求令牌获取访问令牌,但验证码对应于第一个请求令牌 - 因此,您不会获得访问令牌。有意义吗?
如果你从onResume方法中取出requestToken = service.getRequestToken();
,那么这应该可以正常运行,因为其他一切看起来都是正确的。