I have a service account setting up with domain wide delegation to Gsuite domain.
I'd like to impersonate one of the users to be the organizer of a created event.
My code is:
List<String> scopes = new ArrayList<>();
scopes.add(CalendarScopes.CALENDAR);
scopes.add(CalendarScopes.CALENDAR_EVENTS);
InputStream credentialsJSON = Service5.class.getClassLoader()
.getResourceAsStream("credentials.json");
GoogleCredential gcFromJson = GoogleCredential.fromStream(credentialsJSON, HTTP_TRANSPORT, JSON_FACTORY).createScoped(scopes);
GoogleCredential cred = new GoogleCredential.Builder()
.setTransport(gcFromJson.getTransport())
.setJsonFactory(gcFromJson.getJsonFactory())
.setServiceAccountId(gcFromJson.getServiceAccountId())
.setServiceAccountUser("edt#company.tn")
.setServiceAccountPrivateKey(gcFromJson.getServiceAccountPrivateKey())
.setServiceAccountScopes(gcFromJson.getServiceAccountScopes())
.build();
Calendar service = new Calendar.Builder(HTTP_TRANSPORT, JSON_FACTORY, cred).setApplicationName(APPLICATION_NAME).build();
Event event = new Event().setSummary("Test");
DateTime startDateTime = new DateTime("2020-04-27T09:00:00.000Z");
EventDateTime start = new EventDateTime()
.setDateTime(startDateTime)
.setTimeZone("Africa/Tunis");
event.setStart(start);
DateTime endDateTime = new DateTime("2020-04-27T10:30:00.000Z");
EventDateTime end = new EventDateTime()
.setDateTime(endDateTime)
.setTimeZone("Africa/Tunis");
event.setEnd(end);
List<EventAttendee> attendees = new ArrayList<EventAttendee>();
EventAttendee ens = new EventAttendee().setEmail("user#company.tn");
attendees.add(ens);
event.setAttendees(attendees);
String calendarId = "primary";
event = service.events().insert(calendarId, event).execute();
But I got that exception:
EDIT - 1
I downloaded the json file resulted from CREATE KEY
Got that exception:
Exception in thread "main"
com.google.api.client.auth.oauth2.TokenResponseException: 401
Unauthorized at
com.google.api.client.auth.oauth2.TokenResponseException.from(TokenResponseException.java:105)
at
com.google.api.client.auth.oauth2.TokenRequest.executeUnparsed(TokenRequest.java:287)
at
com.google.api.client.auth.oauth2.TokenRequest.execute(TokenRequest.java:307)
at
com.google.api.client.googleapis.auth.oauth2.GoogleCredential.executeRefreshToken(GoogleCredential.java:394)
at
com.google.api.client.auth.oauth2.Credential.refreshToken(Credential.java:493)
at
com.google.api.client.auth.oauth2.Credential.intercept(Credential.java:217)
at
com.google.api.client.http.HttpRequest.execute(HttpRequest.java:880)
at
com.google.api.client.googleapis.services.AbstractGoogleClientRequest.executeUnparsed(AbstractGoogleClientRequest.java:419)
at
com.google.api.client.googleapis.services.AbstractGoogleClientRequest.executeUnparsed(AbstractGoogleClientRequest.java:352)
at
com.google.api.client.googleapis.services.AbstractGoogleClientRequest.execute(AbstractGoogleClientRequest.java:469)
at tn.esprit.spring.google.calendar.Service5.main(Service5.java:183)
Could you please tell me what I missed?.
Thanks a lot
To use a service account, you need to create dedicated service accounts credentials
Go to the GCP console
Choose a project
Go on APIs & Services -> Credentials
Choose + CREATE CREDENTIALS -> Service Account
Choose a Service account name and click on Create
If desired, you can select a role (optional)
Click on Create key and select JSON (p12 is also possible, but you will need to build GoogleCredential differently
The correct json file will be downloaded to your computer
It will look as following:
{
"type": "service_account",
...
The json file you were using was not the right one for service accounts, it did not have the field type specified - thus the error 'type' field not specified.
Related
Is there possibility for encrypted use of the Google drive OAuth2 TokenResponse file?
My target:
If my token file is encrypted, end user can't use it (which is after the authority in browser) for another target.
Thanks in advance!
VB.NET code:
'prerequisites: create oauth2 client ids for gmail user and download file client_secret.json
Dim GooSvc As Google.Apis.Drive.v3.DriveService
Dim UserInfo As Google.Apis.Auth.OAuth2.UserCredential
Dim Stream1 = New System.IO.MemoryStream(New System.Text.UTF8Encoding().GetBytes("content_of_client_secret.json"))
UserInfo = Google.Apis.Auth.OAuth2.GoogleWebAuthorizationBroker.AuthorizeAsync(
Google.Apis.Auth.OAuth2.GoogleClientSecrets.Load(Stream1).Secrets,
New String() {"https://www.googleapis.com/auth/drive"},
"user1",
System.Threading.CancellationToken.None,
New Google.Apis.Util.Store.FileDataStore("d:\temp", True)).Result
GooSvc = New Google.Apis.Drive.v3.DriveService(New Google.Apis.Services.BaseClientService.Initializer() With {.HttpClientInitializer = UserInfo})
After this, the token file d:\temp\Google.Apis.Auth.OAuth2.Responses.TokenResponse-user1:
- created automatically (after the authority in browser) if it's not exists
- refreshed automatically if it's out of date (after 1 hour)
- nothing happens with it, if it's "fresh" (within 1 hour)
Example content of the token file:
{"access_token":"ya29.XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX-XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX","token_type":"Bearer","expires_in":3600,"refresh_token":"1/XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX","scope":"https://www.googleapis.com/auth/drive","Issued":"2019-06-02T13:21:54.775+02:00","IssuedUtc":"2019-06-02T11:21:54.775Z"}
So my problem is little bit complicated.
Main goal: register account (class / table) that contains list of Players (class / table) from a web application into a SQL Server database through a WCF service.
So for creating the classes I used Linq-to-SQL which created the Account and Player class. The Player has a foreign key AccountEmail to the Account table. Due to that the class Account has EntitySet<Player> _Players;.
Now the web application has reference to this service and when user finish registration I am making an POST request with WebClient and DataContractJsonSerializer to the service .
Unfortunately the service or the http protocol cannot understand the request :
System.Net.WebException: The remote server returned an error: (400)
Full error response from server
https://s31.postimg.org/x6b27uqqj/errorrr.png
The fail is on service side for some reason it doesn't know how to read the json player DB.designer.cs:line 295 at ReadPlayerFromJson(XmlReaderDelegator
Service:
[OperationContract]
[WebInvoke(UriTemplate = "/Register",
RequestFormat = WebMessageFormat.Json,
ResponseFormat = WebMessageFormat.Json, Method = "POST")]
void RegisterAccount(Account account);
Client side :
DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(Account));
MemoryStream mem = new MemoryStream();
Account a = new Account { EMAIL = Email.Text, PASSWORD = Password.Text, NAME = nickname.Text};
a.Players = accountPLayers.ToArray();
ser.WriteObject(mem, a);
string data = Encoding.UTF8.GetString(mem.ToArray(), 0, (int)mem.Length);
WebClient webClient = new WebClient();
webClient.Headers["Content-type"] = "application/json";
webClient.Encoding = Encoding.UTF8;
webClient.UploadString(WEB_SITE_URL+ "/Register", "POST", data);
When sending Account without the list of players, the operation succeeds:
{"EMAIL":"test#gmail.com","NAME":"1","PASSWORD":"test","Players":null}
With the list of players the operation fails :
{"EMAIL":"test#gmail.com","NAME":"1","PASSWORD":"test","Players":[{"Account":null,"AccountEmail":"test#gmail.com","FirstName":"test","Id":0,"LastName":"test","Type":-1}]}
Questions:
I guess that REST service expecting to get only Account and doesn't know what is the list of players? I have to define that somehow.
Why in the service does the Account have EntitySet<Player> _Players;? And in the client after adding reference to service it is an array Player[] ?
Why does Linq-to-SQL add field Account to player? What should it contain? As you can see this field is null in the json.
Is complex object/known types has to do something with my problem ?
Please help me to solve this issue, thanks!
Solved !!!
So if any one ever will get this problem ,
The thing is that player has foreign key of EMAIL column to Account Email .
When you create your JSON DO NOT PUT EMAIL INSIDE EACH PLAYER
LINQTOSQL knows the association and will add it automatically when parsing the JSON .
So my JSON Sent to the service looks like this :
{"EMAIL":"test#gmail.com","NAME":"test","PASSWORD":"test#A","Players":[{"Account":null,"AccountEmail":null,"FirstName":"wow","Id":0,"LastName":"koko","Type":null}]}.
In my ASP.NET application I am implementing Google Document List API, to fetch User data I using OAuth2 to do so I did some code:
string CLIENT_ID = "123456789321.apps.googleusercontent.com";
string CLIENT_SECRET = "xxxxxxxxxxxxxxxxxxxxxxxx";
string SCOPE = "https://docs.google.com/feeds/ https://docs.googleusercontent.com/ https://spreadsheets.google.com/feeds/";
string REDIRECT_URI = "urn:ietf:wg:oauth:2.0:oob";
parameters = new OAuth2Parameters();
parameters.ClientId = CLIENT_ID;
parameters.ClientSecret = CLIENT_SECRET;
parameters.RedirectUri = REDIRECT_URI;
parameters.Scope = SCOPE;
parameters.AccessCode = Convert.ToString(HttpContext.Current.Session["AccessCode"]);
OAuthUtil.GetAccessToken(parameters);
settings = new RequestSettings("My Application", parameters);
Every time OAuthUtil.GetAccessToken(parameters); gives error that is:
Can any one tell me where I am doing mistake?
Also, how to access RefreshToken??
You are using the redirect URI for installed in a web application.
I'd recommend you to update your code to use the newer Drive API, which also includes a complete ASP.NET sample application and tutorial:
https://developers.google.com/drive/examples/dotnet
Can anyone provide me with a .NET (C# / VB) sample of how to get all mailboxes that I have access to ?
I have only been able to get my OWN mailbox via EWS - not ALL THE OTHER mailboxes that I also have access to through Outlook.
I don't have the names nor the id's of these mailboxes but isn't it possible to retrieve ALL mailboxes - including my own - that I am allowed to see - just as I can in Outlook ?
I am using Autodiscover to get my mailbox like this: service.AutodiscoverUrl("xxxx#ee.dd") - this will perhaps only get my own mailbox and not all the rest?
Please help !?
The way I got around this was to define the group mailbox in question as a "mailbox" object and then obtain the FolderID for the particular folder.
Define mailbox object
Mailbox gpmailbox = new Mailbox("mailbox#yourdomainname.com");
Get the FolderID (in this case, the Inbox)
FolderId gpInbox = new FolderId(WellKnownFolderName.Inbox, gpmailbox);
Use FolderID in your normal code (in this case I'm obtaining 100 messages)
ItemView view = new ItemView(100);
FindItemsResults<Item> results = hookToServer.FindItems(new FolderId(WellKnownFolderName.Inbox, gpmailbox), view);
The key is to grab the FolderID of the folder you need. Hope this helps.
Edit: I also failed to note that my object "hookToServer" is simply the ExchangeService object. Here's how I defined it:
ExchangeService hookToServer = new ExchangeService(ExchangeVersion.Exchange2010_SP1);
hookToServer.UseDefaultCredentials = true;
hookToServer.Url = new Uri("TheExchangeServer")
I also used this as reference:
EWS 2007 Group Mailbox Guide
You can do this by Using Autodiscover to get user settings, this is a completely separate service to the one with the AutodiscoverUrl method.
The setting name you need is AlternateMailboxes, this will give a collection of all the 'other' mailboxes you have access to. You might then add the user's default mailbox to get a complete list.
In c#:
using Microsoft.Exchange.WebServices.Autodiscover; // from nuget package "Microsoft.Exchange.WebServices"
internal List<string> GetAccessibleMailboxes()
{
AutodiscoverService autodiscoverService = new AutodiscoverService("outlook.office365.com");
autodiscoverService.Credentials = networkCredential;
var userSmtpAddress = networkCredential.UserName;
GetUserSettingsResponse userresponse = autodiscoverService.GetUserSettings(
userSmtpAddress,
UserSettingName.AlternateMailboxes);
var alternateMailboxCollection = (AlternateMailboxCollection)userresponse.Settings[UserSettingName.AlternateMailboxes];
var smtpAddressList = alternateMailboxCollection.Entries.ToList().Select(a => a.SmtpAddress).ToList();
smtpAddressList.Add(userSmtpAddress);
return smtpAddressList;
}
I am using Facebook C# SDK on my site, and is trying to access the cookie made by Facebook when the user has chosen to use Facebook as login, but I am getting the following error:
(OAuthException) An active access token must be used to query
information about the current user.
Here is the code I am using:
var client = new FacebookClient([App ID], [App Secret]);
dynamic me = client.Get("me");
string firstName = me.first_name;
Response.Write(firstName);
What am i doing wrong?
Thanks in advance
You need to authorize first before trying to access the user. This does the necessary redirects and plumbing to have Facebook set the cookie.
var auth = new CanvasAuthorizer { Permissions = new string[] {"user_about_me"} };
if (auth.Authorize()) {
var client = new FacebookClient([App ID], [App Secret]);
dynamic me = client.Get("me");
string firstName = me.first_name;
Response.Write(firstName);
}