How to authenticate in Google Fusion Tables with Oauth2 in Dart? - oauth-2.0

I'm trying to get data from a fusion table. I write, as it is written in the example
import "package:google_fusiontables_v1_api/fusiontables_v1_api_browser.dart";
import "package:google_oauth2_client/google_oauth2_browser.dart";
class CFusionTable
{
static const _tableName = '*mytablename*';
static const _clientID = "*myclientid*";
GoogleOAuth2 _gauth;
CFusionTable()
{
_gauth = new GoogleOAuth2(_clientID, [Fusiontables.FUSIONTABLES_SCOPE]);
var fusiontables = new Fusiontables(_gauth);
fusiontables.query.sql('select ID, Name, Latitude, Longitude, Country, Territory, City, Photo, ROWID from '+_tableName,
hdrs: false)
.then(_loadData);
}
void _loadData(data)
{
print (data.toString());
}
}
But the authentication does not work:
Failed to load resource: the server responded with a status of 403
(Forbidden)
As">https://www.googleapis.com/fusiontables/v1/query?hdrs=false&sql=select%20ID%2C%20Name%2C%20Latitude%2C%20Longitude%2C%20Country%2C%20Territory%2C%20City%2C%20Photo%2C%20ROWID%20from%201bSQ16GyMgRuleMBdn1aF4Xfu0E3HRv_As
Uncaught Error: APIRequestException: 403 Daily Limit for
Unauthenticated Use Exceeded. Continued use requires signup.
Exception: APIRequestException: 403 Daily Limit for Unauthenticated
Use Exceeded. Continued use requires signup. undefined
(undefined:0:0)
Tell me please, what am I doing wrong?

You need to authenticate first before you can execute methods on the fusion tables. In the example code below, call the login method to invoke the authentication and the fusion tables when authentication was successful.
import "package:google_fusiontables_v1_api/fusiontables_v1_api_browser.dart";
import "package:google_oauth2_client/google_oauth2_browser.dart";
class CFusionTable
{
static const _tableName = '*mytablename*';
static const _clientID = "*myclientid*";
GoogleOAuth2 _gauth;
CFusionTable() {
_gauth = new GoogleOAuth2(_clientID, [Fusiontables.FUSIONTABLES_SCOPE]);
}
void login() {
_gauth.login().then(_gauth_tokenLoadedHandler);
}
void _gauth_tokenLoadedHandler(Token token) {
var fusiontables = new Fusiontables(_gauth);
fusiontables.query.sql('select ID, Name, Latitude, Longitude, Country, Territory, City, Photo, ROWID from '+_tableName,hdrs: false)
.then(_loadData);
}
void _loadData(data) {
print (data.toString());
}
}

Another thing to check when you see 403 is your Client ID. Many of the Google APIs have rate limits, and for unregistered apps the rate limit is essentially zero. So when you see 403 it’s often the case that (a) you didn’t register the app or (b) you registered the app but put the wrong Client ID value in your code or (c) you did all those but registered your app for the wrong scopes... you see the pattern.

Related

.Net Core Graph API Token Issue - "Access token has expired or is not yet valid"

I am developing a .Net 6 application, hosted in an Azure App Service and using Azure AD Authentication.
When viewing a Request page, I would like to check if the user belongs to an Azure Ad Group. This works sometimes, but users will periodically get an error when trying to view the page: "Access token has expired or is not yet valid."
I assume the token is being expired as if the user clears their cookies, AAD will re-authenticate them creating a new token and all is fine again, but but I haven't been able to find anything around refreshing tokens and am not sure where to go from here.
Has anyone experienced this behaviour and found a solution for it?
Here are some relevant sections of the code
Startup.cs File:
string[] initialScopes = Configuration.GetValue<string>("GraphAPI:Scopes")?.Split(' ');
services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApp(Configuration.GetSection("AzureAd"))
.EnableTokenAcquisitionToCallDownstreamApi(options =>
{
Configuration.Bind("AzureAd", options);
}, initialScopes)
.AddInMemoryTokenCaches()
.AddMicrosoftGraph(options =>
{
options.Scopes = String.Join(' ', initialScopes);
});
AADGroupFunctions.cs
AADGroupFunctions.cs
private readonly GraphServiceClient _graphServiceClient;
public AADGroupFunctions(GraphServiceClient graphServiceClient)
{
_graphServiceClient = graphServiceClient;
}
public async Task<List<IADLookupModel>> FindUsersInGroup(string groupId)
{
var listOfUsers = new List<IADLookupModel>();
var filterString = $"startswith(mail, '{groupId}')";
var groups = await _graphServiceClient.Groups
.Request()
.Header("ConsistencyLevel", "eventual")
.Filter(filterString)
.Expand("members")
.Top(1)
.GetAsync();
if (groups.Any())
{
if (groups.First().Members.Any())
{
foreach (Microsoft.Graph.User user in groups.First().Members)
{
try
{
var mail = "";
if (user.Mail != null)
{
mail = user.Mail.ToLower();
listOfUsers.Add(new UserModel()
{
DisplayName = user.DisplayName,
UPN = user.UserPrincipalName.ToLower(),
Email = mail,
Description = user.JobTitle ?? ""
});
}
}
catch (Exception)
{
}
}
}
}
return listOfUsers;
}
Error Message when trying to call the FindUsersInGroup() function:
An unhandled exception occurred while processing the request.
ServiceException: Code: InvalidAuthenticationToken Message: Access token has expired or is not yet valid. Inner error: AdditionalData: date: 2022-02-21T17:37:46 request-id: [removed] client-request-id: [removed] ClientRequestld: [removed] Microsoft.Graph.HttpProvider.SendAsync(HttpRequestMessage request, HttpCompletionOption completionOption, CancellationToken cancellationToken)
Routing
The access token have a short lifetime, sometimes like an hour or even shorter. So you need to use a refresh token to ask AzureAd for a new access token when the current one is about to expire.
see this link https://learn.microsoft.com/en-us/azure/active-directory/develop/refresh-tokens

