Ueberauth and How to Authorize Single Page Apps

After trying this for too long, and wearing out Google, I am at my wit’s end.

How do you (or should you) use Ueberauth with an SPA?

I tried it two different ways.

First, I tried following the Ueberauth examples. I made controller routes /auth/:provider and /auth/:provider/callback Then on the client, a link to the /auth/:provider route.

It works, but it forces a full page reload. That’s undesirable for UX and because it destroys the state of the app. (I realize that I could serialize the state, pass it, and rebuild it… but wow what a pain, especially for an app that’s reloading anyway)

Second, I tried using implicit OAuth flow on the client. That also works – the entire OAuth response returns to the client. But there’s no way to pass a response code to the Phoenix server because the client will have a different response uri from the server, and the oauth server rejects the code.

The second solution is preferable, but it looks like I’ll need to throw away Ueberauth and handle the storage / data structures /etc manually.

Is that the proper way to deal with OAuth 2 on an SPA?

1 Like

Not really, but look at how this forum does OAuth2 as it is an SPA too, it loads the OAuth2 form in another window, which handles the auth, and when it returns it sends a token back from the OAuth server back to the server page that then updates this main page. :slight_smile:

3 Likes

Thank you. That’s a good example!

I think the reason that I’m having so much trouble finding the solution is that there isn’t a non-page reloading server answer. My OAuth ignorance.

It works well reasonably well for forums because you don’t get too much state built up (just the page view, mostly).

1 Like

OAuth(2) operates kind of like you send the user to a special url on the remote server, they either log in or are already logged in and then that server signs some data and sends it back (sometimes even ‘with’ the user) to your server as a token (which you can use to verify logged in status, or get more information or so). So yes, it does require not just one but ‘at least’ 2 url redirects, hence why most SPA sites do it via a popup window or (*shudder*) an iframe. :slight_smile:

1 Like

+1 for the remote server solution with popup, I’m using it for a chrome extension that I built. I had considered implicit flow too but figured it would be too much hassle (sending the tokens from the client, verifying it server-side, etc.). I haven’t got any issues so far.

1 Like

It also seems like authorization flow is preferred over implicit flow for security.

One thing that still confuses me is how do you get the server generated token back to the client? A redirect? E.g. https://server.com/addToken/#{token} and let the client take the route and add the token to its request header(s)?

1 Like

Yes, that’s what I do. After successfully authenticated, the popup goes to something like https://server.com/auth/retrieve#token={token}. The client JS can then look at the URL of the popup window to get the token.

From what I know, I think this approach wouldn’t introduce security bugs if done via HTTPS, but I may be wrong… (would love if someone point it out!)

1 Like