The Google+ API is set to "On" from google's developer console. I am fetching the profile information of the user by supplying the api key but I get an error saying:
Access Not Configured. Please use Google Developers Console to activate the API for your project. [403]
BaseClientService.Initializer ini = new BaseClientService.Initializer { ApiKey = "" };
PlusService plusService = new PlusService(ini);
if (plusService != null)
{
PeopleResource.GetRequest prgr = plusService.People.Get("me");
Person googleUser = prgr.Execute();
}
The error is thrown when Execute is called.
Does this service needs to be set up with "billed" profile ? This may be the reason I am getting access error.
The "me" argument only works when you have an authenticated user's OAuth 2.0 access token. Simple API access with a key only allows access to public data - try putting in a numeric user id instead of me and you should get a response.
Related
I'm trying to use Okta SSO to authenticate my users in AspNetZero app.
When I click on the OpenID in the bottom of the login page, I'm redirected to Okta login and then I'm back to my app login page and finally "openIdConnectLoginCallback" is calling "ExternalAuthenticate" on the TokenAuthController and the call to _externalAuthManager.GetUserInfo throw exception "name claim is missing".
In "login.service.ts", claims array contain "name" claim and ExternalAuthenticateModel.ProviderAccessCode contains a valid JSon Token and I check and "name" is in the token.
let claims = this.oauthService.getIdentityClaims();
const model = new ExternalAuthenticateModel();
model.authProvider = ExternalLoginProvider.OPENID;
model.providerAccessCode = this.oauthService.getIdToken();
model.providerKey = claims['sub'];
model.singleSignIn = UrlHelper.getSingleSignIn();
model.returnUrl = UrlHelper.getReturnUrl();
Here is my appsettings.json
Here is my app configuration in Okta
Any ideas to fix that "name" claim missing ?
I have an application using .NET Core 3.1 MVC Web App that uses Azure AD B2C to sign in users and I've just migrated it to use Microsoft Identity Web library.
We want to have two different policies for Sign In, one for regular users (B2C_1A_SignUpOrSignIn) and one for admin users (B2C_1A_SignInAdmin).
So, in the Appsettings, we have the following format:
"AzureAdB2C": {
"Instance": "https://url.b2clogin.com/tfp/",
"ClientId": "clientId",
"CallbackPath": "/signin-oidc",
"SignedOutCallbackPath": "/signout/B2C_1A_SignUpOrSignIn",
"Domain": "url.onmicrosoft.com",
"Domain_b2cLogin": "url", // Required by the Cookie Policy
"SignUpSignInPolicyId": "B2C_1A_SignUpOrSignIn",
"SignInAdminPolicyId": "B2C_1A_SignInAdmin",
"ResetPasswordPolicyId": "B2C_1A_PasswordReset",
"EditProfilePolicyId": "",
"ClientSecret": key,
"B2cExtensionAppClientId": "key"
},
In the Startup class, I just added the following:
services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApp(Configuration, "AzureAdB2C");
And I also overrode the "AzureController", so, for a regular user, I use the same method obtained from
here Microsoft Identity Web - Account Controller "SignIn". However, for an admin user, I changed that method to use something similar to what is provided by the PasswordReset method, as the following:
public IActionResult SignInAdmin()
{
string scheme = OpenIdConnectDefaults.AuthenticationScheme;
var redirectUrl = Url.Content("~/");
var properties = new AuthenticationProperties { RedirectUri = redirectUrl };
properties.Items[Constants.Policy] = "B2C_1A_SignInAdmin";
return Challenge(properties, scheme);
}
So, as you can see, I'm using a different policy name for this method.
Everything seems to work fine, the user is redirected to the correct login page based on the policy and the token is issued by Azure and our application accepts the Token, in our method
options.Events.OnTokenValidated = context => {}
However, soon after that, something goes wrong with the authentication and the method
options.Events.OnRemoteFailure
is called with the following exception
"{"Message contains error: 'invalid_grant', error_description: 'AADB2C90088: The provided grant has not been issued for this endpoint. Actual Value : B2C_1A_SignUpOrSignIn and Expected Value : B2C_1A_SignInAdmin ..."
So, my question is, what do I have to do to be able to use two different policies to sign in? Or is there any configuration that I should do to be able to do that?
Thank you in advanced.
I guess the B2c Middleware validates the "tfp" claim. This should usually match the SignInPolicyId. You might have to override the TokenValidation to let both policies (tfp = trustedFrameworkPolicy) be valid
I am trying to integrate several Google API calls into a custom Drupal 8 module.
I am basically trying to first get my custom class to get an access token from Google via OAuth before I try do anything else. I am doing this by using a class function with everything simply in one place. The function is as follows:
public function testTokenRequest(): void
{
// Setup Google Client Config within context of initialized class
$this->googleClient->setClientId($this->googleClientID);
$this->googleClient->setClientSecret($this->googleClientSecret);
$this->googleClient->setDeveloperKey($this->googleApiKey);
// Add Google MyBusiness scope
$this->googleClient->setScopes(array('https://www.googleapis.com/auth/plus.business.manage'));
try {
$accessToken = $this->googleClient->getAccessToken(); // null returned where breakpoint hit
$this->googleAccessToken = $accessToken; // Put xdebug breakpoint here
} catch (Exception $exception) {
echo $exception->getMessage();
}
}
Currently all I get is a null returned for the $accessToken = $this->googleClient->getAccessToken(); call.
Unsure where I am going wrong, possibly the AddScopes call because the vendor documentation for the apiclient does this slightly differently, i.e. $client->addScope(Google_Service_Plus::PLUS_ME); but I couldn't find the correct class to use for the MyBusinessAPI scope so used the OAuth playground string instead https://www.googleapis.com/auth/plus.business.manage
I get an OAuth Playground AccessToken returned when I use that but end up with a Permission Denied error instead even though I have the GMB API added to my whitelist under credentials.
Google MyBusiness is Oauth2 based. The access token is not received until the user has approved your app, it is normal that the function returns null if the user has not approved the app yet.
Here is an example on how you create a link where to send the user to start authentication and authorization for your app.
$client = new \Google_Client();
$client->setAuthConfig(getcwd() . '/../client_secret.apps.googleusercontent.com.json');
$client->setAccessType("offline"); // offline access
$client->setIncludeGrantedScopes(true); // incremental auth
$client->addScope(
array(
'https://www.googleapis.com/auth/userinfo.email',
'https://www.googleapis.com/auth/userinfo.profile',
'https://www.googleapis.com/auth/plus.business.manage'
)
);
$client->setRedirectUri('http://server.com/code');
$client->setApprovalPrompt('force');
return new Response(
'<html><body>Authenticate here : <a href="' .
$auth_url = filter_var($client->createAuthUrl(), FILTER_SANITIZE_URL)
. '">HERE</a></body></html>'
);
The example above assumes your server will also implement a /code endpoint where the user is redirected to with the authorization token, then you need to call the api to exchange the token with the access and refresh code.
This document will help you understand further
https://developers.google.com/api-client-library/php/auth/web-app
I created a Google API Console project and client ID with web application type.Then Using OAuth 2.0 Playground - Google Developers I authorized to drive, sheet and calendar scopes using my client id.
Also, Service account client id and scopes added and authorized in G Suite.
I tried to list files in a folder in the drive using the below sample
index.php
<?php
require_once 'vendor/autoload.php';
require_once 'vendor/google/apiclient/examples/templates/base.php';
$service = get_service_document();
$folderid='FOLDER_ID';
try {
$children1 = $service->files->listFiles(array(
'q' => "'$folderid' in parents "));
$filearray1 = $children1;
}
catch(Exception $e){
echo $e->getMessage();
}
print_r($children1);
exit;
function buildServiceDrive($userEmail,$service_id,$scope,$service_filename) {
$client = new Google_Client();
putenv("GOOGLE_APPLICATION_CREDENTIALS=".$service_filename);
if ($credentials_file = checkServiceAccountCredentialsFile()) {
// set the location manually
$client->setAuthConfig($credentials_file);
}
elseif (getenv('GOOGLE_APPLICATION_CREDENTIALS')) {
// use the application default credentials
$client->useApplicationDefaultCredentials();
}
else {
echo missingServiceAccountDetailsWarning();
return;
}
$client->setApplicationName("DRIVE");
$client->setScopes('https://www.googleapis.com/auth/drive');
$client->setSubject($userEmail);
return new Google_Service_Drive($client);
}
//COMMON FUNCTION TO CREATE CALENDAR ID
function get_service_document(){
$userstamp='user#domain.com';
$driveService =buildServiceDrive($userstamp,'','','project-id-451a5f6b12ce.json';
return $driveService;
}
But I got this issue
{
"error": "unauthorized_client",
"error_description": "Client is unauthorized to retrieve access tokens using this method."
}
I m getting this issues newly created Google API Console project only
Please help me to solve this.
Thanks in advance
This is a common error when running an API call with a service account but not properly completing the domain-wide delegation (DWD) or because the authorization in the admin console has not propagated yet.
This article explains in details the process of DWD. If you have done that, wait 24 hours and it should work. If it doesn't work after that, then it must be something else but as far as I can say right now, the DWD process is the issue.
PLEASE NOTE: DWD is available only to G Suite customers. If you are using a consumer gmail.com account, you won't be able to do this. Instead, you'll have to go through the user consent OAuth flow.
This error could also occur if API client only have write permissions and in scope you specify that you only need readonly access.
{
"error": "unauthorized_client",
"error_description": "Client is unauthorized to retrieve access tokens using this method."
}
I am working with this package Analytics-Laravel 4 for google analytics and I have follower all of the steps correctly. When I try to get the site id for example, I face this error:
Error refreshing the OAuth2 token, message: '{ "error" : "invalid_grant" }'
I have double checked all of the configurations, client id, service_account and private key but the error still occurs.
Anything else I should try to check that maybe would solve this issue?!
I didn't use this package before, I'm using google-api-php-client, but anyways, this error occurs if you don't set the refresh token.
You should know that you need to have the access token ONLY once. You also need to set the access type to be offline, which will provide you with a refresh token that you will use to automatically get a new access token without getting a new code every time your access token expires.
In google's console, I created a Client ID for web application. Make sure you set the redirect URI to your web page where you will receive the code and will extract the access token using that code.
Here is a code example using google-api-php-client, I hope it will help:
You need to run the following code only once, and retrieve and store the access token.
<?php
require_once('google-api-php-client-master/src/Google/Client.php');
session_start();
$client = new Google_Client();
$client->setApplicationName('APP_NAME');
$client->setClientId(YOUR_CLIENT_ID);
$client->setClientSecret('YOUR_CLIENT_SECRET');
$client->setRedirectUri('YOUR_REDIRECT_URI');
$client->setDeveloperKey('YOUR_DEV_KEY');
$client->setScopes(array('https://www.googleapis.com/auth/analytics.readonly'));
$client->setAccessType("offline");
// Step 1: Create an auth url
if (isset($_GET['ref']) && $_GET['ref'] == "1") {
$authUrl = $client->createAuthUrl();
return Redirect::to($authUrl);
}
// Step 2: The user accepted your access now you need to exchange it.
if (isset($_GET['code'])) {
$client->authenticate($_SESSION['code']); //Authenticate the client
$token = $client->getAccessToken(); //Get the access token
var_dump($token); //Store the token in your DB or config file
die();
}
?>
After getting your access token from the code above (which should contain a refresh token), store it in your DB or a config file.
Now the following code should authenticate the client and refresh the access token when it expires via the getAccessToken function
<?php
require_once('google-api-php-client-master/src/Google/Client.php');
require_once('google-api-php-client-master/src/Google/Service/Analytics.php');
$client = new Google_Client();
$client->setApplicationName('APP_NAME');
$client->setClientId(YOUR_CLIENT_ID);
$client->setClientSecret('YOUR_CLIENT_SECRET');
$client->setRedirectUri('YOUR_REDIRECT_URI');
$client->setDeveloperKey('YOUR_DEV_KEY');
$client->setScopes(array('https://www.googleapis.com/auth/analytics.readonly'));
$client->setAccessType("offline"); //Make sure the access type is offline to get a refresh token
$config = CoreConfig::find(1); //Getting the first record from the config table
$client->setAccessToken($config->google_access_token); //Retrieve the access token that you stored and set it to the client object
//Check this the token is expired
if($client->isAccessTokenExpired()) {
$token = json_decode($config->google_access_token, true); //Get the token stored, and convert JSON to array
$client->refreshToken($token['refresh_token']); //Set the refresh token
$newtoken = $client->getAccessToken(); //Call the getAccessToken() function to get a new access token for you
$config->update(array('google_access_token' => $newtoken)); //Store the new token in your DB
}
if ($client->getAccessToken()) {
$analytics = new Google_Service_Analytics($client);
//Do something with the $analytics object
}
?>
It could be the server time. If the local time on your server is out of sync with google's oAuth server even by a few seconds you'll get that error message.
You can check the time by running "date" in the console.
Running "sudo ntpdate ntp.ubuntu.com" solved it for us.