Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
432 views
in Technique[技术] by (71.8m points)

oauth - Android Dev - Callback URL not working... (0_o)

I'm working on an android application for my research, and I am working with OAuth (signpost library) to gain access to user data from a web service which is also a part of the development process. I am able to flow through the common steps of OAuth, and I use a Uri (for callback to the app), and can get to the step where I invoke the devices browser, choose to verify my app, and the next step is SUPPOSED to redirect the browser BACK to the application....

Instead I get an error that reads something like "you do not have permission to open:

appSchema://appName?authorizationSensitiveInfo..." the appendages after the '?' are the oauth_token and oauth_verifier from the service (we can assume all steps up until the redirection are "correct").

Possible problems lie within the appSchema://appName part. from my understanding this is the redirect URL which tells the Uri to use the phone's browser to locate my application and invoke the onResume() method. Where do the values for appSchema://appName come from (defined in manifest? if so where?).

Why the problem with permission? Must I set permissions for my Uri to access my app? I'm lost...if you need code snippets to help me please reply, I didn't include any code because this is more like a concept I just missed...I'm not at my machine now but I can supply code if that would make things easier to understand. Really beating my head in here...

IN RESPONE TO A GREAT ANSWER HERE IS HOW I HANDLE MY ON RESUME

protected void onResume() {
    super.onResume();       
    Uri uri = this.getIntent().getData();
    if (uri != null && uri.toString().startsWith(CALLBACK_URL)) {
        Log.d("StepGreenM", uri.toString());
        String verifier = uri.getQueryParameter(OAuth.OAUTH_VERIFIER);
        Log.d("StepGreenM", verifier);
        try {

            provider.retrieveAccessToken(consumer, verifier);
            TOKEN = consumer.getToken();
            REQUEST_SECRET = consumer.getTokenSecret();

            Log.d("StepGreenM", TOKEN);
            Log.d("StepGreenM", REQUEST_SECRET);

        } catch (OAuthMessageSignerException e) {
            e.printStackTrace();
        } catch (OAuthNotAuthorizedException e) {
            e.printStackTrace();
        } catch (OAuthExpectationFailedException e) {
            e.printStackTrace();
        } catch (OAuthCommunicationException e) {
            e.printStackTrace();
        }
    }

    uri = getIntent().getData();
    if (uri != null && CALLBACK_URI.getScheme().equals(uri.getScheme())) {
        String token = settings.getString(HomeScreen.REQUEST_TOKEN, null);
        String secret = settings.getString(HomeScreen.REQUEST_SECRET, null);
        Intent i = new Intent(Intent.ACTION_VIEW); // Intent to go to the action view

        try {
            if(!(token == null || secret == null)) {
                consumer.setTokenWithSecret(token, secret);
            }
            String otoken = uri.getQueryParameter(OAuth.OAUTH_TOKEN);
            String verifier = uri.getQueryParameter(OAuth.OAUTH_VERIFIER);

            // We send out and save the request token, but the secret is not the same as the verifier
            // Apparently, the verifier is decoded to get the secret, which is then compared - crafty
            // This is a sanity check which should never fail - hence the assertion
            Assert.assertEquals(otoken, consumer.getToken());

            // This is the moment of truth - we could throw here
            provider.retrieveAccessToken(consumer, verifier);
            // Now we can retrieve the goodies
            token = consumer.getToken();
            secret = consumer.getTokenSecret();
            //Save it to a settings file
            HomeScreen.saveAuthInformation(settings, token, secret);
            // Clear the request stuff, now that we have the real thing
            HomeScreen.saveRequestInformation(settings, null, null);
            i.putExtra(USER_TOKEN, token);
            i.putExtra(CONSUMER_SECRET, secret);

            //GO TO APPLICATION

        } catch (OAuthMessageSignerException e) {
            e.printStackTrace();
        } catch (OAuthNotAuthorizedException e) {
            e.printStackTrace();
        } catch (OAuthExpectationFailedException e) {
            e.printStackTrace();
        } catch (OAuthCommunicationException e) {
            e.printStackTrace();
        } finally {
            startActivity(i); // we either authenticated and have the extras or not, but are going to the action view
            this.setContentView(R.layout.indivaction);
            finish();
        }
    }
}

Not sure what really makes this fall apart...but like I said it force closes when this method is invoked. I know it makes it past the redirect because I use an httpSniffer to check the messages to and from the server...

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

In order for the callback uri to work properly you need to add an intent filter similar to the following to your manifest in the activity you want to use it in.

   <intent-filter>          
    <action android:name="android.intent.action.VIEW"/>     
    <category android:name="android.intent.category.DEFAULT"/>
    <category android:name="android.intent.category.BROWSABLE"/>
    <data android:scheme="appSchema" android:host="appName"/> 
   </intent-filter>

Now, if your activity is using singleInstance/singleTask, you should use something similar to the following:

@Override
public void onNewIntent(Intent intent) {

    super.onNewIntent(intent);
    Uri uri = intent.getData();
    String oauthToken = uri.getQueryParameter("oauth_token");
    String oauthVerifier = uri.getQueryParameter("oauth_verifier");

    //...do what you need with the parameters
}

if not using singleTask or singleInstance, you can do

@Override
public void onResume() {

    super.onResume();
    Intent intent = getIntent();
    Uri uri = intent.getData();
    String oauthToken = uri.getQueryParameter("oauth_token");
    String oauthVerifier = uri.getQueryParameter("oauth_verifier");

    //...do what you need with the parameters
}

I believe this should work.

Also, if I'm not mistaken, the callback url you provide should include the ?, so "appSchema://appName?"


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...