Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 9001025
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: June 16, 20262026-06-16T00:22:58+00:00 2026-06-16T00:22:58+00:00

I’m having an issue implementing custom OAuth2Client for google using DotNetOpenAuth and MVC4. I’ve

  • 0

I’m having an issue implementing custom OAuth2Client for google using DotNetOpenAuth and MVC4.

I’ve got to the point where I can successfully make the authorization request to the google endpoint
https://accounts.google.com/o/oauth2/auth

and Google asks if the user will allow my application access to their account. All good so far. When the user clicks ‘OK’, google then calls my callback URL as expected.

The problem is when I call the VerifyAuthentication method on the OAuthWebSecurity class (Microsoft.Web.WebPages.OAuth)

var authenticationResult = OAuthWebSecurity.VerifyAuthentication(Url.Action("ExternalLoginCallback", new { ReturnUrl = returnUrl }));

It’s always returning an AuthenticationResult with IsSuccessful = false and Provider = ""

I’ve looked into the code for this, and the OAuthWebSecurity class tries to get the Provider name from

Request.QueryString["__provider__"]

but Google is not sending this information back in the querystring. The other provider I have implemented (LinkedIn) is sending the provider name back and it all works just fine.

I’m not sure what I can do from this point, apart from abandon the Microsoft.Web.WebPages.OAuth classes and just use DotNetOpenAuth without them, but I was hoping someone might have another solution I can try…

I’ve searched extensively, but can’t seem to find anything to help … I’ve found it really difficult even just to find examples of people doing the same thing, which has really surprised me.