accessing Twitter API from Google Apps Script

I'm trying to read in a Google sheet my Twitter timeline.
I've copied the following code reported in the GAS documentation about twitter authentication (omitting step 2 since I'm not using the code inside a UI):
function getTwitterService() {
// Create a new service with the given name. The name will be used when
// persisting the authorized token, so ensure it is unique within the
// scope of the property store.
return OAuth1.createService('twitter')
// Set the endpoint URLs.
.setAccessTokenUrl('https://api.twitter.com/oauth/access_token')
.setRequestTokenUrl('https://api.twitter.com/oauth/request_token')
.setAuthorizationUrl('https://api.twitter.com/oauth/authorize')
// Set the consumer key and secret.
.setConsumerKey('mykey')
.setConsumerSecret('mysecret')
// Set the name of the callback function in the script referenced
// above that should be invoked to complete the OAuth flow.
.setCallbackFunction('authCallback')
// Set the property store where authorized tokens should be persisted.
.setPropertyStore(PropertiesService.getUserProperties());
}
function authCallback(request) {
var twitterService = getTwitterService();
var isAuthorized = twitterService.handleCallback(request);
if (isAuthorized) {
return Logger.log('Success! You can close this tab.');
} else {
return Logger.log('Denied. You can close this tab');
}
}
function makeRequest() {
var twitterService = getTwitterService();
var response = twitterService.fetch('https://api.twitter.com/1.1/statuses/user_timeline.json');
Logger.log(response);
}
but I obtain the message error: Service not authorized. (row 292, file "Service", project "OAuth1").
What's wrong?
I needed to add the following line the first time I execute makeRequest:
var authorizationUrl = twitterService.authorize();
Logger.log(authorizationUrl);
Then, open the url read from the log and authorize the app.
After that, all works fine.

Block IP address from Google adwords with their API

Does anyone know how to block certain IP addresses from our Google adwords account using the Google API?
In this article you can see how to do it manually, but I cannot find a way to do it programmatically.
I know it's late. But I needed it as well.
I found the IpBlock type on Google AdWords here.
Here is some sample code i found, and improved slightly
require_once this code, then make this call for each campaign u want to ban the IP for
YourNameSpace\BlockedIP::add($campaignId, $ip);
voila
<?php
/*
...
*/
namespace YourNameSpace;
use Google\AdsApi\AdWords\AdWordsServices;
use Google\AdsApi\AdWords\AdWordsSession;
use Google\AdsApi\AdWords\AdWordsSessionBuilder;
use Google\AdsApi\Common\OAuth2TokenBuilder;
use Google\AdsApi\AdWords\v201802\cm\CampaignCriterionService;
use Google\AdsApi\AdWords\v201802\cm\IpBlock;
use Google\AdsApi\AdWords\v201802\cm\NegativeCampaignCriterion;
use Google\AdsApi\AdWords\v201802\cm\CampaignCriterionOperation;
use Google\AdsApi\AdWords\v201802\cm\Operator;
class BlockedIP {
public static function runExample(AdWordsServices $adWordsServices,
AdWordsSession $session,
$campaignId,
$ip) {
$campaignCriterionService =
$adWordsServices->get($session, CampaignCriterionService::class);
$campaignCriteria = [];
// Add a negative campaign criterion.
$ipBlock = new IpBlock();
$ipBlock->setIpAddress($ip);
$negativeCriterion = new NegativeCampaignCriterion();
$negativeCriterion->setCampaignId($campaignId);
$negativeCriterion->setCriterion($ipBlock);
$operation = new CampaignCriterionOperation();
$operation->setOperator(Operator::ADD);
$operation->setOperand($negativeCriterion);
$operations[] = $operation;
$result = $campaignCriterionService->mutate($operations);
// Print out some information about added campaign criteria.
foreach ($result->getValue() as $campaignCriterion) {
printf(
"Campaign targeting criterion with ID %d and type '%s' was added.\n",
$campaignCriterion->getCriterion()->getId(),
$campaignCriterion->getCriterion()->getType());
}
}
public static function add($campaignId, $ip) {
// Generate a refreshable OAuth2 credential for authentication.
$oAuth2Credential = (new OAuth2TokenBuilder())
->fromFile()
->build();
// Construct an API session configured from a properties file and the OAuth2
// credentials above.
$session = (new AdWordsSessionBuilder())
->fromFile()
->withOAuth2Credential($oAuth2Credential)
->build();
self::runExample(new AdWordsServices(), $session, $campaignId, $ip);
}
}

