Service account authentication - google-calendar-api

I'm trying to create calendar event via PHP for one particular user - say developement#example.com.
I've created Service Account in Google Developers Console, got ClientID, E-mail address and private key. The authentication is done with code:
$client = new Google_Client();
if (isset($_SESSION['service_token'])) {
$client->setAccessToken($_SESSION['service_token']);
}
$cred = new Google_Auth_AssertionCredentials(
'somelongstring#developer.gserviceaccount.com.',
array('https://www.googleapis.com/auth/calendar','https://www.googleapis.com/auth/calendar.readonly'),
file_get_contents('p12 file'));
$client->setAssertionCredentials($cred);
if ($client->getAuth()->isAccessTokenExpired()) {
$client->getAuth()->refreshTokenWithAssertion($cred);
}
$_SESSION['service_token'] = $client->getAccessToken();
This type of authentication seems pretty OK. But all events are created as user with E-mail address somelongstring#developer.gserviceaccount.com instead of developement#example.com.
I've tried setting sub parameter:
$cred = new Google_Auth_AssertionCredentials(
....
$cred->sub = 'developement#example.com';
$client->setAssertionCredentials($cred);
But this piece of code throws exception:
Google_Auth_Exception: Error refreshing the OAuth2 token, message: '{ "error" : "access_denied", "error_description" : "Requested client not authorized." }'
And now I'm lost. Any advice?

OK, resolved ;-)
Problem was with developement on own domain.
As mentioned in other question and in Google SDK Guide I have to grant access for service account to all scopes I request access. I forgot to add read-only scope.

Related

when I use asmx service and SSRS report service I am getting "The request failed with http status 401: unauthorised"

I was trying to call report related service (asmx) from my asp.net web application by running locally.
Then an exception happened saying. The request failed with http status401:unauthorised.
In my analysis I understood the issue caused due to below code
SSRSWebService.ReportingService2005 rs = new SSRSWebService.ReportingService2005();
rs.Credentials = new MyReportServerCredentials().NetworkCredentials;
and
Uri reportUri = new Uri(ConfigurationManager.AppSettings["ReportServerManagement.ReportingService2005"]);
this.rptViewer.ServerReport.ReportServerCredentials = new MyReportServerCredentials();
In my detailed analysis I understood that the issue was because of the credential set up in serviceObject.credential OR ServerReport.ReportServerCredentials was wrong. This can be rectified in two different way either by setting credential to default with below code
rs.Credentials = System.Net.CredentialCache.DefaultCredentials;//"rs" is report object
Or locate below code and set up proper authenticated user credential in the code
public WindowsIdentity ImpersonationUser
{
get
{
// Use the default Windows user. Credentials will be
// provided by the NetworkCredentials property.
return null;
}
}
public ICredentials NetworkCredentials
{
get
{
// Read the user information from the Web.config file.
// By reading the information on demand instead of
// storing it, the credentials will not be stored in
// session, reducing the vulnerable surface area to the
// Web.config file, which can be secured with an ACL.
// User name
string userName =
<<AccurateUserName;>>
// Password
string password =
<<AccuratePassword;>>
// Domain
string domain = <<AccurateDomainName;>>
return new NetworkCredential(userName, password, domain);
}
}
In order to check whether which user has the access, we need to type service url ending with asmx (http:/MyServiceHostedServer/MyService.asmx) in a web browser. It will prompt a user name and password . Give our username as :Domain\Username and password.If we are able to see wsdl xml file then that user has the access.

Azure AD Application Add User to Active Directory using Client Credentials

