Google Domain Api Access Type Public Not Working - google-plus

I have issue connect with type access, after post with help google domain api on google plus page, top part on my post I can't see "public" only private, domain or show only for me, how can I resolve it ?
I spoke with google support he told me what on my console all good.
Scopes
http://i.prntscr.com/IVs4E5yHQLi30sYazCaKNw.png
Get Token
http://i.prntscr.com/afhAgxzgRz_AflG3fkLgrA.png
How I see on top my post
http://i.prntscr.com/VqeWNM9DS46SyHsQQS3XHw.png
$plusDomain = new \Google_Service_PlusDomains($client);
$activity = new \Google_Service_PlusDomains_Activity();
$obj = new \Google_Service_PlusDomains_ActivityObject();
$access = new \Google_Service_PlusDomains_Acl();
$access_type = new \Google_Service_PlusDomains_PlusDomainsAclentryResource();
$comment = 'new comments';
$me = $plusDomain->people->get('me');
$userId = $me->id;
$obj->setContent($comment);
$access->setDomainRestricted(true);
$access_type->setType('public');
$access->setItems(array($access_type));
$activity->setObject($obj);
$activity->setAccess($access);
$plusDomain->activities->insert($userId, $activity);

Related

Microsoft Graph API - Administrator Consent to update User Calendar

