Google API Calender v3 Event Insert via Service Account using Asp.Net MVC - asp.net-mvc

I have been trying to insert a Google calendar event via Google service account that was created for an app in my dev console, but I am continually getting a helpless 404 response back on the Execute method. In the overview of the dev console I can see that the app is getting requests because there are instances of errors on the calendar.events.insert method. There is no information on what is failing. I need this process to use the Service account process instead of OAuth2 so as to not require authentication each time a calendar event needs to be created.
I have set up the service account, given the app a name, have the p12 file referenced in the project. I've also, gone into a personal calendar and have shared with the service account email address. Also, beyond the scope of this ticket, I have created a secondary app, through an administration account and have granted domain wide access to the service account only to receive the same helpless 404 error that this is now giving.
Error Message: Google.Apis.Requests.RequestError
Not Found [404]
Errors [Message[Not Found] Location[ - ] Reason[notFound] Domain[global]
Any help identifying a disconnect or error would be greatly appreciated.
var URL = #"https://www.googleapis.com/calendar/v3/calendars/testcalendarID.com/events";
string serviceAccountEmail = "createdserviceaccountemailaq#developer.gserviceaccount.com";
var path = Path.Combine(HttpRuntime.AppDomainAppPath, "Files/myFile.p12");
var certificate = new X509Certificate2(path, "notasecret",
X509KeyStorageFlags.Exportable);
ServiceAccountCredential credential = new ServiceAccountCredential(
new ServiceAccountCredential.Initializer(serviceAccountEmail)
{
Scopes = new[] { Google.Apis.Calendar.v3.CalendarService.Scope.Calendar },
}.FromCertificate(certificate));
BaseClientService.Initializer initializer = new
BaseClientService.Initializer()
{
HttpClientInitializer = credential,
ApplicationName = "Test App"
};
Google.Apis.Calendar.v3.CalendarService calservice = new Google.Apis.Calendar.v3.CalendarService(initializer);
string timezone = System.TimeZone.CurrentTimeZone.StandardName;
var calendarEvent = new Event()
{
Reminders = new Event.RemindersData()
{
UseDefault = true
},
Summary = title,
Description = description,
Location = location,
Start = new EventDateTime()
{
//DateTimeRaw = "2014-12-24T10:00:00.000-07:00",
DateTime = startDateTime,
TimeZone = "America/Phoenix"
},
End = new EventDateTime()
{
//DateTimeRaw = "2014-12-24T11:00:00.000-08:00",
DateTime = endDateTime,
TimeZone = "America/Phoenix"
},
Attendees = new List<EventAttendee>()
{
new EventAttendee()
{
DisplayName = "Joe Shmo",
Email = "joeshmoemail#email.com",
Organizer = false,
Resource = false
}
}
};
var insertevent = calservice.Events.Insert(calendarEvent, URL);
var requestedInsert = insertevent.Execute();

I had the same problem. The solution was to add an email client, whose calendar event you want to send.
Credential = new ServiceAccountCredential(
new ServiceAccountCredential.Initializer(serviceAccountEmail)
{
Scopes = Scopes,
User = "example_client_email#gmail.com"
}.FromCertificate(certificate));

So I found out that for this to work, You need to make sure that you access the google.Admin account for referencing the service account Client ID of the app you created.
Another thing that helps is making sure the timezone is in the following format "America/Phoenix"
I have now successfully created events through the service account WITHOUT authentication.

Related

How do I access Outlook365 mailbox using impersonation using .NET?

I'm using this code:
var cca = ConfidentialClientApplicationBuilder
.Create(clientId)
.WithClientSecret(clientSecret)
.WithTenantId(tenantId)
.Build();
var ewsScopes = new [] { "https://outlook.office365.com/.default" };
var authResult = await cca.AcquireTokenForClient(ewsScopes).ExecuteAsync(cancellationToken);
var service = new ExchangeService
{
Credentials = new OAuthCredentials(authResult.AccessToken),
Url = new Uri("https://outlook.office365.com/EWS/Exchange.asmx"),
ImpersonatedUserId = new ImpersonatedUserId(ConnectingIdType.SmtpAddress, "mailbox#user.com"),
TraceListener = new TraceListener(),
TraceEnabled = true,
TraceFlags = TraceFlags.All
};
Folder inbox = Folder.Bind(service, WellKnownFolderName.Inbox);
The code throws a ServiceRequestException (403) on the last line, and trace logs contains the error:
x-ms-diagnostics: 2000008;reason="The token contains not enough scope to make this call.";error_category="invalid_grant"
Do I need to expand the ewsScopes? Or is this because I'm lacking the correct permissions in Azure? Which roles/permissions do I need?
Check the token your using in
Credentials = new OAuthCredentials(authResult.AccessToken),
in jwt.io
What you should see in the roles is
If you don't have that role it means your application registration isn't correct (eg you have added the delegate permission instead of Application permission which is a common mistake).

The given token is invalid error in EWS OAuth authentication when using personal account

I have to get the contacts from Exchange server from any account, so we have used the code from below link.
https://learn.microsoft.com/en-us/exchange/client-developer/exchange-web-services/how-to-authenticate-an-ews-application-by-using-oauth
But it is not working for personal accounts, which is working fine for our organization account. So I have used AadAuthorityAudience property instead of TenantId and changed the scope from EWS.AccessAsUser.All to others. Now authentication got success but getting "The given token is invalid" error while using the token in ExchangeService.
var pcaOptions = new PublicClientApplicationOptions {
ClientId = "77xxxxxxxxxxx92324",
//TenantId = "7887xxxxxxxxxxxxx14",
RedirectUri = "https://login.live.com/oauth20_desktop.srf",
AadAuthorityAudience = AadAuthorityAudience.AzureAdAndPersonalMicrosoftAccount};
var pca = PublicClientApplicationBuilder.CreateWithApplicationOptions(pcaOptions).Build();
//var ewsScopes = new string[] { "https://outlook.office365.com/EWS.AccessAsUser.All" };
var ewsScopes = new string[] { "User.Read", "Contacts.ReadWrite.Shared" };
var authResult = await pca.AcquireTokenInteractive(ewsScopes).ExecuteAsync();
var ewsClient = new ExchangeService();
ewsClient.Url = new Uri("https://outlook.office365.com/EWS/Exchange.asmx");
//ewsClient.ImpersonatedUserId = new ImpersonatedUserId(ConnectingIdType.SmtpAddress, "araj#concord.net");
ewsClient.Credentials = new OAuthCredentials(authResult.AccessToken);
// Make an EWS call
var folders = ewsClient.FindFolders(WellKnownFolderName.MsgFolderRoot, new FolderView(10));
What am doing wrong here?
https://outlook.office365.com/EWS.AccessAsUser.All is the right scope to use. The scope is invalid for personal accounts since they're not supported by EWS.

Allow all domains when adding a user to Azure B2C using the Graph API

I am trying to add a user with the email ...#gmail.com to my B2C directory via the Graph API (C#). I get this as a response:
The domain portion of the userPrincipalName property is invalid. You
must use one of the verified domain names in your organization.
This system needs to allow for users of any email domain to sign in. The users need to log in to a website, not have access to the Azure Portal.
Is there a way to accomplish this without manually adding every domain?
Code for adding user via Graph API:
var confidentialClientApplication = ConfidentialClientApplicationBuilder
.Create(clientId)
.WithTenantId(tenantId)
.WithClientSecret(clientSecret)
.Build();
var authProvider = new ClientCredentialProvider(confidentialClientApplication);
var graphClient = new GraphServiceClient(authProvider);
var user = new User
{
AccountEnabled = true,
DisplayName = emailAddress,
MailNickname = emailAddress.Split('#').FirstOrDefault(),
UserPrincipalName = emailAddress,
PasswordProfile = new PasswordProfile
{
ForceChangePasswordNextSignIn = true,
Password = tempPassword
}
};
If you're trying to create local B2C (not AAD) accounts try setting the identities property in your request but not the upn. This last should be auto-generated. Also password expirations must be disabled, and force change password at next sign-in must also be disabled.
I had to add following packages:
<PackageReference Include="Microsoft.Graph" Version="4.0.0-preview.7" />
<PackageReference Include="Microsoft.Graph.Auth" Version="1.0.0-preview.7" />
Then:
var confidentialClientApplication = ConfidentialClientApplicationBuilder
.Create(Settings.ClientId)
.WithTenantId(Settings.Tenant)
.WithClientSecret(Settings.ClientSecret)
.Build();
var authProvider = new ClientCredentialProvider(confidentialClientApplication);
var graphClient = new GraphServiceClient(authProvider);
var user = new User
{
AccountEnabled = true,
GivenName = "Name",
Surname = "Surname",
DisplayName = "Name Surname",
PasswordProfile = new PasswordProfile
{
ForceChangePasswordNextSignIn = false,
Password = "pass.123",
},
PasswordPolicies = "DisablePasswordExpiration",
Identities = new List<ObjectIdentity>
{
new ObjectIdentity()
{
SignInType = "emailAddress",
Issuer = Settings.Tenant,
IssuerAssignedId = "sample#sample.com"
}
}
};
await graphClient.Users.Request().AddAsync(user);
Make sure to add permission to create users in Azure portal.

Microsoft graph calling/communication SDK not working with MediaSession

I am making calls to teams user using Graph Communication SDK with local machine.I am using ngork for making local machine endpoints public. I can make call to teams user without using MediaSession but when I use Media Session call is not reaching to teams user and it is not giving any error.Need help to find out issue.I am referring examples from this doc- https://github.com/microsoftgraph/microsoft-graph-comms-samples/tree/master/Samples/V1.0Samples/LocalMediaSamples
Working Call:
var mediaToPrefetch = new List<MediaInfo>();
var call = new Call()
{
Targets = new[] { target },
MediaConfig = new ServiceHostedMediaConfig { PreFetchMedia = mediaToPrefetch },
RequestedModalities = new List<Modality> { Modality.Audio, Modality.Video, Modality.VideoBasedScreenSharing },
TenantId = joinCallBody.TenantId,
};
var statefulCall = await this.Client.Calls().AddAsync(call, scenarioId: scenarioId).ConfigureAwait(false);
Non Working Call:
var mediaSession=this.CreateMediaSession();
var mediaToPrefetch = new List<MediaInfo>();
var call = new Call()
{
Targets = new[] { target },
MediaConfig = new ServiceHostedMediaConfig { PreFetchMedia = mediaToPrefetch },
RequestedModalities = new List<Modality> { Modality.Audio, Modality.Video, Modality.VideoBasedScreenSharing },
TenantId = joinCallBody.TenantId,
};
var statefulCall = await this.Client.Calls().AddAsync(call, scenarioId: scenarioId,mediaSession:mediaSession).ConfigureAwait(false);
Those samples refer to application-hosted media bots: https://learn.microsoft.com/en-us/microsoftteams/platform/bots/calls-and-meetings/requirements-considerations-application-hosted-media-bots
Did you follow all the steps to register the bot app? https://github.com/microsoftgraph/microsoft-graph-comms-samples/tree/master/Samples/V1.0Samples/LocalMediaSamples/PolicyRecordingBot#bot-registration
You need to explicitly add permissions to access media, and later to grant by an administrator of the azure account.
If you did all that, could you please share what kind of exception/error are you getting?

Always "This transaction is invalid..." on live PayPal for ASP.NET

I am developing web application on ASP.NET. In application users can purchase article for money.
For work with PayPal I using PayPal Merchant SDK for .NET package. Application work good with sandbox but with live display error: "This transaction is invalid". Please return to the recipient's website to complete your transaction using their regular checkout flow."
When user click on purchase button I execute code:
// only for live
var paypalConfig = new Dictionary<string, string> {
{"account1.applicationId", "<APP-LIVEID>"},
{"account1.apiUsername", "<username>"},
{"account1.apiPassword", "<pass>"},
{"account1.apiSignature", "<signature>"},
{"mode", "live"}};
try
{
var currency = CurrencyCodeType.USD;
var paymentItem = new PaymentDetailsItemType
{
Name = "item",
Amount = new BasicAmountType(currency, amount.ToString()),
ItemCategory = ItemCategoryType.DIGITAL,
};
var paymentItems = new List<PaymentDetailsItemType>();
paymentItems.Add(paymentItem);
var paymentDetail = new PaymentDetailsType();
paymentDetail.PaymentDetailsItem = paymentItems;
paymentDetail.PaymentAction = PaymentActionCodeType.SALE;
paymentDetail.OrderTotal = new BasicAmountType(currency, amount.ToString());
paymentDetail.SellerDetails = new SellerDetailsType {
PayPalAccountID= sellerEmail
};
var paymentDetails = new List<PaymentDetailsType>();
paymentDetails.Add(paymentDetail);
var ecDetails = new SetExpressCheckoutRequestDetailsType {
ReturnURL = returnUrl,
CancelURL = cancelUrl,
PaymentDetails = paymentDetails,
};
var request = new SetExpressCheckoutRequestType
{
Version = "104.0",
SetExpressCheckoutRequestDetails = ecDetails,
};
var wrapper = new SetExpressCheckoutReq
{
SetExpressCheckoutRequest = request
};
var service = new PayPalAPIInterfaceServiceService(paypalConfig);
var setECResponse = service.SetExpressCheckout(wrapper);
if (sandbox)
return "https://www.sandbox.paypal.com/cgi-bin/webscr?cmd=_express-checkout&token={0}".FormatWith(setECResponse.Token);
return "https://www.paypal.com/cgi-bin/webscr?cmd=_express-checkout&TOKEN={0}".FormatWith(setECResponse.Token);
}
// # Exception log
catch (System.Exception ex)
{
// Log the exception message
Console.WriteLine("Error Message : " + ex.Message);
}
After all I redirect user to url with received TOKEN.
For my application, registered on PayPal, I set in options only "Adaptive Payments > Basic Payments > Checkout, Send Money or Parallel Payments"
Why live paypal payments can not work? What is the reason?
Removed
ItemCategory = ItemCategoryType.DIGITAL,
and all work
From previous experiences this problem usually comes from having a "null" token because of some mistake in the "setExpressCheckout" request (where, in the express checkout flow, you ask paypal for a transaction token).
Basically, you ask paypal for a token so you can build the redirect URL, but you make some mistake and paypal gives you an error but no token, so you build the URL with no token (or a wrong one).
If you try to redirect the user to the checkout URL ( https://www.sandbox.paypal.com/cgi-bin/webscr?cmd=_express-checkout&token={...}&useraction={...}) with an empty token you will get this error.
Actually I'm trying to know of there can be other causes...

Resources