403 Current user cannot create courses [forbidden] while creating a course for Google classroom api (.Net) - google-classroom

I have created a VisualStudio (C#) project, wihch use google classroom apis.
With Super admin, It can create a course, but with delegated admin, It returns an error.
I have use a delegated admin. Why does that error return ?
Errors [
Message[#UserCannotCreateCourse Current user cannot create courses.] Location[ - ] Reason[forbidden] Domain[global]
]
my code is below given
string[] Scopes = {ClassroomService.Scope.ClassroomCourses};
UserCredential credential;
using (var stream = new FileStream("credentials.json", FileMode.Open, FileAccess.Read))
{
string credPath = "token.json";
credential = GoogleWebAuthorizationBroker.AuthorizeAsync(
GoogleClientSecrets.Load(stream).Secrets,
Scopes,
"user",
CancellationToken.None,
new FileDataStore(credPath, true)).Result;
Console.WriteLine("Credential file saved to: " + credPath);
}
var service = new ClassroomService(new BaseClientService.Initializer()
{
HttpClientInitializer = credential,
ApplicationName = "Classroom test"
});
var body = new Course()
{
Name = "MyFirstClass",
OwnerId = "me"
};
var course = service.Courses.Create(body).Execute();
"credentials.json"File is from My Google Cloud Platform project.
My project is verificated.
./auth/classroom/courses
./auth/classroom/rosters
(etc.)
Delegated admin is created by Google Console.
I added custom admin role.

I found that the owner of the classroom course must a member of classroom_teachers Group. (If the account is not the super admin)
With an account that has not be a teacher, classroom api gets error.
And after becoming a teacher (manually sign-in, and create a classroom course), classroom api succeeded.
So, before creating a course, I join that account into classroom_teacher group.
Thank you.

Related

Unable to add attendees to google calendar using service account

I'm having couple of issues with adding attendees to my calendar using google calendar API and service account.
My service account has domain-wide delegation ticket in the cloud console and I am able to create/update a event without adding attendees.
When I try to send request with attendee then I get following response:
Google.Apis.Requests.RequestError
Service accounts cannot invite attendees without Domain-Wide Delegation of Authority. [403]
Errors [Message[Service accounts cannot invite attendees without Domain-Wide Delegation of Authority.] Location[ - ] Reason[forbiddenForServiceAccounts] Domain[calendar]
This is how my code looks like:
var eventDetails = _calendarService.GetEvent(eventDto.EventId).GetAwaiter().GetResult();
eventDetails.Attendees.Add( new EventAttendee
{
DisplayName = "Test Name",
Email = "testemail#example.com" // I tried with few emails but results is same
});
_credential = AuthorizeServiceAccount();
_calendarService = new CalendarService(new BaseClientService.Initializer()
{
HttpClientInitializer = _credential,
ApplicationName = _calendarOptions.AplicationName,
});
var request = _calendarService.Events.Patch(eventRequest,_calendarOptions.CalendarId, eventId);
var result = await request.ExecuteAsync();
public GoogleCredential AuthorizeServiceAccount()
{
var serviceAccountCredential = new ServiceAccountCredential(
new ServiceAccountCredential.Initializer(_calendarOptions.Id) // I'm using service account email here, tried with clientId but same result
{
ProjectId = _calendarOptions.ProjectId,
KeyId = _calendarOptions.KeyId,
User = _calendarOptions.User, // I tried with email from request or null value - for both same result
Scopes = _calendarOptions.Scopes, // ["https://www.googleapis.com/auth/gmail.send", "https://www.googleapis.com/auth/calendar.readonly","https://www.googleapis.com/auth/calendar.events","https://www.googleapis.com/auth/calendar" ],
}
.FromPrivateKey(_calendarOptions.Key));
return GoogleCredential.FromServiceAccountCredential(serviceAccountCredential);
}
Can you please help me so I will be able to add attendees to my events? I don't need to send emails to attendees but emails are required in google API. I don't want also to have G Suite domain account as it's paid.

Google My Business API: issue obtaining Reviews

What's been done so far:
The Prerequisites and Basic Setup steps have been followed, and our
account has been granted access to "Google My Business API". (The
dashboard says "Activation status: Enabled")
In the APIs section of
google, a Service Account has been created under the Google Project
with the role of Editor.
In the My Business section of google i can
see our 6 published/verified Locations.
When our website uses the Service Account to interrogate the "List all reviews" api method, the exception back is "Google.GoogleApiException: 'Parameter validation failed for "parent"'"
A bit more about our code: Its asp.net and using a "Google.Apis.MyBusiness.v4" nuget package generated from https://github.com/googleapis/google-api-dotnet-client/issues/1352#issuecomment-475167066. I have downloaded the JWT file from the google dashboard, and the credential and business service objects are constructed as follows:
var scopes = new List<string>()
{
"https://www.googleapis.com/auth/plus.business.manage",
};
var stream = new FileStream("key.json", FileMode.Open, FileAccess.Read);
var credential = GoogleCredential.FromStream(stream);
credential = credential.CreateScoped(scopes);
var initializer = new BaseClientService.Initializer()
{
HttpClientInitializer = credential,
ApplicationName = "Google Reviews",
};
var service = new MyBusinessService(initializer);
And the Reviews api call where the exception happens
var reviewsListRequest = service.Accounts.Locations.Reviews.List("our location name here");
var listReviewsResponse = reviewsListRequest.Execute();
So the question is what isn't set up correctly and causing that exception?
Example:
var reviewsListRequest = service.Accounts.Locations.Get("accounts/accountnumber")
^^ WILL WORK
var reviewsListRequest = service.Accounts.Locations.Get("accountnumber");
^^ WILL NOT WORK

Error in using YouTube Reporting Services with Service Account

I'm getting below error when I try to accessing YouTube Reporting Services API using Service Account.
Google.GoogleApiException HResult=0x80131500
Message=Google.Apis.Requests.RequestError The caller does not have
permission [403] Errors [ Message[The caller does not have
permission] Location[ - ] Reason[forbidden] Domain[global] ]
When I searched online, somewhere I saw we need to have GSuite subscription in order to use service account with API, is it correct?
Here is my code snippet:
String serviceAccountEmail = "xxxxxxxxxxxxx#youtubereportingapi.iam.gserviceaccount.com";
var certificate = new X509Certificate2(#"xxxxxxxx.p12", "notasecret", X509KeyStorageFlags.Exportable);
ServiceAccountCredential credential = new ServiceAccountCredential(
new ServiceAccountCredential.Initializer(serviceAccountEmail)
{
Scopes = new[] { YouTubeReportingService.Scope.YtAnalyticsReadonly, YouTubeReportingService.Scope.YtAnalyticsMonetaryReadonly }
}.FromCertificate(certificate));
var youtubeReportingService = new YouTubeReportingService(new BaseClientService.Initializer()
{
HttpClientInitializer = credential,
ApplicationName = Assembly.GetExecutingAssembly().GetName().Name
});
var jobsListResponse = youtubeReportingService.Jobs.List().Execute(); // Here its throwing error
In order to use a service account you must share data with it. I have never heard of using GSuite with a YouTube account you can have the admin try and set up domain wide delegation to the service account. However to my knowledge there is no way to share YouTube data with a service account.
Service accounts are not supported by the YouTube APIs. You will need to use Oauth2 and save your refresh token for access later. The docs only mention OAuth2.

Google classroom authentication based on Domains

Presently i am working on google classroom API to integrate classroom into my .NET product.My problem is when i execute this method it asking authentication for first time but when i execute this code next time it directly log in as previous log in credentials.Even i change the client_secret.json of another(2nd) domain also it directly login as 1st domain authenticated user.My requirement is when i change the client_secret.json file dynamically in code at run time it will directly log in as domain user of this client_secret.json file rather than previous domain user of client_secret.json file.Is this possible?
If yes How can i achieve this.Please any one help on this.
private ClassroomService getservice()
{
using (var stream =
new FileStream(Server.MapPath("client_secret.json"), FileMode.Open, FileAccess.Read))
{
string credPath = System.Environment.GetFolderPath(
System.Environment.SpecialFolder.Personal);
credPath = Path.Combine(credPath, ".credentials");
credential = GoogleWebAuthorizationBroker.AuthorizeAsync(
GoogleClientSecrets.Load(stream).Secrets,
Scopes,
"user",
CancellationToken.None,
new FileDataStore(credPath, true)).Result;
}
var service = new ClassroomService(new BaseClientService.Initializer()
{
HttpClientInitializer = credential,
ApplicationName = ApplicationName,
});
return service;k
}
The client_secret.json file holds application-specific credentials, not user- or domain-specific credentials. Changing the client_secret.json file is not the correct way to log in/out users. Instead, you'll need to use a FileDataStore with a different path.

Google calendar api CalendarList List return empty element

EDIT: The original poster asked this for C#, but the same problem occurs regardless of the library used, and its solution is language independent.
Using C# lib,
string service_account = "myaccount#developer.gserviceaccount.com";
var certificate = new X509Certificate2(#"pathtomy-privatekey.p12", "notasecret", X509KeyStorageFlags.Exportable);
ServiceAccountCredential credential = new ServiceAccountCredential(
new ServiceAccountCredential.Initializer(service_account)
{
Scopes = new[] { CalendarService.Scope.Calendar }
}.FromCertificate(certificate));
// Create the service.
var service = new CalendarService(new BaseClientService.Initializer()
{
HttpClientInitializer = credential,
ApplicationName = "My project name",
});
var calendarList = service.CalendarList.List().Execute();
IList<CalendarListEntry> items = calendarList.Items;
items is empty. On https://developers.google.com/google-apps/calendar/v3/reference/calendarList/list, when I try the api, I get the good result.
I really don't understand why I don't have any result : seems like if the service_account do not have the same calendar as my gmail account linked to.
Any suggestion ?
Thanks.
The solution is to share the existing calendar with the service account
<paste-your-account-here>#developer.gserviceaccount.com
(You can find the account in question under the credentials tab in Google Developers Console, it's called 'EMAIL ADDRESS')

Resources