I am trying to add a user to an application Active Directory but with little success. I am using the GraphServiceClient with.Net Core
The documentation here says I need these permissions
Azure AD Graph Client Beta Docs
Application Directory.ReadWrite.All
But I cannot find where in the Azure Portal I can assign this permission.
The code is above, the GraphServiceClient is in beta at the moment and this is not part of the API yet, so I am calling the request manually.
Below is my code for authentication, I am using my applications client secret which is set against the application in the AD. I can read directory data fine.
public async Task AuthenticateRequestAsync(HttpRequestMessage request)
{
try
{
if (null == _configuration)
{
throw new InvalidOperationException("Azure AD Configuration is not set");
}
var authContext = new AuthenticationContext(
$"{_configuration.Instance}/{_configuration.Domain}", false);
var credentials = new ClientCredential(_configuration.ClientId, _configuration.ClientSecret);
var authResult =
await authContext.AcquireTokenAsync("https://graph.microsoft.com/", credentials);
request.Headers.Add("Authorization", "Bearer " + authResult.AccessToken);
}
catch (Exception ex)
{
_logger.Error("Authentication Provider, unable to get token", ex);
}
}
Update - After checking with Rohit's advice, you can see I have the permissions set. But notice they are all in blue with the ticks next to them! I have changed and saved, you can see the save button is disabled. I have clicked Grant Permissions. Is this relevant?
But I cannot find where in the Azure Portal I can assign this
permission.
In Azure portal navigate to Azure Active Directory > App Registrations > Your specific app > Settings > Required Permissions
Click on Add and Select Microsoft Graph
Now, in the Application Permissions section, check "Read and write directory data"
Once you're done, do "Grant Permissions" for Admin consent, as this permission needs it.

Error:"invalid_grant", Description:"Invalid JWT: Token must be a short-lived token and in a reasonable timeframe", Uri:""

I am trying to access google-calendar with the help of google service account
but i got belloing error
An exception of type 'Google.Apis.Auth.OAuth2.Responses.TokenResponseException' occurred in Google.Apis.dll but was not handled in user code
The error I am getting: "invalid_grant", Description:"Invalid JWT: Token must be a short-lived token and in a reasonable timeframe", Uri:""
string credPath = "key path";
String serviceAccountEmail = xxxx#developer.gserviceaccount.com";
var certificate = new X509Certificate2(credPath, "notasecret", X509KeyStorageFlags.Exportable);
ServiceAccountCredential credential = new ServiceAccountCredential(
new ServiceAccountCredential.Initializer(serviceAccountEmail)
{
Scopes = new[] { CalendarService.Scope.CalendarReadonly,
CalendarService.Scope.Calendar}
}.FromCertificate(certificate));
// Create the service.
var service = new CalendarService(new BaseClientService.Initializer()
{
HttpClientInitializer = credential,
ApplicationName = "HRTool",
});
var events = service.Events.List("my calaender id").Execute();
Invalid grant
When you try to use a refresh token, the following returns you an invalid_grant error:
Your server's clock is not in sync with network time protocol - NTP.
The refresh token limit has been exceeded.
First, kindly check the synchronization problem with the server clock, see the poor synchronization of the computer's clock answer for additional information. Second, check handling of refresh token and the old tokens. Some flows include additional steps, such as using refresh tokens to acquire new access tokens. For detailed information about flows for various types of applications, see Google's OAuth 2.0 documentation.
Hope this helps!
If you are getting the error of "Invalid JWT Signature." and if you are using the P12 certificate then confirm the P12 is correct or not for the Client Key you have used.
If you are getting the error of "Invalid JWT Signature." This is the error caused by some other plugin which you just installed check. I solved by removing rank math plugin as after this plugin install the elementor update was not working.

X509Certificate2 Access denied error

