« Back to home

oidc-token-manager library with Google Identity Platform - Part 2

Daj się poznać

This post is a continuation of the previous one previous one where I started to describe my attempt to use library oidc-token-manager with Google Identity Platform.

I was stuck at the moment when this library couldn’t validate a signature for an access token because of the unexpected format of the certs. I found in the documentation that I can provide certs for this library myself in the config and the library wouldn’t make a request for them.

I did this in the config property by specifying the value for the jwks property. After this, config in index.html looked like:

var config = {
   authority: "https://accounts.google.com",
   client_id: "342665198077-tp56a5pab4ei5lri37nkba69b6sqghou.apps.googleusercontent.com",
   redirect_uri: window.location.protocol + "//" + window.location.host + "/callback.html",
   post_logout_redirect_uri: window.location.protocol + "//" + window.location.host + "/index.html",
   response_type: "id_token token",
   scope: "email",
   silent_redirect_uri: window.location.protocol + "//" + window.location.host + "/frame.html",
   popup_redirect_uri: window.location.protocol + "//" + window.location.host + "/popup.html",
   jwks: {
       keys: [{
           kty: "RSA",
           x5c: ["-----BEGIN CERTIFICATE-----\nMIIDJjCCAg6gAwIBAgIIUQ9p7LoIOI8wD …[removded for brevity ]... eTh45xGznVwh8\n-----END CERTIFICATE-----\n"]
       }]
   },
   silent_renew: true
};

and in the callback.html, config looked like this:

var config = {
   authority: "https://accounts.google.com",
   client_id: "342665198077-tp56a5pab4ei5lri37nkba69b6sqghou.apps.googleusercontent.com",
   jwks: {
       keys: [{
           kty: "RSA",
           x5c:  ["-----BEGIN CERTIFICATE-----\nMIIDJjCCAg6gAwIBAgIIUQ9p7LoIOI8wD …[removded for brevity ]... eTh45xGznVwh8\n-----END CERTIFICATE-----\n"]
       }]
   },
};

I found a value for this x5c property requesting this url https://www.googleapis.com/oauth2/v1/certs and this url I found in the file downloaded from Google Developer Console, which I used in the previous post to get the client_id. You can read here how I got it. (link). Hardcoding the value for x5c is a very bad solution because Google often changes certs but for testing it’s sufficient for me.

After this, when I opened the application I got this screen: [networkError.png]

Network error

And the web browser console showed me this:

Userinfo 404

This error came from a request for userinfo. Fortunately, I don’t need to get a user profile. All I need to know about the user is their email and it is in the token. So I can turn off loading the user profile with this option:

load_user_profile : false,

With this option set to false, the oidc-token-manager library won’t send requests to Google for a user profile. After this, another attempt to get a token resulted in the following message in the browser console:

Final result

I could see my token was also in the local storage of the browser:

Token in local storage

As you can see, I got a token from Google Identity Provider and I could use it to get access to the API but my solution is far from perfect.

I made a dangerous assumption in the configuration of oidc-token-manager. While fetching certs from this url https://www.googleapis.com/oauth2/v1/certs, I got a response like this:

{
  "8087d258ac19c0fcf1dab7a908c221cdd81d5512": "-----BEGIN CERTIFICATE-----\nMIIDJjCCAg6gAwIBAgIIBzgwCmlF7SMwDQYJKoZIhvcNAQEFBQAwNjE0MDIGA1UE\nAxMrZmVkZXJhdGVkLXNpZ25vbi5zeXN0ZW0uZ3NlcnZpY … [removed for brevity]... ]eOV9CqsTSJCZ9baLqF4wk6botNe187A88wnj5OVbyoVZK4SMW\n-----END CERTIFICATE-----\n",
  "428489e3a6753680152ffcf1a8f7d0379f28ce9e": "-----BEGIN CERTIFICATE-----\nMIIDJjCCAg6gAwIBAgIIUQ9p7LoIOI8wDQYJKoZIhvcNAQEFB …[removed for brevity]... xcOKB6l8wBqKDmyc1aMXZ+H0WkBgvcEHqeTh45xGznVwh8\n-----END CERTIFICATE-----\n"
}

And I assumed that the second cert was the right one to validate the token. I chose the second one because the first one didn’t work. Instead of this, I should have made a choice dependent on the value provided in the token header which looked like this:

{"alg":"RS256","kid":"428489e3a6753680152ffcf1a8f7d0379f28ce9e"}

The property kid indicates that in the object with certs, I should use the one with the property like the kid value. I discovered that this was the second property but it won’t always be true. I should choose a certificate dynamically but I didn’t want to change source code of the library oidc-token-manager, so that’s why I hardcoded it.

An authentication is a non-trivial challenge for any app. Many developers have tools and techniques they trust for building traditional (page-by-page) auth flows. I thought for a while about building a traditional membership system but I finally decided to try something different. We’ll see the consequences of my choices in the future. For now, I have proven that I can obtain access tokens from Google using the library oidc-token-manager, but the implementation isn’t perfect. If I want to use this library, I would have to change it a bit. I don’t want to do this until I check other possibilities. Future posts will be about the further exploration of the web client authentication with Google Identity Provider.

Related posts:

Comments

comments powered by Disqus