upload video to youtube in .net - youtube-api

I need to upload a video in .NET
I use your client library. And when I receive code at my callback url, I need to change this code for token.
How can I do this? I didn't find any information about this.
And then, where should I put this token, uploading a video?
Thanks

Just like other quickstart using Youtube API, you must also follow the steps on how to obtain your client_secret.json that contains your token_uri:
Use this wizard to create or select a project in the Google Developers Console and automatically turn on the API. Click Continue,
then Go to credentials.
On the Add credentials to your project page, click the Cancel button.
At the top of the page, select the OAuth consent screen tab. Select an Email address, enter a Product name if not already set, and click
the Save button.
Select the Credentials tab, click the Create credentials button and select OAuth client ID.
Select the application type Other, enter the name "YouTube Data API Quickstart", and click the Create button.
Click OK to dismiss the resulting dialog.
Click the download icon (Donwload JSON) button to the right of the client ID.
Move the downloaded file to your working directory and rename it client_secret.json.
client_secret.json
{"installed":{"client_id":"837380381682-kthu0nva0f5tqli35o6hk4jiv0p9mh3s.apps.googleusercontent.com","project_id":"sureness-1534400441179","auth_uri":"https://accounts.google.com/o/oauth2/auth","token_uri":"https://www.googleapis.com/oauth2/v3/token","auth_provider_x509_cert_url":"https://www.googleapis.com/oauth2/v1/certs","client_secret":"n-5X4ssSnqw9JXFOrLAl1J1y","redirect_uris":["urn:ietf:wg:oauth:2.0:oob","http://localhost"]}}
This is a code snippet from .Net Code Sample where client_secrets.json was implemented:
UserCredential credential;
using (var stream = new FileStream("client_secrets.json", FileMode.Open, FileAccess.Read))
{
credential = await GoogleWebAuthorizationBroker.AuthorizeAsync(
GoogleClientSecrets.Load(stream).Secrets,
// This OAuth 2.0 access scope allows for full read/write access to the
// authenticated user's account.
new[] { YouTubeService.Scope.Youtube },
"user",
CancellationToken.None,
new FileDataStore(this.GetType().ToString())
);
}

Related

Using authorized YouTube APIs with the new Google Identity Services - How do I select an account?

I currently still use GAPI for a project that accesses the YouTube Data API with endpoints that require authorization.
Very briefly, this is the current implementation:
User clicks "Log in with Google" in the frontend
User can select his YouTube channel (this can either be the main account or any other account where the user is owner, e.g. brand accounts)
Google returns the code, code is sent to backend, backend exchanges the code for a refresh token and the refresh token is stored for that specific YouTube account.
From then on, authorized requests can be made for that account.
Now GAPI is being deprecated in place of Google Identity it separates authentication from authorization.
My problem is: I can only select the main Google Account during both authentication and authorization. I cannot see brand accounts or others channels I am the owner of. However I need to be able to select any of the YouTube accounts.
With GAPI the page for account selection shows "Select an account or brand account" - with Google Identity Services it is just "choose an account".
So now my theory is that I might be able to retrieve and store the refresh token for the main Google Account and then access all YouTube accounts connected to it.
Is this correct?
If it is:
When Google wanted to make login more fine granular, not being able to select only a limited number of YouTube accounts seems like a downgrade. Is there any way to counteract this?
How do I know what YouTube accounts are linked to the main Google Account? It does not help to have access to all accounts, when I don't know which they are.
If it is not:
How else can I select a specific YouTube account?
Edit:
Code
Regarding the implementation in the frontend: I use React with #react-oauth/google. You can find a preview of that hosted here which can be cloned from here.
Basically the idea would be to let a user log in to the application using the ID Token flow, which corresponds to the button on the left on the preview page.
A logged-in user could then grant permission to any of their YouTube accounts, which would correspond to the "Authorization" button on the right.
To reproduce the problem, create a second YouTube account with your main Google Account. The goal would be to find any way to grant permission to query that account using the YouTube Data API.
When trying to build a minimal example, I decided to ditch react and the third party library and use the plain gsi library:
<!DOCTYPE html>
<html>
<head>
<script
src="https://accounts.google.com/gsi/client"
onload="initClient()"
async
defer
></script>
</head>
<body>
<script>
var client;
var access_token;
function initClient() {
client = google.accounts.oauth2.initTokenClient({
client_id:
"<your-client-id>",
scope: "https://www.googleapis.com/auth/youtube.readonly",
callback: (tokenResponse) => {
access_token = tokenResponse.access_token;
},
});
}
function getToken() {
client.requestAccessToken();
}
function revokeToken() {
google.accounts.oauth2.revoke(access_token, () => {
console.log("access token revoked");
});
}
</script>
<h1>Google Identity Services Authorization Token model</h1>
<button onclick="getToken();">Get access token</button><br/><br />
<button onclick="revokeToken();">Revoke token</button>
</body>
</html>
When I removed the YouTube scope I could not see the YouTube accounts. I then checked the request I made with #react-oauth/google and it turned out that it did not contain the scope in the request it made.
This does not seem to be a problem in #react-oauth/google but in my application.
Summary:
Make sure to pass the YouTube scope if you want to see YouTube accounts
Check the request that is actually being made in the dev tools

