Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Migrating Google OpenID to OpenID Connect: openid_id does not match

I have begun the process of Migrating from Google OpenID to the OpenID Connect with OAuth 2.0 following what is presented in the Documentation. I am able successfully complete the workflow of retrieving the openid_id and sub inside the id_token from the token endpoint, but when I do, the openid_id does not match the existing identifier we have in our system. Preventing me from mapping the existing user to the new ID and preventing the user from logging into our application (or possibly being allowed to log in as someone else). the id is of the correct format, but just doesn't match.

I have set the openid.realm parameter to our existing openid.realm as well as setting the redirect the same as suggested by the documentation. This is happening both locally and in our azure hosted environments. I am using the JWT.JsonWebToken to decode the id_token but I also verified that it was being decoded properly by using the web hosted decoder on google: JWT Decoder, and I came up with the same OpenID Identifier that did not match the one we currently have for that user. I should also note that I have tried adding the profile scope as well but that did not make any difference.

We are using DotNetOpenAuth.OpenId for our original system, so I don't think the problem lies there. I have examined the ClaimedIdentifier that is part of the response and it does match what we save in our system for openId so we are not saving it incorrectly.

Below is the what we use to generate the Uri for the auth request. It is mostly a modified version of the DotNetOpenAuth.GoogleOAuth2 client.

protected static Uri GetServiceLoginUrl(Uri returnUrl)
    {
        var state = string.IsNullOrEmpty(returnUrl.Query) ? string.Empty : returnUrl.Query.Substring(1);

        return BuildUri(AuthorizationEndpoint, new NameValueCollection
            {
                { "response_type", "code" },
                { "client_id", AppId },
                { "scope", "openid" },
                { "prompt", "select_account"},
                { "openid.realm", CloudServiceConfiguration.GetDNSName() },
                { "redirect_uri", returnUrl.GetLeftPart(UriPartial.Path) },
                { "state", state },
            });
    }

private static Uri BuildUri(string baseUri, NameValueCollection queryParameters)
        {
            var q = HttpUtility.ParseQueryString(string.Empty);
            q.Add(queryParameters);
            var builder = new UriBuilder(baseUri) { Query = q.ToString() };
            return builder.Uri;
        }

And here is what we use to generate the request to the token endpoint.

protected static Tuple<string, string> GetAuthTokens(Uri returnUrl, string authorizationCode)
    {
        var postData = HttpUtility.ParseQueryString(string.Empty);
        postData.Add(new NameValueCollection
            {
                { "grant_type", "authorization_code" },
                { "code", authorizationCode },
                { "client_id", AppId },
                { "client_secret", AppSecret },
                { "redirect_uri", returnUrl.GetLeftPart(UriPartial.Path) },
            });

        var webRequest = (HttpWebRequest)WebRequest.Create(TokenEndpoint);

        webRequest.Method = "POST";
        webRequest.ContentType = "application/x-www-form-urlencoded";

        using (var s = webRequest.GetRequestStream())
        using (var sw = new StreamWriter(s))
            sw.Write(postData.ToString());

        using (var webResponse = webRequest.GetResponse())
        {
            var responseStream = webResponse.GetResponseStream();
            if (responseStream == null)
                return null;

            using (var reader = new StreamReader(responseStream))
            {
                var response = reader.ReadToEnd();
                var json = JObject.Parse(response);
                var accessToken = json.Value<string>("access_token");
                var idToken = json.Value<string>("id_token");
                return new Tuple<string,string>(accessToken,idToken);
            }
        }
    }
like image 482
kkychuck Avatar asked Apr 03 '14 15:04

kkychuck


1 Answers

Please make sure you use EXACTLY the same openid.realm value during the migration flows as you used during the initial OpenID2 flows: any mismatch in those values (even a missing trailing slash char) will lead to completely different openid identifier values.

like image 126
Miguel Andres Avatar answered Oct 17 '22 14:10

Miguel Andres