EDIT: This is my final code after taking your(#DalmTo) advice:
public static AnalyticsService Authenticate()
{
string[] scopes = new string[] { AnalyticsService.Scope.Analytics,
AnalyticsService.Scope.AnalyticsManageUsers};
string keyFilePath = #"G:\PleskVhosts\mydomainname\httpdocs\App_Data\API Project-2f74017ed363.p12"; // found in developer console
string serviceAccountEmail = "myconsoleapiaccount#developer.gserviceaccount.com"; // found in developer console
var certificate = new X509Certificate2(keyFilePath, "notasecret", X509KeyStorageFlags.Exportable);
ServiceAccountCredential credential = new ServiceAccountCredential(new ServiceAccountCredential.Initializer(serviceAccountEmail) { Scopes = scopes }.FromCertificate(certificate));
AnalyticsService service = new AnalyticsService(new BaseClientService.Initializer()
{
HttpClientInitializer = credential,
ApplicationName = "myappname",
});
Thank you so much for the tutorial you linked me, I examined it carefully and your code was so much less work than trying to do it manually. I am aware of the tips you have given me, and I have necessary permissions for that account in my Google Analytics account. I followed your tutorial, and it works like a charm in my localhost, but when I publish my website, this is the current error I am getting this error:
{"Message":"Access is denied.\r\n","StackTrace":" at System.Security.Cryptography.X509Certificates.X509Store.Add(X509Certificate2 certificate)\r\n at Thunder.Main.Default.Authenticate()\r\n at Thunder.Main.Default.GetChartData()","ExceptionType":"System.Security.Cryptography.CryptographicException"}
I have contacted with my hosting provider, and they are telling me that they won't be making changes in IIS, I've added trust level full tag to the web.config, but I am still getting this error.I am currently working on it, but if you have any advices, please let me know. I will update here If I can come up with a solution. Thanks!
As mentioned above you need to configure IIS but as our case, some time you need to check the permission of the following folder:
C:\ProgramData\Microsoft\Crypto\RSA\MachineKeys
If you set X509KeyStorageFlags parameter it will create a key file in this folder. In my case there was a difference in permission of this folder. Pool account was not added in the mentioned folder.
You really are making things harder for yourself here. I am not sure whats wrong with your code. TBH I have never tried doing it manually because I use the client library
NuGet Package
PM> Install-Package Google.Apis.Analytics.v3
Authentication with a service account.
You need to send the full path to the key file or sometimes it complains. Ideally it should be out side of the web root but it needs to be someplace that the webserver has access to read it since you are using asp for this.
string[] scopes =
new string[] {
AnalyticsService.Scope.Analytics, // view and manage your Google Analytics data
AnalyticsService.Scope.AnalyticsManageUsers}; // View Google Analytics data
string keyFilePath = #"c:\file.p12" ; // found in developer console
string serviceAccountEmail = "xx#developer.gserviceaccount.com"; // found in developer console
//loading the Key file
var certificate = new X509Certificate2(keyFilePath, "notasecret", X509KeyStorageFlags.Exportable);
ServiceAccountCredential credential = new ServiceAccountCredential( new ServiceAccountCredential.Initializer(serviceAccountEmail)
{Scopes = scopes }.FromCertificate(certificate));
Creating Service
You pass the credential created above to the service. All of your requests will then go though the service.
AnalyticsService service = new AnalyticsService(new BaseClientService.Initializer()
{
HttpClientInitializer = credential,
ApplicationName = "Analytics API Sample",
});
Tips
For a service account to work with Google Analytics it must have access to your Google Analytics account. Go to the Google Analytics website admin section create a new user at the account level it must be the account level. Did I mention it wont work if it isn't the account level.
Code is taken from my tutorial series. Google Analtics with C# enjoy

DotNetOpenAuth Failing to work on Live Server

I worked on a sample application integrating OpenID into ASP.NET Web Forms. It works fine when hosted locally on my machine. However, when I uploaded the application to a live server, it started giving "Login Failed".
You can try a sample here: http://samples.bhaidar.net/openidsso
Any ideas?
Here is the source code that fails to process the OpenID response:
private void HandleOpenIdProviderResponse()
{
// Define a new instance of OpenIdRelyingParty class
using (var openid = new OpenIdRelyingParty())
{
// Get authentication response from OpenId Provider Create IAuthenticationResponse instance to be used
// to retreive the response from OP
var response = openid.GetResponse();
// No authentication request was sent
if (response == null) return;
switch (response.Status)
{
// If user was authenticated
case AuthenticationStatus.Authenticated:
// This is where you would look for any OpenID extension responses included
// in the authentication assertion.
var fetchResponse = response.GetExtension<FetchResponse>();
// Store the "Queried Fields"
Session["FetchResponse"] = fetchResponse;
// Use FormsAuthentication to tell ASP.NET that the user is now logged in,
// with the OpenID Claimed Identifier as their username.
FormsAuthentication.RedirectFromLoginPage(response.ClaimedIdentifier, false);
break;
// User has cancelled the OpenID Dance
case AuthenticationStatus.Canceled:
this.loginCanceledLabel.Visible = true;
break;
// Authentication failed
case AuthenticationStatus.Failed:
this.loginFailedLabel.Visible = true;
break;
}
}
As Andrew suggested, check the exception. In my case, my production server's time & date were off and it wouldn't authenticate because the ticket expired.
Turn on logging on your live server and inspect them for additional diagnostics. It's most likely a firewall or permissions problem on your server that prevents outbound HTTP requests.
You may also find it useful to look at the IAuthenticationResponse.Exception property when an authentication fails for clues.

Resources