8

Our production Android application uses Chrome Custom Tabs for OAuth login

It was working fine yesterday when Chrome version was 61.0.3163.98

Following an overnight update of Chrome to 72.0.3626.76 the Login process gets stuck in the embedded browser and the user is presented with a blank white screen.

If we uninstall the Chrome update the login starts to work again

What has changed with Chrome and/or Chrome Custom Tabs that breaks our login process?

If I switch my default browser to Firefox my apps login works fine.

In fact if I change default browser to anything other than chrome it works fine, even Opera works, although Opera doesnt show an embedded browser.

It also works when I uninstall the Chrome update and revert back to chrome version 61.0.3163.98

Further Details:-

Step 1). Load URL with prompt=none and my custom scheme Redirect URL.
Step 2). My App receives a NEW INTENT containing the auth code.
Step 3). I attempt to access my back end APIs with this code, which fails with 400
Step 4). Load URL prompt=login and my users are presented with a sign in screen where they enter their credentials and click on the Sign In button.
Step 5). NOTHING HAPPENS, the user is presented with a blank screen, my app does not receive a NEW INTENT.

Heres the code I employ to open the Login URL via a Chrome Custom Tab

private void openCustomTab() {
    codeVerifier = generateRandomCodeVerifier();
    checkCodeVerifier(codeVerifier);
    codeChallenge = deriveCodeVerifierChallenge(codeVerifier);

    CustomTabsIntent.Builder builder = new CustomTabsIntent.Builder();
    CustomTabsIntent customTabsIntent = builder.build();
    customTabsIntent.launchUrl(this, getURL(PROMPT_NONE));
}

The above code loads the URL with prompt=none and it also specifies my custom scheme redirect url.

My Android app receives a New Intent in onNewIntent that contains an authCode, I attempt to retrieve an access token with this authocode which fails with 400.

I then use custom Tabs to load a second URL with prompt=login as follows:-

            final CustomTabsIntent.Builder builder = new CustomTabsIntent.Builder();
            builder.setToolbarColor(Color.BLUE);

            final CustomTabsIntent customTabsIntent = builder.build();
            customTabsIntent.launchUrl(SignInActivity.this, getURL(PROMPT_LOGIN, authCode));

By loading this URL with prompt=login the user can enter their credentials and click on the Sign In button.

Its at this point the Chrome Custom Tab gets stuck.

here are the network calls I capture using Stetho, the last call made is authorization.ping that shows as cancelled

enter image description here

I have found a resolution for this issue as follows:-

I added an additional prompt of "consent" to the existing prompts of "none" then "login".

Now the user see a consent screen titled

oauth.approval.page.template.title

where the user sees a list of choosable options including

ACCESS TO YOUR DATA
SIGN IN WITH OPENID CONNECT
OPENID CONNECT PROFILE SCOPE
OPENID CONNECT EMAIL SCOPE

at the bottom of this screen theres two options

oauth.approval.page.template.allow
oauth.approval.page.template.dontAllow

when the user selects

oauth.approval.page.template.allow

they can now proceed into the android app.

The only issue is the user sees this approval screen whenever they log in

Hector
  • 4,016
  • 21
  • 112
  • 211
  • Why the downvote? Google has released a version of chrome on android that breaks chrome custom tabs and I ask why and it gets downvoted, interesting. Once again the stock overflow community provides assistance with a downvote. – Hector Jan 30 '19 at 12:48
  • 1
    You didn't update Chrome for almost a year and a half, and you want someone to explain what's broken without including any code in your question? – Josh Lee Jan 30 '19 at 17:50
  • What code would I put in my question? I use chrome custom tab to load my oauth URL, my users enter their credentials and click on SIGN IN and the embedded browser stops responding, what options are available to me to show code or fix this? Web uses of the same sign in URL are still working, as is our iOS application – Hector Jan 30 '19 at 17:53
  • 1
    @Hector, do you check for KEY_INTENT from the AccountManagerCallback?? – 0xA Jan 31 '19 at 12:02
  • @KARAMJABER, we are not using the AccountManager at all, just chrome custom tabs to load our login URLs – Hector Jan 31 '19 at 12:06
  • 1
    Does Chrome log any console messages? – Josh Lee Jan 31 '19 at 15:50
  • @JoshLee, no, All I see in logcat is the prompt=login URL being loaded and then the logcat is blank, I see no more logs produced. However as mentioned in my last update when I add consent to the login prompt it all works as required and the user can sign in, although the downside is they have to grant approval in an extra screen. – Hector Jan 31 '19 at 15:53

2 Answers2

2

I have recently answered this same question, I believe the update with chrome adds some security layer. I also had same issue before with different browser (stock browser that comes with different non-officials Custom ROMS) and I think we're not safe in case other browsers implement the same behavior.

To avoid all these problems, I would suggest that you implement a staging page that will serve to handle all your OAuth2 redirects.

This solution also has the advantage of avoiding for the user to "Allow" login every time.

You can find a detailed answer here: How to implement OAuth single Sign In/Sign Out with Chrome Custom Tabs

113408
  • 3,364
  • 6
  • 27
  • 54
1

The only change that has been made on that update is the break/removal of HPKP ( HTTP-Based Public Key Pinning)

HTTP-Based Public Key Pinning (HPKP) was intended to allow websites to send an HTTP header that pins one or more of the public keys present in the site's certificate chain. Unfortunately, it has very low adoption, and although it provides security against certificate misissuance, it also creates risks of denial of service and hostile pinning. For these reasons, this feature is being removed.

You are getting the 400 Bad request because of that, Thats just my guess.

If all goes well, the Bundle contains a valid token in the KEY_AUTHTOKEN key using token = bundle.getString(AccountManager.KEY_AUTHTOKEN); from the AccountMangerCallback and you're off to the races

Authentication with OAuth2 services has been changed on developer.android.com, it is required to request an auth token again, some of the authenticators are requiring a direct interaction with the user before giving a valid token.

try and run AccountManager or whatever API you're implementing to get KEY_INTENT before you get clientID, clientSecret, granting type, or your redirectURI

check the following link and adopt any new implementations: https://developer.android.com/training/id-auth/authenticate

0xA
  • 1,519
  • 1
  • 9
  • 23
  • 1
    If you need any help please provide a code snippet of your API calls so i can debug with the new set of rules. – 0xA Jan 31 '19 at 12:31
  • I do not make any API calls, I just load URLs in Chrome custom tabs. I've just found a "Fix" for this issue as my updated question now shows. – Hector Jan 31 '19 at 14:32