"Error 403: access_denied" when usign Google OAuth

I am trying to understand the basic logics for receiving GMail emails with Google OAuth. I see this document Authorizing Your App with Gmail
Now I follow the instructions in Setting Up POP3 Importing with OAuth via Google to setup POP3 with Google OAuth.
I login one Google account(Account1) and then in Google Cloud, create the Google App and OAuth Client ID.
Then I start connect to GMail account(Account2) with the web application(WHMCS). When connecting, it asks me to choose an account that create the app, so I choose Account1. But get the following error:
Error 403: access_denied
The developer hasn’t given you access to this app.
Thus I am a bit confused. Since Account1 is used to create the app and OAuth Client ID, it should be able to access the app when I choose Account1, but the app will not be able to access the data in Account2. Or does the App in the error message means Gmail, not the app I created in Google Cloud?
Should I use Account2 to create the app for receiving emails in Account2? If yes, then for each Gmail account, should I create a separate app accordingly?
Update
Now I try to do as follows:
Use Account3(The admin of Google Workspace) to create the Cloud Project, Consent Window, Client ID, etc.
Then when connecting from WHMCS on our domain datanumen.com, it asks me to choose the account, I choose Account3, and then see a new window as below:
I then select "Allow" button, but then see the following error:
Connection unsuccessful. Please close this window and try again.
Update
I try several times. And find the first time will be successful. I forget enable POP3 in my Gmail account. After enabling it, everything is fine.
I am a bit confused as to what you are trying to do here.
You created a project on Google cloud console and created client id and client secret for the authorization of your project.
All this does is create a project that will be allowed to use Oauth2 to request authorization of a user to access their data.
If I understand what WHMCS is trying to do. Its going to let you use your client id and client secret to request access of a user to access their data.
So when it asks you to authorize a user this is the user whos data you want access to. That user must be added as a test user over on Google cloud console for the project that you created.
The project you create on google cloud console is still in the testing phase. Each user you want to allow to test your application must be added as a test user. Other wise only the owner of the project can test the applicaiton.
To fix this issue for me was this simple:
Go to https://console.developers.google.com/
open the project in question.
Click "OAuth consent screen" on the left.
Under "Test users" there is a button called "+ ADD USERS"
Type the email of the account you will be testing with, press enter, then click save.
It should work now
It seems like they updated this recently because last year I did not have to do this.
workspace
The issue you may be having is that if you created this project on a workspace account then i suspect only workspace domain users are going to be able to authorize it. It cant be authorized by someone on the standard google domain. So try with a workspace domain user. The same may go the other way I have never tried tbh. I tend to keep workspace within its domain.

IdentityServer4: How to show external providers consent screen?

