403 Error - Thats an error. Error: disallowed_useragent

IosIphoneGoogle Calendar-ApiGoogle Oauth

Ios Problem Overview


I am trying to authorise a user for Google calendar API inside an IOS app. I am using the OAuth2 feature of Google to authenticate users. Authorisation page opens with a 403 error with the description:

> This user-agent is not permitted to make OAuth authorisation request to Google as it is classified as an embedded user-agent (also known as a web-view). Per our policy, only browsers are permitted to make authorisation requests to Google. We offer several libraries and samples for native apps to perform authorisation request in browser.

I followed the same procedure which is mentioned in this link: https://developers.google.com/google-apps/calendar/quickstart/ios

Rather than seeing my code, it's better to look at this link: https://developers.google.com/google-apps/calendar/quickstart/ios because I copy-pasted the same thing in my application.

below are my clientId and keyChainItemName:

static NSString *const kKeychainItemName = @"Google Calendar API";
static NSString *const kClientID = @"954370342601-sgl8k0jrbqdeagea9v6vfu3tspte96ci.apps.googleusercontent.com";

Ios Solutions


Solution 1 - Ios

In my case I was using native web view to login with Google, I find out the way that you should provide user agent to webview it was worked for me. Try below code I am sure it will worked.

Add the code in application didFinishLaunchingWithOptions

Objective C

 NSDictionary *dictionary = [NSDictionary dictionaryWithObjectsAndKeys:@"Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2228.0 Safari/537.36", @"UserAgent", nil];
 [[NSUserDefaults standardUserDefaults] registerDefaults:dictionary];

Swift 3.0

let dictionary = NSDictionary(object: "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2228.0 Safari/537.36", forKey: "UserAgent" as NSCopying)
UserDefaults.standard.register(defaults: dictionary)

Solution 2 - Ios

<preference name="OverrideUserAgent" value="Mozilla/5.0 Google" />

I also face this issue on my cordova project. You can try this: Just add this to your config.xml, worked for me.

Solution 3 - Ios

The short answer is that Google has updated its security restrictions for OAuth flow. They are not going to allow native web-views to initiate OAuth flows, but rather are encouraging people to use the OS browsers to do so. In your case, you'll probably have to wait for the Google calendar SDK to update their code to obey the newly recommended flow. More information is available in the Google blog

EDIT : I have tried to create a cross platform plugin which wraps around the native Google sign-in SDKs for using in a Xamarin forms app. More information can be found here

Solution 4 - Ios

Got same issue. Resolved by setting following property to the webview object:

webview.getSettings().setUserAgentString("Chrome/56.0.0.0 Mobile");

Hope this will help.

Solution 5 - Ios

As mentioned in previous answers, SFSafariViewController is a way to go, but for those who still uses WKWebView for OAuth authorization there is a simple workaround.

Just change customUserAgent to either one from list or set it to some arbitrary value. After that disallowed_useragent error will disappear:

WKWebViewConfiguration *configuration = [[WKWebViewConfiguration alloc] init];
WKWebView *webView = [[WKWebView alloc] initWithFrame:CGRectZero configuration:configuration];
// Check for selector availability, as it is available only on iOS 9+
if ([webView respondsToSelector:@selector(setCustomUserAgent:)]) {
    webView.customUserAgent = @"MyCustomUserAgent";
}

For changing User-Agent in UIWebView you can check this answer.

But be careful, as some backend code can depend on User-Agent header value.

Solution 6 - Ios

By default, if you don't have any google app, the google SDK opens the login inside a UIWebView when we initiate the login by using the following method.

        [[GIDSignIn sharedInstance] signIn];

I just added one line before this, which is as follows.

        [[GIDSignIn sharedInstance] setAllowsSignInWithWebView:NO];

Now the google doesn't authorise using the UIWebView popup. Instead, it opens in the Safari browser. And now everything just works as the way it was.

Solution 7 - Ios

Google decided to not longer allow embedded browsers to handle the oAuth authentication. The best way is to use SFSafariViewController on iOS. Here is how it can be solved using the CloudRail SDK:

In Objective-C:

@implementation AppDelegate

  // This method will receive the redirect URI after the authentication process was
  // successfull
- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url {
  
  // Here we pass the response to the SDK which will automatically
  // complete the authentication process.
  [[NSNotificationCenter defaultCenter] postNotificationName:@"kCloseSafariViewControllerNotification" object:url];
  
  return YES;
}

@end

and Swift:

// This method will receive the redirect URI after the authentication process was
// successfull
func application(application: UIApplication, openURL url: NSURL, sourceApplication: String?, annotation: AnyObject) -> Bool {

    if (sourceApplication == "com.apple.SafariViewService") {
        // Here we pass the response to the SDK which will automatically
        // complete the authentication process.
        NSNotificationCenter.defaultCenter().postNotificationName("kCloseSafariViewControllerNotification", object: url)
        return true
    }
    return true
}

The complete blog post covering this issue can be found here: Solving ‘disallowed_useragent’ for Google services

