androidoauth-2.0openid-connectappauth

AppAuth Android not closing browser redirect response on second try (why it is not idempotent action)


I am using AppAuth library for Android to connect to an OIDC server which is not from the list of well known vendors like Okta, Google, etc.

This vendor does not support custom url schemas. It only supports https redirects.

I configured my app based on the documentation and sample app from AppAuth-Android github repo.

I have added the AppLink activity from the library in my AndroidManifest file:

<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="https"
             android:host="example.com"
             android:path="/redirect.html"/>
   </intent-filter>
</activity>

I did NOT put the following code in my build.gradle file because I am not using custom url schema:

manifestPlaceholders = [
                'appAuthRedirectScheme': 'net.openid.appauthdemo'
        ]

Below is my auth_config.json file, so you can see my configuration. I modified the real values to not leak private data.

{
  "client_id": "MY_CLIENT_ID",
  "redirect_uri": "https://example.com/redirect.html",
  "end_session_uri":"https://example.com/redirect.html",
  "authorization_scope": "openid email profile",
  "discovery_uri": "https://my-idp.com/.well-known/openid-configuration",
  "authorization_endpoint_uri": "",
  "token_endpoint_uri": "",
  "registration_endpoint_uri": "",
  "user_info_endpoint_uri": "",
  "https_required": true
}

My question is: Why browser tab closing is not idempotent? I will explain what I mean by idempotent below.

When I start the application and click Sign In it opens CUSTOM TAB and redirects me to the IDP. I log in on the server successfully and the IDP sends me back (redirects me) to https://example.com/redirect.html?code=XXXXXXX&state=XXXXXX. The app catches the response and exchanges the code for token and everything is good so far.

When I try to sign in again, the browser already has the cookies for the valid session and it redirects me strait forward to https://example.com/redirect.html?code=XXXXXXX&state=XXXXXX. This time the browser is stuck and the application is not catching the callback. In a normal OIDC flow this action is idempotent. The application should catch the response like the first time and extract the code to be exchanged for a new token. I am not sure if this is the problem from the android itself not catching the URL as expected or something is happening in the AppAuth library that is throwing exception and not closing the browser. The redirect URLs from the first and the second redirect are exactly the same (except the code query param value is different).

Thanks in advance


Solution

  • This is a browser specific issue - due to a missing user gesture in the Chrome Custom Tab on the second login attempt - and may be intermittent.

    It is a nuance of using claimed HTTPS schemes, and the same problem exists on iOS. The solution is to use an interstitial web page so that there is a user gesture on every redirect, and so that return to the app is deterministic.

    RESOURCES OF MINE

    You should be able to just clone the below repo and run the sample on your PC, for something to compare against. The blog posts describe the issues in more depth.