ueberauth / guardian

Elixir Authentication
MIT License
3.43k stars 379 forks source link

Google OAuth2 keys #646

Closed brunoripa closed 4 years ago

brunoripa commented 4 years ago

First of all thanks for the tool, it's really great!

I am actually using ueberauth to authenticate, and Guardian (decode_and_verify/2) in the callback controller to decode the token and extract the claims.

My problem is that google regularly rotates the secrets, which are published here:

https://www.googleapis.com/oauth2/v3/certs

but I don't understand why they are two (clearly, at any attempt, of the two, only one actually works), and also I don't understand how to use the Cache-Control header value to detect the need to update them (this is mentioned here: https://developers.google.com/identity/sign-in/web/backend-auth#verify-the-integrity-of-the-id-token).

Also, it's not very clear how to use the SecretFetcher module, in case.

Sorry if this might not be the place to ask, but I am struggling to get this.

Hanspagh commented 4 years ago

Hi @brunoripa. A bit out of the scope of Guardian, but let me see if I can help anyway. Can you confirm that only one of the keys is working? The way I read it, is that you will need to re-fetch the keys once in a while (according to the cache-control header), but not that only one of them should work.

brunoripa commented 4 years ago

Hi @Hanspagh , thanks for reply.

I had a workaround, the 2 keys are basically the old one plus the new one which will substitute the old one. So what I had to make something like this:

MyApp.GoogleGuardian.decode_and_verify(token, %{}, secret: SecretsFetcher.get(token))

using a specific SecretsFetcher but passing the token, since I need to read the "kid" value in the token headers in order to identify which key to use. My question, at this point, is: I have a feeling that there might be a "Guardian way" to do this, but I have been not able to find any example (which is strange, I think keys rotation is pretty frequent).

Let me know if I have not been very clear :P

Hanspagh commented 4 years ago

So is it correctly understood that a certain key is matching a certain token and therefore you will need to fetch a specific key to a token? Would this not mean that if there are enough key rotations a token can be invalidated by the missing key. I have not seen this sort of key roration before, but if it makes sense we can have a look at how to handle this

brunoripa commented 4 years ago

I can for sure tell you that the kid is telling you which key is to be used among the available ones. But I have guessed this reading tons of fragmented info on the web. Clearly, as a rule of thumb, I did not want to test all of them, but precisely fetch the one needed (what if the server policy changes and they have multiple valid keys ? Testing all of them could end in a performance hit).

Hanspagh commented 4 years ago

@brunoripa Maybe you should rely on https://github.com/potatosalad/erlang-jose for this instead? Seems a bit out of the guardian scope

Hanspagh commented 4 years ago

Closing due to inactivity, feel free to open again