Ueberauth purpose? Google Sign In?

This may be a dumb question, but I’m lookin at ueberauth, I’m unclear as to its purpose… the docs kinda miss the forest for the trees IMO. I’m going to truffle sniff through the links there but has anyone used it to verify a Google Sign In?

The uberauth library is a base which tries to help with all authentication methods that work with a request & callback for example OAuth2.
You generally dont use it alone but instead use a strategy on top of it (which is a different library) these strategies are more specific implementations like github, gitlab, google as you said and many more

Hope that helps :slight_smile:

The uberauth library is a base which tries to help with all authentication methods that work with a request & callback for example OAuth2.

Yeah, it’s built on the same concept as OmniAuth, so you want to use the individual strategy libraries. Here’s the one for google: GitHub - ueberauth/ueberauth_google: Google OAuth2 Strategy for Überauth.

Side note; I never really liked this approach, it feels like too much abstraction. I built Assent to have everything out-of-the-box to both conform the strategy flows, make each strategy integration as minimal as possible, and prevent breaking stuff whenever there’s any changes to the core logic: GitHub - pow-auth/assent: Multi-provider framework in Elixir

1 Like

Hmm… the more I look at this, the more I think this is really an unfortunately failure of documentation. Ueberauth looks like a great package, but the documentation doesn’t demonstrate the problems it solves. I suspect this failure is responsible for motivating the development of some other packages that cover some of the same ground. It’s always a bummer when the docs aren’t up to par with the code and people never get to take advantage of all the hard work that went into the code. If I can get this figured out, I’ll try to submit a PR for the docs.

I had the same impression the first time I looked into this… sometimes it’s just easier to read the code :man_shrugging:

1 Like

Yeah, @pera, I hear you.

So a couple things I don’t understand with the Ueberauth Google implementation (and for @danschultzer and the asset package)…

There are 3 config/ENV variables that these implementations rely on:

  • GOOGLE_CLIENT_ID
  • GOOGLE_CLIENT_SECRET
  • GOOGLE_REDIRECT_URI

The flow for both these implementations (so far as I understand it):

  1. a user comes to your Phoenix site, clicks on the “Google Sign In” link whose target is another Phoenix route, /auth/google.
  2. Somehow, the request to /auth/google redirects to the the Google Sign In page for configured client, e.g. https://accounts.google.com/signin/oauth/identifier?client_id=123
  3. After successfully authenticating against Google, Google makes a GET request back to your app, e.g. http://localhost:4000/auth/google/callback?code=xxxxxyyyyzzz&scope=email+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.email+openid&authuser=0&hd=mysite.com&prompt=consent

And that’s where I can’t follow what it’s doing. Is the plug checking the supplied code in the GET request from Google to verify that it actually is from Google and properly signed? Because I assume there’s something there that’s preventing randos from making GET requests against that same endpoint and having it issue a session.

How I did my implementation of this was simpler (IMO). It required only 1 config: the GOOGLE_CLIENT_ID. I used the Google Sign In button provided by Google – I just had to include their JS. The flow was this:

  1. User comes to my Phoenix site, clicks the Google Sign In button.
  2. The Google JS fires a popup which requests https://accounts.google.com/signin/oauth/identifier?client_id=123 page (identified by the Google Client ID).
  3. After the user has successfully auth’d, execution came back to the JS, and it entered into the user defined callback.

At that point, your JS has the JWT produced via the signup, and it can POST that value to any endpoint you define in your app, and then:
4. Your app would verify the signature of the JWT to make sure it hadn’t been tampered with – setting GOOGLE_CLIENT_SECRET and GOOGLE_REDIRECT_URI was not required.

Why/how is Ueberauth verifying the OAuth response?

It’s OAuth 2.0 auth code flow in both cases. Normally the client returns an auth code via query params to the server, and the server exchanges the auth code for an access token using the client secret. When you use the JS SDK it’s instead the client that handles this process. Instead of using client secret it’s done with PKCE, and the server will only have to validate the token signature.

This might give you an idea how it works in JS: https://developers.onelogin.com/openid-connect/guides/auth-flow-pkce

This PKCE link is helpful, thank you! Let me see if I have this straight… in the first case (e.g. the one used by Ueberauth), the server backend (e.g. Phoenix) ends up with a token which (after exchanging it) can be used to make further requests, whereas in the JS variant, the client ends up only with a JWT which vouches for the user and basically proves that the user is who they say they are (the client just has to verify the signature on the JWK to prove that it has not been tampered with).

I don’t recall having to define a client secret or code challenge, however… I’m also looking over https://auth0.com/docs/flows/concepts/auth-code-pkce – but I don’t follow all the steps that it diagrams.

I’ve done Facebook OAuth setups – they work the same way as the Ueberauth example with a token sent to the redirect URL that has to be exchanged before it can be used to make calls against the Facebook API. Twitter uses (used?) OAuth1, but it was the same type of flow.

I’m not aware of other authorities that will cough up a JWT as a “by-product” of logging in, which the client can then verify.

@danschultzer - does Assent support the PKCE type logins?

Yeah, that’s about right, they are both access tokens, but the one fetched by the client is usually short lived.

It’s handled in the JS SDK, so the code challenge is generated by the client and the only information needed is the client id.

No, but it make sense that short lived access tokens fetched by the client can be used in the Assent callback flow to generate long lived access token and fetch userinfo. It’s something I got in the pipeline (in this case Facebook), but haven’t had time to deal with yet: Allow passing access token to callback · Issue #34 · pow-auth/assent · GitHub

Many providers have this PKCE option or similar to generate tokens on clients, it is a necessity with e.g. SPA that doesn’t rely on a backend. As you can see in the above issue, Facebook has a client side SDK as well (they also have a JS version if I recall correctly).