403 Error - Thats an error. Error: disallowed_useragent
IosIphoneGoogle Calendar-ApiGoogle OauthIos 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.
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"}
/>