Search code examples
c#asp.net-mvcgoogle-oauthgoogle-calendar-apigoogle-api-dotnet-client

How to solve redirect_uri_mismatch i ASP.NET MVC?


I have created ASP.NET MVC web application to integrate with google calendar API.

I have followed the documentation in Google sites. I have set up the project in Google Developer console as follows:

enter image description here

I have also downloaded the credentials files after creating the project but while using it i am getting uri_mismatch error every time.

enter image description here

How can this be solved?

My code for authorization is :

string jsonFile = HttpContext.Server.MapPath("~/credentials.json");

            UserCredential credential;

            using (var stream =
                new FileStream(jsonFile, FileMode.Open, FileAccess.Read))
            {
                // The file token.json stores the user's access and refresh tokens, and is created
                // automatically when the authorization flow completes for the first time.
                //string credPath = "token.json";
                string credPath = HttpContext.Server.MapPath("~/token");
                credential = GoogleWebAuthorizationBroker.AuthorizeAsync(
                    GoogleClientSecrets.Load(stream).Secrets,
                    Scopes,
                    "user",
                    CancellationToken.None,
                    new FileDataStore(credPath, true)).Result;
                Console.WriteLine("Credential file saved to: " + credPath);
            }

            // Create Google Calendar API service.
            var service = new CalendarService(new BaseClientService.Initializer()
            {
                HttpClientInitializer = credential,
                ApplicationName = ApplicationName,
            });

            // Define parameters of request.
            EventsResource.ListRequest request = service.Events.List("primary");
            request.TimeMin = DateTime.Now;
            request.ShowDeleted = false;
            request.SingleEvents = true;
            request.MaxResults = 10;
            request.OrderBy = EventsResource.ListRequest.OrderByEnum.StartTime;


Solution

  • The redirect uri you set in Google Developer console must exactly match where you are sending from and expecting the response to be returned to.

    I am going to assume that you are using the Google .net client library because your response says /authorize which is configured with in the library

    Solution for uri_mismatch

    in Google developer console add

    http://localhost:63972/authorize
    

    or

    http://127.0.0.1:63972/authorize
    

    but make sure that you have a static port set up in your IDE (visual studio) or you are going to have the same issue again.

    Tip web application vs installed application

    The code you have posted uses GoogleWebAuthorizationBroker.AuthorizeAsync which is designed for use with installed applications. When the authorization window opens it will open on the machine the code is running on. While you are in development this will work as its going to open on your dev machine but when you try to release this to the server its not going to work.

    You should be using GoogleAuthorizationCodeFlow for following this example Web applications (ASP.NET MVC)

    using System;
    using System.Web.Mvc;
    
    using Google.Apis.Auth.OAuth2;
    using Google.Apis.Auth.OAuth2.Flows;
    using Google.Apis.Auth.OAuth2.Mvc;
    using Google.Apis.Drive.v2;
    using Google.Apis.Util.Store;
    
    namespace Google.Apis.Sample.MVC4
    {
        public class AppFlowMetadata : FlowMetadata
        {
            private static readonly IAuthorizationCodeFlow flow =
                new GoogleAuthorizationCodeFlow(new GoogleAuthorizationCodeFlow.Initializer
                    {
                        ClientSecrets = new ClientSecrets
                        {
                            ClientId = "PUT_CLIENT_ID_HERE",
                            ClientSecret = "PUT_CLIENT_SECRET_HERE"
                        },
                        Scopes = new[] { DriveService.Scope.Drive },
                        DataStore = new FileDataStore("Drive.Api.Auth.Store")
                    });
    
            public override string GetUserId(Controller controller)
            {
                // In this sample we use the session to store the user identifiers.
                // That's not the best practice, because you should have a logic to identify
                // a user. You might want to use "OpenID Connect".
                // You can read more about the protocol in the following link:
                // https://developers.google.com/accounts/docs/OAuth2Login.
                var user = controller.Session["user"];
                if (user == null)
                {
                    user = Guid.NewGuid();
                    controller.Session["user"] = user;
                }
                return user.ToString();
    
            }
    
            public override IAuthorizationCodeFlow Flow
            {
                get { return flow; }
            }
        }
    }