Any help much appreciated!

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-06-16T00:22:59+00:00Added an answer on June 16, 2026 at 12:22 am

    Update: As Matt Johnson mentions below he has packaged up a solution to this which you can get from GitHub: https://github.com/mj1856/DotNetOpenAuth.GoogleOAuth2

    As he notes:
    DNOA and OAuthWebSecurity for ASP.Net MVC 4 ship with only an OpenId provider for Google. This is an OAuth2 client that you can use instead.

    IMPORTANT – If you are using ASP.Net MVC 5, this package is not applicable. You should use Microsoft.Owin.Security.Google instead. (It also ships with the MVC 5 starter templates in VS 2013.)


    I got round this in the end by catching the request when it comes in, and doing my own check to see which provider it has come from. Google allow you to send a parameter to the OAuth request called ‘state’, which they simply pass straight back to you when they make the callback, so I’m using this to pass the provider name for google, and I check for this in the absence of the "__provider__".

    something like this:

     public String GetProviderNameFromQueryString(NameValueCollection queryString)
        {
            var result = queryString["__provider__"];
    
            if (String.IsNullOrWhiteSpace(result))
            {
                result = queryString["state"];
            }
    
            return result;
        }
    

    I’ve then implemented a custom OAuth2Client for Google, and I manually call the VerifyAuthentication method on that myself, bypassing the Microsoft wrapper stuff.

     if (provider is GoogleCustomClient)
            {
                authenticationResult = ((GoogleCustomClient)provider).VerifyAuthentication(context, new Uri(String.Format("{0}/oauth/ExternalLoginCallback", context.Request.Url.GetLeftPart(UriPartial.Authority).ToString())));
            }
            else
            {
                authenticationResult = OAuthWebSecurity.VerifyAuthentication(returnUrl);
            } 
    

    This has allowed me to keep the stuff I already had in place for the other providers using the Microsoft wrappers.

    As requested by @1010100 1001010, here is my custom OAuth2Client for Google (NOTE: IT NEEDS SOME TIDYING! I HAVEN’T GOT ROUND TO TIDYING THE CODE UP YET. It does work though) :

    public class GoogleCustomClient : OAuth2Client
    {
        ILogger _logger;
    
        #region Constants and Fields
    
        /// <summary>
        /// The authorization endpoint.
        /// </summary>
        private const string AuthorizationEndpoint = "https://accounts.google.com/o/oauth2/auth";
    
        /// <summary>
        /// The token endpoint.
        /// </summary>
        private const string TokenEndpoint = "https://accounts.google.com/o/oauth2/token";
    
        /// <summary>
        /// The _app id.
        /// </summary>
        private readonly string _clientId;
    
        /// <summary>
        /// The _app secret.
        /// </summary>
        private readonly string _clientSecret;
    
        #endregion
    
    
        public GoogleCustomClient(string clientId, string clientSecret)
            : base("Google")
        {
            if (string.IsNullOrWhiteSpace(clientId)) throw new ArgumentNullException("clientId");
            if (string.IsNullOrWhiteSpace(clientSecret)) throw new ArgumentNullException("clientSecret");
    
            _logger = ObjectFactory.GetInstance<ILogger>();
    
            this._clientId = clientId;
            this._clientSecret = clientSecret;
        }
    
        protected override Uri GetServiceLoginUrl(Uri returnUrl)
        {
            StringBuilder serviceUrl = new StringBuilder();
    
            serviceUrl.AppendFormat("{0}?scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.email+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.profile", AuthorizationEndpoint);
            serviceUrl.Append("&state=google");
            serviceUrl.AppendFormat("&redirect_uri={0}", returnUrl.ToString());
            serviceUrl.Append("&response_type=code");
            serviceUrl.AppendFormat("&client_id={0}", _clientId);
    
            return new Uri(serviceUrl.ToString());
    
        }
    
        protected override IDictionary<string, string> GetUserData(string accessToken)
        {
            RestClient client = new RestClient("https://www.googleapis.com");
            var request = new RestRequest(String.Format("/oauth2/v1/userinfo?access_token={0}", accessToken), Method.GET);
            IDictionary<String, String> extraData = new Dictionary<String, String>();
    
            var response = client.Execute(request);
            if (null != response.ErrorException)
            {
                return null;
            }
            else
            {
                try
                {
                    var json = JObject.Parse(response.Content);
    
                    string firstName = (string)json["given_name"];
                    string lastName = (string)json["family_name"];
                    string emailAddress = (string)json["email"];
                    string id = (string)json["id"];
    
                    extraData = new Dictionary<String, String>
                    {
                        {"accesstoken", accessToken}, 
                        {"name", String.Format("{0} {1}", firstName, lastName)},
                        {"firstname", firstName},
                        {"lastname", lastName},
                        {"email", emailAddress},
                        {"id", id}                                           
                    };
                }
                catch(Exception ex)
                {
                    _logger.Error("Error requesting OAuth user data from Google", ex);
                    return null;
                }
                return extraData;
            }
    
        }
    
        protected override string QueryAccessToken(Uri returnUrl, string authorizationCode)
        {
            StringBuilder postData = new StringBuilder();
            postData.AppendFormat("client_id={0}", this._clientId);
            postData.AppendFormat("&redirect_uri={0}", HttpUtility.UrlEncode(returnUrl.ToString()));
            postData.AppendFormat("&client_secret={0}", this._clientSecret);
            postData.AppendFormat("&grant_type={0}", "authorization_code");
            postData.AppendFormat("&code={0}", authorizationCode);
    
    
            string response = "";
            string accessToken = "";
    
            var webRequest = (HttpWebRequest)WebRequest.Create(TokenEndpoint);
    
            webRequest.Method = "POST";
            webRequest.ContentType = "application/x-www-form-urlencoded";
    
            try
            {
    
                using (Stream s = webRequest.GetRequestStream())
                {
                    using (StreamWriter sw = new StreamWriter(s))
                        sw.Write(postData.ToString());
                }
    
                using (WebResponse webResponse = webRequest.GetResponse())
                {
                    using (StreamReader reader = new StreamReader(webResponse.GetResponseStream()))
                    {
                        response = reader.ReadToEnd();
                    }
                }
    
                var json = JObject.Parse(response);
                accessToken = (string)json["access_token"];
            }
            catch(Exception ex)
            {
                _logger.Error("Error requesting OAuth access token from Google", ex);
                return null;
            }
    
            return accessToken;
    
        }
    
        public override AuthenticationResult VerifyAuthentication(HttpContextBase context, Uri returnPageUrl)
        {
    
            string code = context.Request.QueryString["code"];
            if (string.IsNullOrEmpty(code))
            {
                return AuthenticationResult.Failed;
            }
    
            string accessToken = this.QueryAccessToken(returnPageUrl, code);
            if (accessToken == null)
            {
                return AuthenticationResult.Failed;
            }
    
            IDictionary<string, string> userData = this.GetUserData(accessToken);
            if (userData == null)
            {
                return AuthenticationResult.Failed;
            }
    
            string id = userData["id"];
            string name;
    
            // Some oAuth providers do not return value for the 'username' attribute. 
            // In that case, try the 'name' attribute. If it's still unavailable, fall back to 'id'
            if (!userData.TryGetValue("username", out name) && !userData.TryGetValue("name", out name))
            {
                name = id;
            }
    
            // add the access token to the user data dictionary just in case page developers want to use it
            userData["accesstoken"] = accessToken;
    
            return new AuthenticationResult(
                isSuccessful: true, provider: this.ProviderName, providerUserId: id, userName: name, extraData: userData);
        }
    
    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

link Im having trouble converting the html entites into html characters, (&# 8217;) i
We're building an app, our first using Rails 3, and we're having to build
I'm making a simple page using Google Maps API 3. My first. One marker
That's pretty much it. I'm using Nokogiri to scrape a web page what has
I have a jquery bug and I've been looking for hours now, I can't
I've got a string that has curly quotes in it. I'd like to replace
I am using the SimpleRSS gem to parse a WordPress RSS feed. The only
I'm using v2.0 of ClassTextile.php, with the following call: $testimonial_text = $textile->TextileRestricted($_POST['testimonial']); ... and
I'm parsing an RSS feed that has an &#8217; in it. SimpleXML turns this
We are using XSLT to translate a RIXML file to XML. Our RIXML contains

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.