Just recently starting using IdentityServer4 (IS4) playing around with samples and so on.
I have a setup where run IS4 (using the included sample UI MVC) configured with Google as an external provider. I also have an API setup, as well as a client (MVC web app). When authenticating, and the user clicks "Google" in the "External Login" section, he/she is redirected to Google as expected. However, after supplying the username and password, I expected to the see Google consent screen, but instead I am redirected back to the consent screen in IS4. Why is that? Should the end user not give consent that his/her Google profile information is being accessed, on a page which clearly is from Google (i.e. HTTPS and Googles certificate)?
I acknowledge that since I am also requiring consent from the user to access my API I might end up with 2 consent screens (one for profile info from Google, and one for API access from my own IS4 configuration), but if I did not have an API in my setup and simply wanted to use IS4 in a federated setup to provide ID tokens, I would not have a need for the consent of my own API and thus would expect only to see the consent screen from my external providers (e.g. Google, Facebook, Twitter, etc.).
I have my external provider configured like this:
services.AddAuthentication()
.AddGoogle("Google", options =>
{
options.ClientId = "<my client id>";
options.ClientSecret = "<my client secret>";
options.SignInScheme = IdentityServerConstants.ExternalCookieAuthenticationScheme;
});
Could someone please enlighten me :-)
Thanks
From Google' help:
To set up your project's consent screen and request verification:
Go to the Google API Console OAuth consent screen page.
Add required information like a product name and support email address.
Click Add Scope.
On the dialog that appears, select the scopes your project uses. Sensitive scopes display a lock icon next to the API name.
To select scopes for registration, you need to enable the API, like Drive or Gmail, from APIs & Services > API Library.
You must select all scopes used by the project.
When you're finished adding details to the OAuth consent screen, click Submit for verification.
A Verification required window displays.
Add scopes justification, a contact email address, and any other information that can help the team with verification, then click Submit.
Note: The consent screen
settings within the console are set at the project level, so the
information that you specify on the Consent screen page applies across
the entire project.
So, what you need is to disable consent for your client in IdSrv and enable it in Google.
Additionally, as described in this answer,
By design, the consent screen is not shown in the scenario with account selection and profile/email scopes only requested..., since the account selection UI already shows the email and profile (name/picture) information that will be shared with the app.
As added by #Mike Wilcox:
When including a sensitive/restricted scope, if not verified for the scopes added, you will see a not verified screen during consent oauth flow. You can pass through by clicking advanced - > go to [app_name] (unsafe)
There is a playground: https://developers.google.com/oauthplayground/ where you can test this out.Click on the settings icon in the top right and then check the "Use your own OAuth Credentials" box to then enter your app creds. You can add scopes and test out there.
You don't have control when you redirect to external idp since it is a delegated authentication. I don't know how Google have implemented their OAuth flows but the following might be reasons as to why consent screen is not shown:
You are not requesting any scopes that require user consent
The user already gave consent to access to his/her info to your client (you should be able to check this in Google account pages)
Your client is configured to bypass consent screens (this is possible in IDS4 by setting RequireConsent flag to false, but I would doubt you can do this in Google as a 3rd party OAuth client)

Is it possible to be able to correctly select any available Google account to use when using authorisation via the JS client library for Drive?