logging in with different user / resource owner

i am trying to write a tool that creates entries in the google calendar.
after following the google docs and creating an client-identifier/secret in the api console, i managed to put together a client that authenticates correctly and shows my registered google calendars. right now for me it looks like my google-account is somehow tied to my client-identifier/secret. what i want to know is: how can i change the auth process so that it is possible for an other user of this tool to enter his google-id and get access to his calendars?
EDIT: in other words (used in the RFC): I want make the resource owner-part editable while leaving the client-part unchanged. but my example, although working, ties together client and resource owner.
here is my app that works fine so far:
public void Connect()
{
var provider = new NativeApplicationClient(GoogleAuthenticationServer.Description);
provider.ClientIdentifier = "123456123456.apps.googleusercontent.com";
provider.ClientSecret = "nASdjKlhnaxEkasDhhdfLklr";
var auth = new OAuth2Authenticator<NativeApplicationClient>(provider, GetAuthorization);
var service = new CalendarService(auth);
//Events instances = service.Events.Instances("primary", "recurringEventId").Fetch();
var list = service.CalendarList.List().Fetch();
foreach (var itm in list.Items)
Console.WriteLine(itm.Summary);
}
private static readonly byte[] AditionalEntropy = { 1, 2, 3, 4, 5 };
private static IAuthorizationState GetAuthorization(NativeApplicationClient arg)
{
var state = new AuthorizationState(new[] { CalendarService.Scopes.Calendar.GetStringValue() });
state.Callback = new Uri(NativeApplicationClient.OutOfBandCallbackUrl);
var refreshToken = LoadRefreshToken();
if (!String.IsNullOrWhiteSpace(refreshToken))
{
state.RefreshToken = refreshToken;
if (arg.RefreshToken(state))
return state;
}
var authUri = arg.RequestUserAuthorization(state);
// Request authorization from the user (by opening a browser window):
Process.Start(authUri.ToString());
var frm = new FormAuthCodeInput();
frm.ShowDialog();
// Retrieve the access token by using the authorization code:
var auth = arg.ProcessUserAuthorization(frm.txtAuthCode.Text, state);
StoreRefreshToken(state);
return auth;
}
private static string LoadRefreshToken()
{
try
{
return Encoding.Unicode.GetString(ProtectedData.Unprotect(Convert.FromBase64String(Properties.Settings.Default.RefreshToken), AditionalEntropy, DataProtectionScope.CurrentUser));
}
catch
{
return null;
}
}
private static void StoreRefreshToken(IAuthorizationState state)
{
Properties.Settings.Default.RefreshToken = Convert.ToBase64String(ProtectedData.Protect(Encoding.Unicode.GetBytes(state.RefreshToken), AditionalEntropy, DataProtectionScope.CurrentUser));
Properties.Settings.Default.Save();
}
Prompt the user to enter their ClientIdentifier and ClientSecret, then pass these values to your Connect method.
i solved the problem myself.
the problem was, that i'm usually always connected to google and because i did't log out from google before my app redirected to google to get the access-token, google automatically generated the access-token for my account - skipping the part where an input-form appears where anyone could enter his/her user-credentials to let google generate an access-token for his/her account.

Microsoft Graph API - Updating password

I am using the Microsoft Graph API sample project. I am able to login fine.
I am trying to update the password of the user that is logged in using the following code:
public async Task<bool> UpdatePassword(GraphServiceClient graphClient, string newPassword)
{
User me = await graphClient.Me.Request().UpdateAsync(new User
{
PasswordProfile = new PasswordProfile
{
Password = newPassword,
ForceChangePasswordNextSignIn = false
},
});
return true;
}
When I execute the code, I get the following error:
{
Status: 500
Message: "No offeractions were provided for validating consent."
Internal error: "empty offerActions array."
}
Any idea what I might be doing incorrectly?
I gave access to everything "Users" related via the App Registration Portal at https://apps.dev.microsoft.com
Thank you!
There is a baked-in ChangePassword() function that you'll want to use for this:
await graphClient.Me.ChangePassword("current-pwd, "new-pwd").Request().PostAsync();

Resources