I am working on a App to integrate Microsoft Graph API, is it possible for the administrator of each tenant to give consent for permissions so that the user does not need to have any interaction with our app to give permission so that we can update the user calendar?
Or does the user have to provide authorization at least once in order to get the authorization token?
I have been looking at this guide:
https://learn.microsoft.com/en-gb/graph/auth-v2-service
You can update users' calendar by calling ms graph api without users sign in. But it depends on the api you used if support Application api permission. For example, this api is used to create event for calendar. It support application permission.
I also want to inform you that using application permission is not the best practice because it will give your application such a big permission to manage all users' calendars. But this seems to be your goal.
Let's come back to your requirement. And using the api I mentioned as an example. You firstly need to have an azure ad application and give it the correct api permission and let the tenant admin to consent the permission by clicking "grant admin consent for xx_tenant".
Then you also need to create a client secret for your azure ad application. Going to Azure ad -> Certificates & secrets -> New cient secret. Pls copy the secret. Then assuming you have an asp.net core app used to call the graph api. Then refer to this section or my code below to use graph sdk to call the api. Pls note, graphClient.Users["user_principle"] means who creates the event, the Attendees defines whose calendars will be added events.
using Azure.Identity;
using Microsoft.Graph;
var scopes = new[] { "https://graph.microsoft.com/.default" };
var tenantId = "your_tenant_name.onmicrosoft.com";
var clientId = "azure_ad_app_id";
var clientSecret = "client_secret";
var clientSecretCredential = new ClientSecretCredential(
tenantId, clientId, clientSecret);
var graphClient = new GraphServiceClient(clientSecretCredential, scopes);
var #event = new Event
{
Subject = "Let's go for lunch",
Body = new ItemBody
{
ContentType = BodyType.Html,
Content = "Does noon work for you?"
},
Start = new DateTimeTimeZone
{
DateTime = "2022-07-15T12:00:00",
TimeZone = "Pacific Standard Time"
},
End = new DateTimeTimeZone
{
DateTime = "2017-07-15T14:00:00",
TimeZone = "Pacific Standard Time"
},
Location = new Location
{
DisplayName = "Harry's Bar"
},
Attendees = new List<Attendee>()
{
new Attendee
{
EmailAddress = new EmailAddress
{
Address = "samanthab#contoso.onmicrosoft.com",
Name = "Samantha Booth"
},
Type = AttendeeType.Required
}
},
AllowNewTimeProposals = true,
TransactionId = "7E163156-7762-4BEB-A1C6-729EA81755A7"
};
await graphClient.Users["user_principle"].Events
.Request()
.Header("Prefer","outlook.timezone=\"Pacific Standard Time\"")
.AddAsync(#event);

IdentityServer4 - Best Practises to get User Information from access token

I recently started developing using IdentityServer4. What I want to achieve is to have a number of independent web applications that use the same authorization server, my identity server.
My problem is how to make sure, that all my independend web applications have obtained and display the up to date user information (like firstName,lastName,avatar etc) which are stored in my IdentityServer4 database
I am aware that I should implement the IProfileService interface, to make sure that user-info endpoint will return all additional user info, but I dont know where to call this api request from my web applications. I have created a function that looks like this:
var t = await HttpContext.GetTokenAsync("access_token");
if (!String.IsNullOrEmpty(t))
{
var client = new HttpClient();
var userInfoRequest = new UserInfoRequest()
{
Address = "https://localhost:5001/connect/userinfo",
Token = t
};
var response = client.GetUserInfoAsync(userInfoRequest).Result;
if (response.IsError)
throw new Exception("Invalid accessToken");
dynamic responseObject = JsonConvert.DeserializeObject(response.Raw);
string firstName = responseObject.FirstName.ToString();
HttpContext.Session.SetString("User_FirstName", firstName);
string lastName = responseObject.LastName.ToString();
HttpContext.Session.SetString("User_LastName", lastName);
HttpContext.Session.SetString("User_FullName", firstName + " " + lastName);
if (responseObject.Image != null && !String.IsNullOrEmpty(responseObject.Image.ToString()))
{
string im = responseObject.Image.ToString();
HttpContext.Session.SetString("User_Image", im);
}
}
to get user Info from web applications.
My problem is when and how to call this function, every time the user redirects logged in from identity server to my web application, and how to make sure that Sessions will keep user associated data, for as much as the user remains logged in to my web application.
You can call Token Introspection endpoint to get all user info from #identityServer4.

Hangout OAuth - Invalid Scope : Some requested scopes cannot be shown

I am facing the below error while generating token for service account for the Hangout Scope - https://www.googleapis.com/auth/chat.bot.
Where i receive 400 response code after making a post request to this url -
https://www.googleapis.com/oauth2/v4/token
the params are
Content-Type:application/x-www-form-urlencoded
httpMode:POST
body:grant_type=jwt-bearer&assertion=assertion-token
Note:This was completely working fine. Suddenly am facing this issue.
cross verified: jwt generation,service_account_id and etc...
Error Response : { "error": "invalid_scope", "error_description": "Some requested scopes cannot be shown": [https://www.googleapis.com/auth/chat.bot]}
code for generating assertion:
//FORMING THE JWT HEADER
JSONObject header = new JSONObject();
header.put("alg", "RS256");
header.put("typ", "JWT");
//ENCODING THE HEADER
String encodedHeader = new String(encodeUrlSafe(header.toString().getBytes("UTF-8")));
//FORMING THE JWT CLAIM SET
JSONObject claimSet = new JSONObject();
claimSet.put("iss","123#hangout.iam.gserviceaccount.com");
claimSet.put("sub","one#domain.com");
claimSet.put("scope","https://www.googleapis.com/auth/chat.bot");
claimSet.put("aud","https://oauth2.googleapis.com/token");
long time = System.currentTimeMillis() / 1000;
claimSet.put("exp",time+3600);
claimSet.put("iat",time);
//ENCODING THE CLAIM SET
String encodedClaim = new String(encodeUrlSafe(claimSet.toString().getBytes("UTF-8")));
//GENERATING THE SIGNATURE
String password = "secretofkey", alias = "privatekey";
String signInput = encodedHeader + "." + encodedClaim;
Signature signature = Signature.getInstance("SHA256withRSA");
String filepath = "/check/PrivateKeys/hangoutPKEY.p12";
KeyStore kstore = KeyStore.getInstance("PKCS12");
fis = new FileInputStream(filepath);
kstore.load(fis, password.toCharArray());
KeyStore.PrivateKeyEntry pke = (KeyStore.PrivateKeyEntry) kstore.getEntry(alias, new KeyStore.PasswordProtection(password.toCharArray()));
PrivateKey pKey = pke.getPrivateKey();
signature.initSign(pKey);
signature.update(signInput.getBytes("UTF-8"));
String encodedSign = new String(encodeUrlSafe(signature.sign()), "UTF-8");
//JWT GENERATION
String JWT = signInput + "." + encodedSign;
String grant_type = URLEncoder.encode("urn:ietf:params:oauth:grant-type:jwt-bearer");
reqBody = "grant_type=" + grant_type + "&assertion=" + JWT;
public static byte[] encodeUrlSafe(byte[] data) {
Base64 encoder = new Base64();
byte[] encode = encoder.encodeBase64(data);
for (int i = 0; i < encode.length; i++) {
if (encode[i] == '+') {
encode[i] = '-';
} else if (encode[i] == '/') {
encode[i] = '_';
}
}
return encode;
}
Does anyone have any idea, where am going wrong?
Short answer:
You are trying to use domain-wide authority to impersonate a regular account. This is not supported in Chat API.
Issue detail:
You are using the sub parameter when building your JWT claim:
claimSet.put("sub","one#domain.com");
Where sub refers to:
sub: The email address of the user for which the application is requesting delegated access.
I noticed that, if I add the sub parameter to my test code, I get the same error as you.
Solution:
Remove this line from your code in order to authorize with the service account (without impersonation) and handle bot data:
claimSet.put("sub","one#domain.com");
Background explanation:
Chat API can be used for bots to manage their own data, not to manage end-user data. Therefore, you can only use a service account to act as the bot, without impersonating an end-user.
From this Issue Tracker comment:
At the present moment, Chat API can only be used to manage bot-related data (listing the spaces in which the bot is included, etc.). Using domain-wide delegation to manage regular users' data is not currently possible.
Feature request:
If you'd like to be able to access regular users' data with your service account and domain-wide delegation via Chat API, you are not alone. This feature has been requested before in Issue Tracker:
Accessing the Google Chats of regular users using domain-wide delegated permission and service account credentials
I'd suggest you to star the referenced issue in order to keep track of it and to help prioritizing it.
Reference:
Using service accounts
Delegating domain-wide authority to the service account
Preparing to make an authorized API call

Google Sheets API v4 receives HTTP 401 responses for public feeds

I'm having no luck getting a response from v4 of the Google Sheets API when running against a public (i.e. "Published To The Web" AND shared with "Anyone On The Web") spreadsheet.
The relevant documentation states:
"If the request doesn't require authorization (such as a request for public data), then the application must provide either the API key or an OAuth 2.0 token, or both—whatever option is most convenient for you."
And to provide the API key, the documentation states:
"After you have an API key, your application can append the query parameter key=yourAPIKey to all request URLs."
So, I should be able to get a response listing the sheets in a public spreadsheet at the following URL:
https://sheets.googleapis.com/v4/spreadsheets/{spreadsheetId}?key={myAPIkey}
(with, obviously, the id and key supplied in the path and query string respectively)
However, when I do this, I get an HTTP 401 response:
{
error: {
code: 401,
message: "The request does not have valid authentication credentials.",
status: "UNAUTHENTICATED"
}
}
Can anyone else get this to work against a public workbook? If not, can anyone monitoring this thread from the Google side either comment or provide a working sample?
I managed to get this working. Even I was frustrated at first. And, this is not a bug. Here's how I did it:
First, enable these in your GDC to get rid of authentication errors.
-Google Apps Script Execution API
-Google Sheets API
Note: Make sure the Google account you used in GDC must be the same account you're using in Spreadsheet project else you might get a "The API Key and the authentication credential are from different projects" error message.
Go to https://developers.google.com/oauthplayground where you will acquire authorization tokens.
On Step 1, choose Google Sheets API v4 and choose https://www.googleapis.com/auth/spreadsheets scope so you have bot read and write permissions.
Click the Authorize APIs button. Allow the authentication and you'll proceed to Step 2.
On Step 2, click Exchange authorization code for tokens button. After that, proceed to Step 3.
On Step 3, time to paste your URL request. Since default server method is GET proceed and click Send the request button.
Note: Make sure your URL requests are the ones indicated in the Spreadsheetv4 docs.
Here's my sample URL request:
https://sheets.googleapis.com/v4/spreadsheets/SPREADSHEET_ID?includeGridData=false
I got a HTTP/1.1 200 OK and it displayed my requested data. This goes for all Spreadsheetv4 server-side processes.
Hope this helps.
We recently fixed this and it should now be working. Sorry for the troubles, please try again.
The document must be shared to "Anyone with the link" or "Public on the web". (Note: the publishing settings from "File -> Publish to the web" are irrelevant, unlike in the v3 API.)
This is not a solution of the problem but I think this is a good way to achieve the goal. On site http://embedded-lab.com/blog/post-data-google-sheets-using-esp8266/ I found how to update spreadsheet using Google Apps Script. This is an example with GET method. I will try to show you POST method with JSON format.
How to POST:
Create Google Spreadsheet, in the tab Tools > Script Editor paste following script. Modify the script by entering the appropriate spreadsheet ID and Sheet tab name (Line 27 and 28 in the script).
function doPost(e)
{
var success = false;
if (e != null)
{
var JSON_RawContent = e.postData.contents;
var PersonalData = JSON.parse(JSON_RawContent);
success = SaveData(
PersonalData.Name,
PersonalData.Age,
PersonalData.Phone
);
}
// Return plain text Output
return ContentService.createTextOutput("Data saved: " + success);
}
function SaveData(Name, Age, Phone)
{
try
{
var dateTime = new Date();
// Paste the URL of the Google Sheets starting from https thru /edit
// For e.g.: https://docs.google.com/---YOUR SPREADSHEET ID---/edit
var MyPersonalMatrix = SpreadsheetApp.openByUrl("https://docs.google.com/spreadsheets/d/---YOUR SPREADSHEET ID---/edit");
var MyBasicPersonalData = MyPersonalMatrix.getSheetByName("BasicPersonalData");
// Get last edited row
var row = MyBasicPersonalData.getLastRow() + 1;
MyBasicPersonalData.getRange("A" + row).setValue(Name);
MyBasicPersonalData.getRange("B" + row).setValue(Age);
MyBasicPersonalData.getRange("C" + row).setValue(Phone);
return true;
}
catch(error)
{
return false;
}
}
Now save the script and go to tab Publish > Deploy as Web App.
Execute the app as: Me xyz#gmail.com,
Who has access to the app: Anyone, even anonymous
Then to test you can use Postman app.
Or using UWP:
private async void Button_Click(object sender, RoutedEventArgs e)
{
using (HttpClient httpClient = new HttpClient())
{
httpClient.BaseAddress = new Uri(#"https://script.google.com/");
httpClient.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));
httpClient.DefaultRequestHeaders.AcceptEncoding.Add(new System.Net.Http.Headers.StringWithQualityHeaderValue("utf-8"));
string endpoint = #"/macros/s/---YOUR SCRIPT ID---/exec";
try
{
PersonalData personalData = new PersonalData();
personalData.Name = "Jarek";
personalData.Age = "34";
personalData.Phone = "111 222 333";
HttpContent httpContent = new StringContent(JsonConvert.SerializeObject(personalData), Encoding.UTF8, "application/json");
HttpResponseMessage httpResponseMessage = await httpClient.PostAsync(endpoint, httpContent);
if (httpResponseMessage.IsSuccessStatusCode)
{
string jsonResponse = await httpResponseMessage.Content.ReadAsStringAsync();
//do something with json response here
}
}
catch (Exception ex)
{
}
}
}
public class PersonalData
{
public string Name;
public string Age;
public string Phone;
}
To above code NuGet Newtonsoft.Json is required.
Result:
If your feed is public and you are using api key, make sure you are throwing a http GET request.In case of POST request, you will receive this error.
I faced same.
Getting data using
Method: spreadsheets.getByDataFilter has POST request

Can't Query Google Analytics Reports API Using OAuth 2

I am trying to to use the latest version of the Report API using OAuth 2. It doesn't appear that there are many people using this version yet, so it has been really hard to find examples.
I have a refresh token, which I am using to generate an access token.
private AnalyticsService getAnalyticsService()
{
AuthorizationServerDescription description = new AuthorizationServerDescription();
description.TokenEndpoint = new Uri(login.TokenEndpoint);
description.AuthorizationEndpoint = new Uri(login.AuthorizationEndpoint);
WebServerClient client = new WebServerClient(description, login.ClientId, login.ClientSecret);
OAuth2Authenticator<WebServerClient> authenticator = new OAuth2Authenticator<WebServerClient>(client, authenticate);
AnalyticsService service = new AnalyticsService(authenticator);
return service;
}
private IAuthorizationState authenticate(WebServerClient client)
{
string[] scopes = new string[] { login.ScopeUrl }; // not sure if this is necessary
IAuthorizationState state = new AuthorizationState(scopes) { RefreshToken = login.RefreshToken };
client.RefreshToken(state);
return state;
}
This appears to be working just fine:
{
"access_token" : "ya29.AHES6ZQy67SSLHWJWGWcLbLn69yKfq59y6dTHDf4ZoH9vHY",
"token_type" : "Bearer",
"expires_in" : 3600
}
However, when I do a request, I am getting an error. For example, here
is a query that results in an error:
AnalyticsService service = getAnalyticsService();
ManagementResource.ProfilesResource.ListRequest request = service.Management.Profiles.List("~all", "~all");
return request.Fetch();
This is the error I get:
{"error":{"errors":[{"domain":"global","reason":"authError","message":"Invalid
Credentials","locationType":"header","location":"Authorization"}],"code":401,"message":"Invalid
Credentials"}}
I have tried other queries, providing valid profile IDs. However, I am
always getting a 401 error, saying I'm not authorized. I am having
trouble finding examples where people are using this code. It could be
something simple like a bad URL or something. Unfortunately, I have no
way to telling. It seems strange that I can get an access token, but I
can't seem to perform any queries.
With OAuth 2, the scope changed from:
https://www.google.com/analytics/feeds/
to:
https://www.googleapis.com/auth/analytics.readonly
You are getting the authentication error because you were trying to get access without the proper scope.
Quick and easy fix.