I noticed this when I re-ran my app on 2.2 and 2.3.4 devices. Basically I have a WebView which is loaded with twitter4j's client getAuthenticationURL.
If everything is correct and "Sign In" is clicked, webview will load another page asking for user's authorization. From there, "Authorize app" will return the app's custom callback and user tokens.
Clicking that "Sign In" button will no longer send the webview to the authorization page. It will just stay there. When I debugged my WebViewClient and probed onPageStarted, I noticed that a request was sent. But there's just no response from Twitter. Also, in my 4.4 Nexus tablet, there's no authorization page. "Sign in" will both authorize and immediately return the callback.
So far I found three workarounds for it (all these tests were done from clean install):
Click cancel, restart the app, and reload the same url + request token. This time there's no login. It will get webview to directly load the Authorization page.
This is the complete hack of all. Basically I need to enter a wrong password and I will get sent to a Password reconfirm page. If I enter the right password this time, I will see that authorization page. In fact the second snapshot above was obtained this way.
If I paste that url + request token on a browser, it will also skip the authorization page and immediately return my callback. I haven't made a thorough research if this works on startActivity-for-browser scheme, not embedded webview.
EDIT : it works, upon Sign In, browser will fire a warning and then return the callback which my app intercepts in onNewIntent. There is no authorization page. Also callback url needs to have callback host like bla://callback
I am pretty sure I was able to navigate the login pages including authorization with my older devices not long ago. Is this authorization thing broken or obsolete ?
In the absence of better answer then the current solution will have to do: separate login methods. I use Intent to browser for pre-ICS and WebView for the rest.
Related
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
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
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
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
Last week I updated our Android application from using the old legacy OAuth API (https://developer.linkedin.com/docs/oauth2-legacy) to the new V2 version (https://developer.linkedin.com/docs/oauth2).
On the surface this appears to work, and my redirect_url is being directed to correctly, however, if LinkedIn decides to verify a user via a CAPTCHA, the redirect_url is not returned, and the user is taken to a LinkedIn home page.
To reproduce this:
Start OAuth with the call to https://www.linkedin.com/oauth/v2/authorization
Enter in an email, but then a bunch of wrong passwords. Do this until you trigger the CAPTCHA flow.
Complete CAPTCHA. When redirected back to login page, enter in correct password
This results in the following URLs being called from LinkedIns side, when going through the CAPTCHA flow:
https://www.linkedin.com/uas/login?session_redirect=
https://www.linkedin.com/uas/consumer-captcha-v2?challengeId=
https://www.linkedin.com/nhome/?trk= <-- OH OH, this should be a login success, followed by our redirect_url
For note, the auth flow that doesn't go through CAPTCHA looks like this and DOES work.
https://www.linkedin.com/oauth/v2/authorization-postlogin?app_id=
https://www.linkedin.com/uas/login?session_redirect=%2Foauth%2Fv2%2Flogin-success%3Fapp_id
https://www.linkedin.com/oauth/v2/login-success?app_id=
http://www.ourCoolCallback/linkedin?code= <-- YAY
Has anyone seen this issue? Does anyone know how to get around this, as I am completely at a loss. It seems as if the redirection is getting lost on the LinkedIn side of things. Since this used to work for us using Legacy OAuth - I am guessing something is borked LinkedIn side? Any help would be appreciated!
You can enable the JavaScript. It will enable the CAPTCHA in webview without any problem:
Following is the code with screenshots showing successful login with CAPTCHA.
webView.clearCache(true);
webView.clearHistory();
webView.getSettings().setJavaScriptEnabled(true);
webView.getSettings().setJavaScriptCanOpenWindowsAutomatically(true);
Hello I am using Cordova app using Visual Studio 2015 community and simply login in the app using google authentication it's pretty fine login is done by open it in new window but after login it gives me the three pop up messages and than don't do anything.
The messages are (which are coming after login process and gives allow permission):
1) gap_init:2
2) gap:[null,"CoreAndroid","messageChannel","CoreAndroid237153815"]
3) gap:[null,"CoreAndroid","show","CoreAndroid237153816"]
by pressing these messages as "OK" it's just showing me my first page in the same popup window from where I logged in using Google and returned url after login is:
http://localhost:4400/?code=4/chL63O9SMzMFZGOlqcB9TFMVUFxWj0E4GYEuVFDQ3gM#.
My configured url settings in console.developers.google.com are:
Authorized JavaScript origins = http://localhost:4400
Authorized redirect URIs = http://localhost:4400
and when I am calling the api in that in redirect_uri I pass localhost://4400
I am supposed to go on the second page after login and give allow permission i.e. index2.html but no such process takes place after window gets popped up.
In mobile it open's the browser but don't come back to application for further process staying there after allow process done and finding the coming url i.e.
http://localhost:4400/?code=4/chL63O9SMzMFZGOlqcB9TFMVUFxWj0E4GYEuVFDQ3gM#.
Where am I doing wrong please suggest me anyone as soon as possible. Thank you
IF you have placed cordova.php in root try reload after renaming it
Following the Instagram documentation I'm able to authenticate a user and retrieve an access_token easily
But now I want to change of Instagram account which is impossible since the browser automatically call my callback URL because I'm already signed in with an account (there is no login / authorization form again)
To explain what happen here is the authenticate / authorization flow :
Open a browser asking user to log and authorize
User fill up form and submit (this step is skipped when user is already signed in !)
Browser redirect to callback URL
You see step 2 is skipped so we can't login with another user
Does the Instagram have a parameter to force relogin ?
Justin Powell answer is working for log out but I need to be also able to log in just after
and it's quite anoying for Android
But it points me in the right direction : Instagram (like other website) maintains our login with session variable (so with cookies)
So to avoid to be always loged in, we just have to find and remove the correct cookie, here is how to do it with Android :
String cookieString = "sessionid=''";
CookieManager.getInstance().setCookie("instagram.com", cookieString);
With this I set the Instagram sessionid cookie to en empty string so Instagram doesn't recognize me anymore
You could call the Instagram logout url (https://instagram.com/accounts/logout/) in the background before asking for access again. See this question and answers.
I believe the only other option is to leave it up to the user to logout of their Instagram account before loading your access url.
solved the same issue by deleting Access-Token from the app and loading url https://instagram.com/accounts/logout in webview without attaching it to any rootview.
I'm trying to integrate Twitter sharing functionality into my Android PhoneGap application, and rather than re-implement the controls to shorten URLs and track tweet length, I thought I'd use their premade web intents at https://twitter.com/intent/...
So I'm trying to launch a URL like https://twitter.com/intent/tweet?text=Hello in a ChildBrowser window, so that I can let Twitter's interface take over. The user could sign in with their credentials, and once they're signed in, the text from the URL params would appear in the Tweet box.
It won't work. When I use http://twitter.com/intent/... instead of https://twitter.com/intent/... , ChildBrowser displays the sign-in screen, but as soon as the user submits their credentials, the screen goes white. I suspect this is because Twitter switches over to HTTPS.
I confirmed that this was the case by trying a simple window.open instead of window.plugins.childBrowser.showWebPage. I have no problems with HTTP / HTTPS when using the native browser on Android. However, the native browser prompts me to accept an unverified security certificate. I suspect this is the problem with ChildBrowser - it doesn't know how to handle that prompt.
Using the native browser popover simply isn't an option: the user needs to be able to exit the process after hitting 'Tweet' or 'Follow', etc., but the 'back' button on the Android device simply moves the history one step backward to the POST action for their intent. Then, it re-launches the app from scratch, instead of returning you to the original state.
How can I configure ChildBrowser / my Android Phonegap application to override SSL issues on Twitter, so that I can run web intents in Childbrowser?
The relevant code is:
base="https://twitter.com/intent/tweet?text=";
URL=base+encodeURIComponent("it works!");
// works, but asks to accept a certificate
window.open(URL);
// blank white page
window.plugins.childBrowser.showWebPage(URL, { showLocationBar: true });
My cordova.xml file has whitelists configured as such:
<access origin="http://127.0.0.1*"/> <!-- allow local pages -->
...which I don't suspect should be a problem. However, a basic test of swapping origin=".*" yielded no change in behaviour.
I've also examined the HTTP and HTTPS headers for the Twitter intent landing pages. There doesn't appear to be anything out of line - they're identical, except for the Strict-Transport-Security header for HTTPS, which works elsewhere (e.g. Github).
Please help!
The ChildBrowser is not bound by the whitelist. The whitelist is only used to keep the main PhoneGap app from running code outside of trusted domains.
I'm confident if you go get the latest ChildBrowser code from Android you won't have run into this problem anymore. We've made some changes recently that make it more robust.
Also, Libby has a good tutorial integrating Twitter and the ChildBrowser.
http://www.mobiledevelopersolutions.com/home/start/twominutetutorials/tmt5p1