0

My website using Google oAuth to let users sign in. I do NOT have a mobile app for this website. However, when a link to my website is shared on Facebook or Facebook messenger, and a user opens that link, my page is opened inside a webview of the Facebook or Facebook Messenger app.

Unfortunately for us web developers, Google did not consider the web login flow when making this decision in 2016 to deprecate some webview flows. Their "feature" assumes that you can just modify your app code to become compliant. https://developers.googleblog.com/2016/08/modernizing-oauth-interactions-in-native-apps.html

The result is that some users on some OS and Facebook app versions get an error:

'403 Google ‘Error: Disallowed_Useragent’ on Android and iOS'

There are numerous old posts on stack overflow related to this problem, and none of them have a solution for website owners. All solutions I have found are focused on app developers. In my case, Facebook Messenger is the problem app.

Is there any way to force my website to be loaded outside of the webview, or tell detect the webview so that I can inform the user of the potential issue along with instructions to avoid it by opening the app in Chrome or Safari directly.

It seems there should be some HTML tag for the head to tell browsers the page cannot be shown in a webview. How could this not be a feature after 6 years? There must be a major site somewhere that gets shared on social media and has Google Login as an option.

Michael Lang
  • 1,100
  • 11
  • 17
  • I think you can detect it using the `userAgent` (though, that can be spoofed I guess) - there's a (very) old question https://stackoverflow.com/questions/6783185/detect-inside-android-browser-or-webview that may still be relevant – Jaromanda X Oct 04 '22 at 02:20
  • @JaromandaX Thanks, unfortunately, all of those answers say how to edit your Android app to set a userAgent. Its my last resort to check userAgent via javascript, since that means I'll have to keep a current list of agents google won't accept via oauth or those that are webview user agents and inform the user what to do (or disable Google login for those cases) – Michael Lang Oct 04 '22 at 18:49
  • Hmm, I must've read them wrong ... I swear one of them said that the userAgent inside web view would contain `; wv` so your website would be able to at least detect that it is running inside a web view – Jaromanda X Oct 04 '22 at 22:24

1 Answers1

0

I could not find a solution to the Original question. There is no way to break a website outside of the mobile app browser. But I did come up with a solution to warn the user of the potential issue so that they open it in their native mobile browser.

A very basic Angular detection service

import { Injectable } from '@angular/core';

@Injectable({
  providedIn: 'root'
})
export class BrowserDetectService {
  // https://raw.githubusercontent.com/3rd-Eden/useragent/master/lib/regexps.js
  fbWvRegex = [
    new RegExp("\\[(FBAN/MessengerForiOS|FB_IAB/MESSENGER);FBAV/(\\d+)(?:\\.(\\d+)(?:\\.(\\d+)|)|)"),
    new RegExp("\\[FB.*;(FBAV)/(\\d+)(?:\\.(\\d+)|)(?:\\.(\\d+)|)"),
    new RegExp("\\[FB.*;"),
  ];
  snapWebRegex = [
    new RegExp("(Snapchat)\\/(\\d+)\\.(\\d+)\\.(\\d+).(\\d+)"),
    new RegExp("(Snapchat)(\\d+)\\.(\\d+)\\.(\\d+).(\\d+)"),
  ];
  AndroidRegex = [
    new RegExp("(Android)"),
  ];
  iPhoneRegex = [
    new RegExp("^(.*)-iPad\\/(\\d+)(?:\\.(\\d+)|)(?:\\.(\\d+)|)(?:\\.(\\d+)|) CFNetwork"),
    new RegExp("^(.*)-iPhone/(\\d+)(?:\\.(\\d+)|)(?:\\.(\\d+)|)(?:\\.(\\d+)|) CFNetwork"),
    new RegExp("(iPod|iPhone|iPad).+GSA/(\\d+)\\.(\\d+)\\.(\\d+) Mobile"),
    new RegExp("(iPod|iPhone|iPad).+Version/(\\d+)\\.(\\d+)(?:\\.(\\d+)|).*[ +]Safari"),
    new RegExp("(iPod|iPod touch|iPhone|iPad);.*CPU.*OS[ +](\\d+)_(\\d+)(?:_(\\d+)|).* AppleNews\\/\\d+\\.\\d+\\.\\d+?"),
    new RegExp("(iPod|iPhone|iPad).+Version/(\\d+)\\.(\\d+)(?:\\.(\\d+)|)"),
    new RegExp("(iPod|iPod touch|iPhone|iPad);.*CPU.*OS[ +](\\d+)_(\\d+)(?:_(\\d+)|).*Mobile.*[ +]Safari"),
    new RegExp("(iPod|iPod touch|iPhone|iPad);.*CPU.*OS[ +](\\d+)_(\\d+)(?:_(\\d+)|).*Mobile"),
    new RegExp("(iPod|iPhone|iPad).* Safari"),
    new RegExp("(iPod|iPhone|iPad)"),
    new RegExp("(Outlook-iOS)/\\d+\\.\\d+\\.prod\\.iphone \\((\\d+)\\.(\\d+)\\.(\\d+)\\)"),
  ];

  constructor(
  ) { }

  detectWebView() : string | undefined {
    const userAgent = navigator.userAgent;
    if (this.matchesAny(userAgent, this.fbWvRegex)) {
      return 'Facebook';
    }
    if (this.matchesAny(userAgent, this.snapWebRegex)) {
      return 'Snapchat';
    }
    return undefined;
  }
  detectMobileOS(): string | undefined {
    const userAgent = navigator.userAgent;
    if (this.matchesAny(userAgent, this.AndroidRegex)) {
      return 'Android';
    }
    if (this.matchesAny(userAgent, this.iPhoneRegex)) {
      return 'iPhone';
    }
    return undefined;
  }
  matchesAny(userAgent: string, parsers: RegExp[]): boolean {
    let res: any;
    for (let i = 0; i < parsers.length; i++) {
      if (parsers[i].exec(userAgent)) {
        return true;
      }
    }
    return false;
  }

  fixInstructionsImgUrl(): string | undefined {
    const app = this.detectWebView();
    const os = this.detectMobileOS();
    if (!app) { return undefined; }
    if (os === 'Android') {
      if (app === 'Facebook') {
        return '/HowTo-OpenInChrome-Android-Facebook.png';
      } else { // Snapchat is last remaining OS with image help
        return '/HowTo-OpenInChrome-Android-Snapchat.png';
      }
    } else { // iOS
      // we only have one image for now on iOS
      // if (app === 'Snapchat') {
        return '/HowTo-OpenInChrome-iOS-Snapchat.png';
      // }
    }
    // return '/HowTo-OpenInChrome.png';
    // Add whichever apps and OS images you have here
  }

}

Then I used this in the usual way from a component to conditionally show/hide content. The result is:

Login page with warning

Help instructions shown on request button click

Michael Lang
  • 1,100
  • 11
  • 17