I've got an existing Google Drive enabled application that's using the Google Java client library and server flow auth.
If you're not logged into the application and navigate to the URL AND you have logged into more than one google account on that browser (only one personal Google account is possible, any additional ones have to be Google business accounts) the OAuth callback offers the options to select which Google Account to use.
However, whilst testing a switch to using the JavaScript client library I'm not able to activate the multiple account selection screen using gapi.auth.authorize. Is it possible to handle multiple accounts using the JS library?
Update : I tried with the immediate parameter false. I can log in as long as I don't change account in the popup. If I do change account, I get to:
https://accounts.google.com/o/oauth2/auth?client_id=433863057149.apps.googleusercontent.com&scope=https://www.googleapis.com/auth/drive.file+https://www.googleapis.com/auth/drive.install+https://www.googleapis.com/auth/userinfo.email+https://www.googleapis.com/auth/userinfo.profile&immediate=false&redirect_uri=postmessage&origin=https://drivedrawio.appspot.com&proxy=oauth2relay593063763&response_type=token&state=701344514&authuser=1
in a new tab and nothing happens. I've made a video to demonstrate.
Update 2 : This bug against the JS client library for the need for double selection of mulitple account has been accepted.
You are not getting the multi user selection screen because of the following parameter: authuser=0
This automatically selects the first account you are signed-in with (authuser=1 would select the second etc...).
It's currently not possible to remove that param using the client library because the client library sets it automatically to 0 (this is why it claims not to handle multi-accounts) if there is no value so one way is to override it to -1 for example, this will show the multi-account chooser. Then you could also ask to access the user's profile or email at the same time you ask access to other APIs and fetch either the email of the user or its ID. Then on subsequent auth you can specify the user_id param which wil bypass the user-selection screen.
So in practice, first authorize like this:
gapi.auth.authorize({client_id: <Your Client ID>,
scope: 'https://www.googleapis.com/auth/drive openid', // That requires access to Google Drive and to the UserInfo API
authuser: -1});
The only problem with the above is that the auto-refresh of the client library will not work because every auth will by blocked at the multi-account selection screen.
The trick is to get the ID of the user using the UserInfo API, save that ID in a session cookie and use it on subsequent auth like that:
gapi.auth.authorize({client_id: <Your Client ID>,
scope: 'https://www.googleapis.com/auth/drive openid',
user_id: <The User ID>,
authuser: -1});
Specifying the User's ID will make sure the multi-account chooser is bypass and will allow the auto-refresh of the token from the client lib to work again.
For reference, other URL param that impact the User flow are:
user_id: similar than authuser (bypasses the multi-account selection screen) but you can use email address (e.g. bob#gmail.com) or the User ID you get from our Open ID Connect endpoint/Google+ API/UserInfo API
approval_prompt: default is auto, can be set to force to make sure that the approval/grant screen gets shown. This makes sure that the gant screen is not bypassed on subsequent auth (after first time).
immediate: immediate is a bit tricky, when set to true it will bypass the grant screen (kinda like approval_prompt=auto) if the user already granted approval previously, but if the user has not granted approval previously you will get redirected with an error: error=immediate_failed. If set to false it won't add special behavior and therefore fallback on the behavior setup by the approval_prompt value.
Note: immediate=true and approval_prompt=force is an invalid combination.
I think the client library is using the immediate param so that if he gets the error=immediate_failed it will restart an auth flow without the authuser param, but that's only speculations :)
The OAuth grant access page is only shown when not in immediate mode, does it work as expected if you set the immediate parameter to false?
According to http://code.google.com/p/google-api-javascript-client/issues/detail?id=11
multi-login isn't supported by the Javascript client
Pay attention to authuser parameter. Set this to "2" for example and you will be prompted for login even if you are authenticated already.

Open Graph Beta: Add Data to Profile URL

In the new Open Graph Beta Auth Dialog does the "Add Data to Profile URL" essentially serve as the callback URL where Facebook will send the user after they click the "Add to My Timeline" button?
In a related question, will clicking the "Add to My Timeline" button in the new auth process in itself generate posting an item to the new Timeline page for the user?
Since these new features are in beta, we're not sure what to expect.
Have a look at:
https://developers.facebook.com/docs/beta/authentication/#add-data
If configured, Reports and stories on Timeline will have a menu option that lets the friends of your app's users click "add to my timeline" to install your app. Note that the screenshots in the docs are somewhat out of date and should say "Add to Timeline".
When a user clicks on "Add To My Timeline", whenever your app post an Open Graph Action for the user (e.g. Bill listened to Nirvana), it will add it to the timeline if you have Aggregation for that action (e.g. Music I Listen To).

Resources