Solution 8 - Ios

Take a look at this issue. Use GTMAppAuth instead.

Solution 9 - Ios

There is a workaround for this issue after the recent change in Google OAuth policies.

After integrating the Google Sign and enabling Google Calendar API, I was able to work with Google Calendar API to fetch and add Calendar Events. We just have to set the authorizer for GTLServiceCalendar which is obtained after Google sign-in.

service.authorizer = user.authentication.fetcherAuthorizer()

Here is the code snippets of Google GIDSignIn, followed by fetching calendar events.

import GoogleAPIClient
import GTMOAuth2
import UIKit
import GoogleSignIn
        
class ViewController: UIViewController, GIDSignInUIDelegate, GIDSignInDelegate {
            
  private let kApiKey = "AIzaXXXXXXXXXXXXXXXXXXXXXXX"
            
  // If modifying these scopes, delete your previously saved credentials by
  // resetting the iOS simulator or uninstall the app.
  private let scopes = [kGTLAuthScopeCalendar]
  private let service = GTLServiceCalendar()
        
  override func viewDidLoad() {
      super.viewDidLoad()
                
      service.apiKey = kApiKey
               
      GIDSignIn.sharedInstance().uiDelegate = self
      GIDSignIn.sharedInstance().scopes = scopes
      GIDSignIn.sharedInstance().signIn()
      GIDSignIn.sharedInstance().delegate = self
  }
    
    
  func sign(_ signIn: GIDSignIn!, didSignInFor user: GIDGoogleUser!, withError error: Error!) {
     
      if user != nil {
           print("\(user)")
           service.authorizer = user.authentication.fetcherAuthorizer()
           fetchEvents()
      }
  }
    
 // Construct a query and get a list of upcoming events from the user calendar
   func fetchEvents() {
            
        let query = GTLQueryCalendar.queryForEventsList(withCalendarId: "primary")
        query?.maxResults = 20
        query?.singleEvents = true
        query?.orderBy = kGTLCalendarOrderByStartTime
        
        service.executeQuery(query!, delegate: self, didFinish: #selector(ViewController.displayResultWithTicket(ticket:finishedWithObject:error:)))
   }
    
// Display the start dates and event summaries in the UITextView
    func displayResultWithTicket(
         ticket: GTLServiceTicket,
        finishedWithObject response : GTLCalendarEvents,
        error : NSError?) {
        
        if let error = error {
            showAlert(title: "Error", message: error.localizedDescription)
            return
        }
        
        var eventString = ""
        
        if let events = response.items(), !events.isEmpty {
            for event in events as! [GTLCalendarEvent] {
                print(event)
             }
        } else
                print("No upcoming events found.")
        }
    }

    }

This is how my credentials section appear in Google Dev Console.

enter image description here

Solution 10 - Ios

After the google sign-in finishes the login, use the currentUser to get the fetcherAuthorizer, this can be used like an authorizer for the Google Drive Service.

After that you can use the Google Drive Service normally:

GIDGoogleUser *googleUser = [GIDSignIn sharedInstance].currentUser;

if(googleUser != nil){
    self.service.authorizer = googleUser.authentication.fetcherAuthorizer;
    [self listFiles];
    
}

Solution 11 - Ios

This is working for me

mWebView.getSettings().setUserAgentString("Mozilla/5.0 (Linux; Android 4.1.1; Galaxy Nexus Build/JRO03C) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.166 Mobile Safari/535.19");

Solution 12 - Ios

I solved the issue it took 1 year :-) just kidding. just add the below line in preference in config.xml

<preference name="OverrideUserAgent" value="Mozilla/5.0 Google" />

Please note i solved this google login issue with Inapp browser.

Thanks

Solution 13 - Ios

I was getting error: "403 Error - Thats an error. Error: disallowed_useragent" on Google Signin InAppBrowser and for my situation the fix was adding userAgent property like this in Webview:

 <WebView
 // other props here
  userAgent={"Chrome/56.0.0.0 Mobile"}
 />

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionSubbuView Question on Stackoverflow
Solution 1 - IosDipen ChudasamaView Answer on Stackoverflow
Solution 2 - IosHardeep SinghView Answer on Stackoverflow
Solution 3 - IosRhishikeshjView Answer on Stackoverflow
Solution 4 - IosKundan Singh ThakurView Answer on Stackoverflow
Solution 5 - IosMaxim PavlovView Answer on Stackoverflow
Solution 6 - IosRamaraj TView Answer on Stackoverflow
Solution 7 - IosTmmView Answer on Stackoverflow
Solution 8 - IosSallyView Answer on Stackoverflow
Solution 9 - IosJen JoseView Answer on Stackoverflow
Solution 10 - IosMauker OlimpioView Answer on Stackoverflow
Solution 11 - Iosdev_mg99View Answer on Stackoverflow
Solution 12 - IosProsenjeet PaulView Answer on Stackoverflow
Solution 13 - IosAkshita AgarwalView Answer on Stackoverflow