javaandroidoauth-2.0appauth

OAuth2 Redirect URI not valid


I'm trying to authenticate to OpenStreetMap via OAuth2 using AppAuth. Via Custom Tab I can retrieve the authorization code but the redirect URI does not open my app but gives an Address Not Found error in the Custom Tab. As you can see as I was experimenting around to solve this issue I used app.example.com as host name, although the package name is com.example.app, but even if I do use the package name as host name in the redirect URI (and change this in the manifest, gradle, osm etc.), it still does not work but results in an Invalid Redirect URI error. So I would assume something with the redirect URI isn't quite right, but I cannot figure out what it is.

Also I cannot use a custom scheme, as OSM only accepts https redirect URIs.

MainActivity.java:

private static final String CLIENT_ID = ...;
private static final String REDIRECT_URI = "https://app.example.com/oauth2redirect";
...
AuthorizationRequest.Builder builder = new AuthorizationRequest.Builder(
            authorizationServiceConfiguration,
            CLIENT_ID,
            ResponseTypeValues.CODE,
            Uri.parse(REDIRECT_URI));
builder.setScopes("write_api", "read_prefs");

AuthorizationRequest request = builder.build();
Intent authorizationIntent = authorizationService.getAuthorizationRequestIntent(request);
startActivityForResult(authorizationIntent, REQUEST_CODE);

Manifest.xml:

 <activity
        android:name=".MainActivity"
        android:exported="true">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>

        <intent-filter>
            <action android:name="com.example.app.HANDLE_AUTHORIZATION_RESPONSE" />
            <category android:name="android.intent.category.DEFAULT" />
        </intent-filter>
    </activity>

    <activity android:name="net.openid.appauth.RedirectUriReceiverActivity"
        android:exported="true">
        <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="https"
                android:host="app.example.com"
                android:pathPrefix="/oauth2redirect"/>
        </intent-filter>
 </activity>

build.gradle

android {
...

defaultConfig {
    applicationId "com.example.app"
    ...
    manifestPlaceholders = [
            appAuthRedirectScheme: 'app.example.com'
    ]
}

In OSM I have set the redirect URI to https://app.example.com/oauth2redirect

Weirdly enough it worked once yesterday, but does not anymore since today. I reverted any changes, reset the app, deleted any data and restarted my phone, but couldn't make it work again.

I've tried to show as little code as needed, please let me know if you need further information for solving this problem.

Edit: I just noticed that it works on Pixel 5 API 30 virtual device, but not on my real device (Xiaomi Poco X3 Pro API 30) nor on Nexus 6 API 30 virtual device. I'm quite confused


Solution

  • Using HTTP redirect URIs requires these settings in the build.gradle file, and also has a prerequisite of app link registration via a hosted assetlinks.json file:

    manifestPlaceholders = [
        'appAuthRedirectScheme': 'https'
    ]
    

    There is a known issue where OAuth HTTPS responses don't automatically return to the app from a Chrome Custom Tab, unless there is a User Gesture first, such as a button click.

    If possible, as an initial solution to this you may want to show an OAuth screen to allow the user to choose which of his accounts they want to use, by using prompt=select_account:

    AuthorizationRequest.Builder authRequestBuilder = new AuthorizationRequest.Builder(
                    Objects.requireNonNull(authState.getAuthorizationServiceConfiguration()),
                    clientId,
                    ResponseTypeValues.CODE,
                    Uri.parse(redirectUri))
                    .setScope(authScope)
                    .setPrompt("select_account");
    
    

    If you want something to compare against try running my demo app and see if this gives you some ideas. Note that recently I've seen problems on emulators that use APIs 31 and above, though no problems on my Google Pixel phone, which runs Android 12.