Question

How does one implement OpenID based authentication in Angular.js (with Flask back-end web app)?

It looks like the Angular.js code needs to incorporate logic like the example found here.

However, the Flask side should also have an OpenID verification mechanism.
Is there a "recommended" way to write the logic for both backend and frontend?
Is there a github example or some other related resource for starters?

Was it helpful?

Solution

Unfortunately I do not have a sample application to share, but here is a high level description that I hope is useful.

Let's forget for a moment that you have an AngularJS app and review how the OpenID authentication exchange works:

  1. User enters OpenID URL in a login form and submits to the server
  2. The server gets the OpenID URL and responds with a redirect to the OpenID provider. The redirect includes some arguments, including a callback URL.
  3. The OpenID provider prompts the user to enter login credentials and then to allow the sharing of his/her identify with the server application.
  4. The OpenID provider responds with a redirect back to the application, at the URL given as a callback in step 2, and makes information about the user such as ID, email, username, etc. available to it.
  5. The server now has user information and can locate the user in its own user database via the unique ID, the email address or some other piece of identification. At this point a new account can be created if the user is not known to the application.
  6. Now that the user is known, the server can write a cookie that records who he/she is, but note that this is a different identity than the one in step 5. The identity information returned by the OpenID provider was useful to locate the user in your own database, so now you can record the user's identify in the context of your application. This could be a database user ID, the email address or the username (if they are unique), or a token, which can be a hash of some of the information you have about the user.
  7. With the cookie written each new request that is sent to the server comes with the data that identifies the authenticated user.

So let's see what happens when you add AngularJS to the mix. Note that there are many ways to do this, what I describe below is one possibility.

If the Angular app issues a request to the server that requires authentication the server should return an error code 401. The Angular app can pop up a login form when it gets a 401, for example.

But the OpenID authentication dance cannot be done all in the context of a rich JS application because it requires browser redirects. Your server side application will have to support at least three routes:

  • a root URL that serves the Angular app
  • a URL that initiates OpenID authentication
  • a URL that is sent as callback to the OpenID provider

So the user connects to your root URL and gets the AngularJS app, which starts in a non-authenticated state. At some point the Angular app will prompt the user to login, using a form that has an OpenID text field an a submit button. These form fields should be part of a regular HTML form that posts to the server, not client-side Angular elements attached to a controller. The "action" attribute of the form should point to the server's OpenID login route.

When the user clicks the login button the server awakens and receives the request to start the OpenID authentication. At this point steps 1-5 above run without change.

At the end of step 5 the server has located the user in the application's database. What the server can do now is respond with a redirect back to the root URL, to get the Angular app restarted. If the app needs to restart in a state that is not the initial state then the state to restore can be saved in client side storage (a cookie, for example) before starting the OpenID authentication process.

But this is not enough, the server also needs to pass Angular some information about the user that logged in. One way to do this is to attach the user's unique ID or token in the query string of the redirect URL, which the Angular app can access. This would be the same piece of ID that went into a cookie in step 6 above.

Now the Angular app is restarted, can restore its state if necessary, and has an ID or token that identifies the logged in user. When the app needs to make an Ajax request to the server it sends this ID or token along with the request. The server can verify it and return 401 if found it is invalid or if it had an expiration date and found to be expired.

If the identification sent with the request is verified then the request can be carried out and a response can be sent back to the Angular app.

A logout function can be implemented in the client-side simply by deleting the user ID/token, so that future requests to the server are sent without authentication again.

Very Important: all exchanges between the Angular app and the Flask server that include user information must be done over secure HTTP. If not your IDs or tokens will be traveling in plain text.

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