0

I am trying to create a simple oauth2 flow using AppAuth. I am following this tutorial of AppAuth. It is doing good up to making an oauth request but after authorization when it comes to main activity then it never calls onNewIntent, I also checked the question discussed here.

Edit: When I use onResume method then it comes to onResume method after authorization but with "android.intent.action.MAIN" action. Where it should come with "com.google.codelabs.appauth.HANDLE_AUTHORIZATION_RESPONSE" action on onResume.

Any suggestion why it is happening?

following is the MainActivity class

public class MainActivity extends AppCompatActivity {
    private static final String USED_INTENT = "USED_INTENT";
    public static final String LOG_TAG = "AppAuthSample";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    public void setupAuthorization(View view) {
        AuthorizationServiceConfiguration serviceConfiguration = new AuthorizationServiceConfiguration(
                Uri.parse("https://accounts.google.com/o/oauth2/v2/auth"), //* auth endpoint *//*,
                Uri.parse("https://oauth2.googleapis.com/token") //* token endpoint *//*
        );

        String clientId = "MY_ID.apps.googleusercontent.com";
        Uri redirectUri = Uri.parse("com.demo.testdriveapi:/oauth2callback");
        AuthorizationRequest.Builder builder = new AuthorizationRequest.Builder(
                serviceConfiguration,
                clientId,
                "code",
                redirectUri
        );
        builder.setScopes("https://www.googleapis.com/auth/drive.appdata");
        AuthorizationRequest request = builder.build();
        AuthorizationService authorizationService = new AuthorizationService(this);

        String action = "com.google.codelabs.appauth.HANDLE_AUTHORIZATION_RESPONSE";
        Intent postAuthorizationIntent = new Intent(action);
        PendingIntent pendingIntent = PendingIntent.getActivity(this, request.hashCode(), postAuthorizationIntent, 0);
        authorizationService.performAuthorizationRequest(request, pendingIntent);
    }

    @Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
        checkIntent(intent);
    }    
 
    private void checkIntent(@Nullable Intent intent) {
        if (intent != null) {
            String action = intent.getAction();
            switch (action) {
                case "com.google.codelabs.appauth.HANDLE_AUTHORIZATION_RESPONSE":
                    if (!intent.hasExtra(USED_INTENT)) {
                        handleAuthorizationResponse(intent);
                        intent.putExtra(USED_INTENT, true);
                    }
                    break;
                default:
                    // do nothing
            }
        }
    }

    @Override
    protected void onStart() {
        super.onStart();
        checkIntent(getIntent());
    }

    private void handleAuthorizationResponse(@NonNull Intent intent) {
        AuthorizationResponse response = AuthorizationResponse.fromIntent(intent);
        AuthorizationException error = AuthorizationException.fromIntent(intent);
        final AuthState authState = new AuthState(response, error);

        if (response != null) {
            Log.i(LOG_TAG, String.format("Handled Authorization Response %s ", authState.jsonSerializeString()));
            AuthorizationService service = new AuthorizationService(this);
            service.performTokenRequest(response.createTokenExchangeRequest(), new AuthorizationService.TokenResponseCallback() {
                @Override
                public void onTokenRequestCompleted(@Nullable TokenResponse tokenResponse, @Nullable AuthorizationException exception) {
                    if (exception != null) {
                        Log.w(LOG_TAG, "Token Exchange failed", exception);
                    } else {
                        if (tokenResponse != null) {
                            authState.update(tokenResponse, exception);
                            Log.i(LOG_TAG, String.format("Token Response [ Access Token: %s, ID Token: %s ]", tokenResponse.accessToken, tokenResponse.idToken));
                        }
                    }
                }
            });
        }
    }
}

Here is the snippet from AndroidMenifest.xml

<application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
            <intent-filter>
                <action android:name="com.google.codelabs.appauth.HANDLE_AUTHORIZATION_RESPONSE"/>
                <category android:name="android.intent.category.DEFAULT"/>
            </intent-filter>
        </activity>

        <activity android:name="net.openid.appauth.RedirectUriReceiverActivity">
            <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="com.demo.testdriveapi"/>
            </intent-filter>
        </activity>
    </application>

and here is the snippet of activity_main.xml, I only have one button

<Button
        android:id="@+id/buttonAuthorize"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="153dp"
        android:layout_marginTop="288dp"
        android:layout_marginEnd="170dp"
        android:onClick="setupAuthorization"
        android:text="Authorize"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

Edit: Also tried using "android:launchMode="singleTop" but it also doesn't work.

Edit2: Adding screenshot of Google developer console

enter image description here

Karan
  • 752
  • 2
  • 13
  • 34

3 Answers3

0

check the google drive API Dashboard for oAuth authentication and your callback name shall match and it should be registered there as well. And it is with this callback that authorization response is sent back to your activity.

Dixit
  • 71
  • 1
  • 5
  • At my google api console it doesn't ask me for a CallBack Url. In Credential section in only ask for Name, Package Name and SHA1. Where do I put CallBack URL? – Karan Jul 04 '20 at 21:18
  • when you create OAuth section in the API console. for OAuth is asks for callback. When your client key might have been generated so look at that page . I am sure there will be some callback that might have been filled. – Dixit Jul 05 '20 at 18:56
  • Have a look at this and look around , you will get the solution you need to set the callback. Hope this helps https://developers.google.com/tasks/oauth-authorization-callback-handler – Dixit Jul 05 '20 at 19:04
  • Hello Thanks again, but I think google has changed this. Have you tried to create OAuth2 credential recently? Because, it provides you the option of RedirectUri when you select Web Application on console not when you use Android option. However, when I download the JSON for the credential I created for Android the it shows redirect Uris in that file. I tried both with no success i.e. "redirect_uris":[ "urn:ietf:wg:oauth:2.0:oob", "http://localhost" ] – Karan Jul 05 '20 at 19:30
  • I added an image of what I am seeing on Google Developer Console for your reference. Please have a look. Thanks in advance. – Karan Jul 05 '20 at 19:35
0

It appears that net.openid:appauth:0.7.1 is buggy. I stumbled upon this question then I changed my version to 0.2.0 and it worked.

Karan
  • 752
  • 2
  • 13
  • 34
  • the entire library has turned out to be a nightmare to work with, docs are somewhat difficult to make sense of as well as a lack of examples. I had to work around a few things – Chief Jul 19 '20 at 22:39
  • Hello @Chief, if you have your work around somewhere on web then please share. – Karan Jul 19 '20 at 23:05
0

If I understand you correctly, you have successfully configured AppAuth and on launching the authentication mechanism, the user is able to enter their username and password to login into openId or whatever it is. But on doing so you cannot intercept the result of that intent (chrome custom tabs).

If so try this override method

onActivityResult(requestCode: Int, resultCode: Int, data: Intent?)

you also need to startActivityForResult(authIntent, REQUEST_CODE)

Chief
  • 854
  • 12
  • 27
  • Yes, but I want to make it explicit intent instead of implicit. The code is still has problem with receiving token after getting authentication code – Karan Jul 19 '20 at 23:45