1
votes

I have created this HTTP trigger azure function, which contains the code(below) to upload a video to YouTube automatically. Source: (https://developers.google.com/youtube/v3/docs/videos/insert).

I also created the Client_Id and Client_secret using Google Console API and stored that data in the client_secrets.json file. (E.g https://github.com/youtube/api-samples/blob/master/dotnet/client_secrets.json)

I try to run the function locally, pasting this: http://localhost:7071/api/Function1 in a browser, I am getting the following error:

400, That's an error. Error: redirect_rui_mismatch The redirect URI in the request, http://localhost58085/authorize/, does not match the ones authorized for the OAuth client. To update the authorized redirect URIs, visit. http://consolse.Developers.google.com/apis/credentials.

I am not sure what I am doing wrong, and I don't know what the URL I should put in for "Authorized redirect URIs"

Code:

using System;
using System.IO;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using Google.Apis.Auth.OAuth2;
using Google.Apis.Upload;
using Google.Apis.YouTube.v3.Data;
using System.Reflection;
using Google.Apis.YouTube.v3;
using Google.Apis.Services;
using System.Threading;

namespace UploadVideo
{
    public static class Function1
    {
        [FunctionName("Function1")]
        public static async Task<IActionResult> Run(
            [HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req,
            ILogger log)
        {
            log.LogInformation("C# HTTP trigger function processed a request.");

            log.LogInformation("YouTube Data API: Upload Video");
            log.LogInformation("==============================");

            try
            {
                await Run();
            }
            catch (AggregateException ex)
            {
                foreach (var e in ex.InnerExceptions)
                {
                    log.LogInformation("Error: " + e.Message);
                }
            }

            return new OkObjectResult($"Video Processed..");

        }

        private static async Task Run()
        {
            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 an application to upload files to the
                    // authenticated user's YouTube channel, but doesn't allow other types of access.
                    new[] { YouTubeService.Scope.YoutubeUpload },
                    "user",
                    CancellationToken.None
                );
            }

            var youtubeService = new YouTubeService(new BaseClientService.Initializer()
            {
                HttpClientInitializer = credential,
                ApplicationName = Assembly.GetExecutingAssembly().GetName().Name
            });

            var video = new Video();
            video.Snippet = new VideoSnippet();
            video.Snippet.Title = "Default Video Title";
            video.Snippet.Description = "Default Video Description";
            video.Snippet.Tags = new string[] { "tag1", "tag2" };
            video.Snippet.CategoryId = "22"; // See https://developers.google.com/youtube/v3/docs/videoCategories/list
            video.Status = new VideoStatus();
            video.Status.PrivacyStatus = "unlisted"; // or "private" or "public"
            var filePath = @"C:\Users\Peter\Desktop\audio\Test.mp4"; // Replace with path to actual movie file.

            using (var fileStream = new FileStream(filePath, FileMode.Open))
            {
                var videosInsertRequest = youtubeService.Videos.Insert(video, "snippet,status", fileStream, "video/*");
                videosInsertRequest.ProgressChanged += videosInsertRequest_ProgressChanged;
                videosInsertRequest.ResponseReceived += videosInsertRequest_ResponseReceived;

                await videosInsertRequest.UploadAsync();
            }
        }

        private static void videosInsertRequest_ProgressChanged(Google.Apis.Upload.IUploadProgress progress)
        {
            switch (progress.Status)
            {
                case UploadStatus.Uploading:
                    Console.WriteLine("{0} bytes sent.", progress.BytesSent);
                    break;

                case UploadStatus.Failed:
                    Console.WriteLine("An error prevented the upload from completing.\n{0}", progress.Exception);
                    break;
            }
        }

        private static void videosInsertRequest_ResponseReceived(Video video)
        {
            Console.WriteLine("Video id '{0}' was successfully uploaded.", video.Id);
        }
    }
}
2

2 Answers

1
votes

The way Oauth2 works is that a user is presented with a consent screen

Do you want to grant Peters awesome application access to your YouTube account.

If the user accepts this then an Authorization code is returned to your application at the point of the redirect uri

http://localhost:7071/api/Function1

This is the file in your application that is able to handle the authorization handshake. This redirect uri must be registered in the Google developer console it helps to ensure that no one trys to hijack your authorization call and send it over to their site and then they will have access to the users data.

how to add redirect uri

Under credentials find the one you are looking for

enter image description here

Click the pencil icon

enter image description here

Note

Please remember that GoogleWebAuthorizationBroker.AuthorizeAsync is used for installed applications its going to open the browser consent window on the server if you try to put this up as a function. you need to do something more like this for a web application Asp.net mvc I cant claim to know a lot about azure functions but if there anything like cloud functions i dont think they have the ability to display a web browser page to your user. I dont think you can authenticate a user with Oauth2 from an azure function.

1
votes

After registering your application and creating your OAuth Client ID from:

https://console.developers.google.com/

Go to the Credentials tab, under the OAuth 2.0 Client IDs section, click the pencil Icon to edit your details, on the screen you get scroll down to Authorized redirect URIs section, click the 'ADD URI' button and enter 'http://localhost/authorize/' in the text-box and click the 'SAVE' button and run your application again.

I hope that helps cause that't how I solved the problem.