Google drive OAuth2: encrypted use of TokenResponse file? - encryption

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"}

Related

Impersonate using json credentials file

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.

Azure KeyVault how to load X509Certificate? [duplicate]

This question already has answers here:
How to serialize and deserialize a PFX certificate in Azure Key Vault?
(5 answers)
Closed 6 years ago.
I uploaded a Certificate to Azure KeyVault and obtained "all" access to it using an application registered into the Active Directory. That all works fine. Now I need to load the obtained key into an X509Certificate to be able to use it as a client certificate for calling a 3rdparty legacy SOAP webservice. As far as I know I can only use a X509Certificate to call that webservice.
It does not matter if I upload it as a Key or Secret? I have tried both.
var clientId = "...."
var clientSecret = "...."
..
var token = authenticationContext.GetAccessToken(resource, adCredential);
var keyClient = new KeyVaultClient(new KeyVaultClient.AuthenticationCallback(token));
KeyBundle key = keyClient.GetKeyAsync("https://mycertifcates.vault.azure.net/keys/MyCertificate/123456789");
So far so good, I got a KeyBundle as a result and it seems like I can convert it to a Base64String, but whatever I try I end up with exceptions :(
1st attempt I tried:
var publicKey = Convert.ToBase64String(key.Key.N);
var cert = X509Certificate.FromBase64String(publicKey);
System.Security.Cryptography.CryptographicException {"Cannot find the requested object.\r\n"}
Ahhhh
2nd attempt, loading it into an RSACryptoServiceProvider, but what to do with that? Results into the same exception and I'm not even able to get the private key if I want to
var rsaCryptoProvider = new RSACryptoServiceProvider();
var rsaParameters = new RSAParameters()
{
Modulus = key.Key.N,
Exponent = key.Key.E
};
rsaCryptoProvider.ImportParameters(rsaParameters);
var cspBlob = rsaCryptoProvider.ExportCspBlob(false);
// what to do with the cspBlob ?
var publicKey = Convert.ToBase64String(cspBlob);
No private key as well, the public key is different. Ofcourse this does not work either.
3rd attempt
I uploaded it as a Secret Certificate ContentType using the management portal.
var secret = helper.GetSecret("https://myCertificate.vault.azure.net/secrets/MyCertificate/1234567890");
var value = secret.Value;
// Now I got the secret.. works flawless
// But it crash with the same exception at .Import
var exportedCertCollection = new X509Certificate2Collection();
exportedCertCollection.Import(Convert.FromBase64String(value));
var cert2 = exportedCertCollection.Cast<X509Certificate2>().Single(s => s.HasPrivateKey);
System.Security.Cryptography.CryptographicException {"Cannot find the
requested object.\r\n"}
Any suggestion is welcome.
I need the pfx including private key, looking at the tracelog
ystem.Net Information: 0 : [37880] SecureChannel#23107755 - Left with 1 client certificates to choose from.
System.Net Information: 0 : [37880] SecureChannel#23107755 - Trying to find a matching certificate in the certificate store.
System.Net Information: 0 : [37880] SecureChannel#23107755 - Locating the private key for the certificate: [Subject]
To answer my own question (I asked it too quickly I guess)
It turns out that this question was in fact a duplicate, but I did not understand it at first. The fact is that the Azure Management Portal is limited. For now uploading a certificate can only be done by using a powershell (or other code for that matter).
https://stackoverflow.com/a/34186811/578552
The 3rd attempt code works fine for the X509Certificate2
var secret = helper.GetSecret("https://myCertificate.vault.azure.net/secrets/MyCertificate/1234567890");
var exportedCertCollection = new X509Certificate2Collection();
exportedCertCollection.Import(Convert.FromBase64String(secret.Value));
var cert2 = exportedCertCollection.Cast<X509Certificate2>().Single(s => s.HasPrivateKey);

Expireing active registration link in asp.net

As a user register in my website, a registration link will send him. What i want is to expire this link after 48 hours. Is there any way to do that?
Thank you so much.
here is my codes:
In activate page:
string userID = Request.QueryString["userID"];
Guid gd = new Guid(userID);
Membership.UpdateUser(user);
In activate page:
MembershipUser user = Membership.CreateUser(TextBox_email.Text, TextBox_Pass.Text, TextBox_email.Text);
Roles.AddUserToRole(TextBox_email.Text, "Author");
user.IsApproved = false;
Membership.UpdateUser(user);
// StringBuilder bodyMsg = new StringBuilder();
Guid userID = (Guid)user.ProviderUserKey;
I guess this is all about special querystring/route parameters in your activation link
You can, for example :
store a link identifier and the date it has been issued in a datastore/database. Then check that a user link is no more than 48h old when a user accesses your site with it.
store a timestamp in the link itself (no need of a db), as well as a hashcode of the timestamp concatenated to a secret key of yours. When a user comes with a link, verify that the hashcode and the timestamp match, then verify that the timestamp is no more than 48h old

Redirecting From One Page to Another After Sending Login Credentials

While I'm logged into a web application 1, I would like to navigate to web application 2 without explicitly logging on manually.
In application 1 I have an OnClick that gathers up my current login credentials and attempts to POST them to applications 2:
long timestamp = DateTime.Now.Ticks;
string userName = currentUser.Credentials.UserName;
string accountName = currentUser.Account.Name;
string ssoUrl = AppUtil.SalesViewSsoUrl;
var ssoKey = new Guid(AppUtil.SalesViewHashKey);
// Build request
System.Net.WebRequest request = System.Net.WebRequest.Create(ssoUrl);
string postData = BuildPostString(userName, accountName, timestamp.ToString("x"), ssoKey);
byte[] postDataBytes = Encoding.Default.GetBytes(postData);
//Request.Headers.Add("SSOParams", postData);
//request.Method = "POST";
//request.ContentType = "application/x-www-form-urlencoded";
//request.ContentLength = postDataBytes.Length;/
//Stream sOut = request.GetRequestStream();
//sOut.Write(postDataBytes, 0, postDataBytes.Length);
//sOut.Flush();
//sOut.Close();
So, the problem here is that I remain on the same page. I can't figure out how to do that basic operation but stay on the newly logged-in application 2 page.
Is there any other way to send those parameters over without putting them in a query string? I want to avoid that.
Any assistance is appreciated.
To my knowledge you should use ASP.NET Web Config tool. You can also handcraft your code. This website has lots of tutorials on ASP.NET. It has some videos about the Authentication and Authorization, etc. in the Advanced ASP.NET section. Manzoor the trainer

Trying to get Facebook Cookie from codebehind, but is getting (OAuthException)

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);
}

Resources