Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does Android Chrome update from 61.0.3163.98 to 72.0.3626.76 break OAuth login in Chrome Custom Tabs?

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

like image 893
Hector Avatar asked Jan 30 '19 11:01

Hector


2 Answers

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

like image 187
113408 Avatar answered Nov 09 '22 03:11

113408


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

like image 29
0xA Avatar answered Nov 09 '22 03:11

0xA