Question

I see that there are some questions about this already but none that i found goes into any details.

I have using my own code from DotNetOpenAuth before but now i decided to switch over to the Microsoft Wrapper for Authentication. Anyways i found this really good OAuth Client:

https://github.com/mj1856/DotNetOpenAuth.GoogleOAuth2

It seems to work fine but now it come to the migration part. In my current login system i save the full OpenID URL that Google returns that are in the form of:

https://www.google.com/accounts/o8/id?id=????????????????????????????????????

According to the documentation here https://developers.google.com/accounts/docs/OpenID i should be able to get that value in some way via the new OAuth system.

I have included the "openid.realm" paramater in the Auth request.

    return BuildUri(AuthorizationEndpoint, new NameValueCollection
        {
            { "response_type", "code" },
            { "client_id", _clientId },
            { "scope", string.Join(" ", scopes) },
            { "redirect_uri", returnUrl.GetLeftPart(UriPartial.Path) },
            { "state", state },
            { "openid.realm", "http://myoldopenidrealm" }
        });

And as far as i understand the documentation that should be all i need to do. I have made sure that the Realm i used for my OpenID 2 authentication is the same and it's also the same as my return URL.

After I've done that i do that token request and as i understand it it's here that i should see a "open_id" field but i cannot understand how to get it.

protected override string QueryAccessToken(Uri returnUrl, string authorizationCode) {
    var postData = HttpUtility.ParseQueryString(string.Empty);
    postData.Add(new NameValueCollection
        {
            { "grant_type", "authorization_code" },
            { "code", authorizationCode },
            { "client_id", _clientId },
            { "client_secret", _clientSecret },
            { "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");
            return accessToken;
        }
    }
}

This is what the documentation says, and i can't see either the "sub" or the "openid_id" field.

*The response from that token request includes the usual fields (access_token, etc.), plus an openid_id field and the standard OpenID Connect sub field. The fields you need in this context are openid_id and sub:*

Was it helpful?

Solution

sub and openid_id fields are contained in the OpenID Connect ID token, rather than the access token.

You can get an ID token either via the token endpoint (same one that you use to retrieve access tokens) or alternatively you can also retrieve it directly from the OpenID Connect authentication request (by adding id_token to the response_type parameter, potentially saving a back-end call to the token endpoint).

Hope that helps!

--

Sample of how to obtain an ID token

(flows generated using oauthplayground -- highly recommended tool to debug OAuth2/OpenID Connect flows)

  1. Go to https://developers.google.com/oauthplayground
  2. Select (for instance) Oauth2 API v2 userinfo.email scope
  3. Click Authorize APIs
  4. Approve OAuth2 request
  5. Press the "Exchange authorization code for tokens" button.

You can see all http requests/responses. Interestingly, the response to the call to Google's token API contains

{ "access_token": "ya29.XYZ", "token_type": "Bearer", "expires_in": 3600, "refresh_token": "1/KgXYZ", "id_token": "my.id.token" }

You can base 64 decode the payload of the obtained ID token (in this example "id") and get all relevant user information. To do base 64 decoding manually you can use any online tools (see https://www.base64decode.org/ for instance).

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top