Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How do we want to handle multiple applications using auth? #34

Closed
RobStallion opened this issue Mar 14, 2019 · 12 comments
Closed

How do we want to handle multiple applications using auth? #34

RobStallion opened this issue Mar 14, 2019 · 12 comments
Assignees
Labels
in-progress An issue or pull request that is being worked on by the assigned person question A question needs to be answered before progress can be made on this issue

Comments

@RobStallion
Copy link
Member

My current understanding of how auth will work is that it will be a separate application that a calling app forwards requests to.

If this is correct, how do we want to handle multiple applications using auth?
Would we deploy multiple versions of the auth app?
Would one auth application handle multiple calling apps?

@RobStallion RobStallion added the question A question needs to be answered before progress can be made on this issue label Mar 14, 2019
@nelsonic
Copy link
Member

@RobStallion thanks for opening this question! 🕺🏻
We need a diagram for this.

@RobStallion
Copy link
Member Author

@nelsonic After reading programming-phx 1.4 my thoughts on how the auth app might work have changed some and I wanted to run my current thoughts passed you.

They talk about separating a users sensitive and non-sensitive information into different places in the application and database. All the non-sensitive info (username, name, etc) is put in the users table while the sensitive info (email, password, etc) is put in the credentials table.

Auth will:

  • be an application that a user requires as a module
  • create a credentials table when a user migrates
  • handle logic around email and password (figured this would be the best place to start and possibly expand this later)
  • update the conn from the parent app with session/assign info.

this is thinking of the auth app in the most basic way at the moment and not including the other tables that it will need to contain (e.g. sessions table).

Pros

Using this approach people using our module will:

  • have a lot of flexibility around the rows that their users/people table contains
  • be able to see and access the credentials data in their database
  • have access to all functions that handle auth (login, login_by_email_and_pass, etc...) will be expose. Users will just to call the functions where needed without having to worry about any implementation details/logic.

Cons

Using this approach people using our module will

  • need to create their own user table which will hold all the info besides the email and password.
  • need to create the login/logout forms

Please let me know your thoughts on any of this. This is my no means a finished idea. I also have a SO question open relating to how we would best implement something along these lines here.

@nelsonic
Copy link
Member

@RobStallion technically all user data is sensitive (according to GDPR)
Yes, in the context of GitHub a username is public but imagine we are building something for the NHS which would have a "forum" where vulnerable people could interact with and seek help from medical professionals. The person's chosen username and especially their name are highly personal and need to be encrypted and stored appropriately.
The Programming Phoenix Book (v1.4) is good for the technical implementation especially contexts, but it's not written from a maximum privacy perspective (and is certainly not GDPR-compliant) please treat the book as a "guide" not a "gospel" when building Auth.

For our purposes all people-related data is sensitive. There is no advantage to splitting out "credentials" into its' own table as we will always select and decrypt the Name of the person (in order to display it in the UI) on a successful login. This is why a login flow diagram is necessary. 😉

Rob, if you have time today we should pair on a Diagram to clarify this for ourselves and others. 📝

  • Auth should be a logically separate Umbrella Application that is fully self-contained.
    https://elixir-lang.org/getting-started/mix-otp/dependencies-and-umbrella-projects.html
  • (for now) it should require the creation of a separate database to store user-sensitive data.
    Having a separate database for auth is the best thing for privacy.

    Note: we may re-visit this later if we want to give people the <option> of using the same DB as their main Phoenix App, but for now it should be completely separate.

  • We should have a Auth.session_verify function which should be it's own Hex module that should be included into any app and used to verify a session validity.
    • Check the JWT info is valid:
    • Force re-authentication if session has expired.
    • Reject any request where device/agent hash does not match JTW.
  • If the Application (using auth) needs access to more of the "user" (personal) data we can create an API request to retrieve that data. e.g: GET /auth/personal_details

We must figure out how to integrate this with Phoenix Sessions: phoenixframework.org/blog/sessions

Please share the link to the StackOverflow question you opened on this when you can.

@RobStallion
Copy link
Member Author

My stack overflow question is here.

@nelsonic
Copy link
Member

nelsonic commented Mar 20, 2019

Auth Diagram: https://docs.google.com/presentation/d/1PUKzbRQOEgHaOmaEheU7T3AHQhRT8mhGuqVKotEJkM0
@RobStallion please LMK if you can access/edit it.

@nelsonic
Copy link
Member

Diagram is public on the interwebs so anyone should be able to see and edit it:
image

@RobStallion if you have time to walk through the requirement for sending an email with a link to "verify email address" with @Cleop please go for it. the issue is: #35 (thanks!)

@RobStallion
Copy link
Member Author

@nelsonic I have created 2 basic phoenix applications called regular_app and auth_app.

regular_app is pretty much just a default phx.new project. I have added httpoison to the deps and and using it to make requests.

auth_app is the app you make following the programming-phx-1.4 book (up till chapter 5 as that is where they cover auth). It has basic login/logout functionality.

So far I have been able to get regular_app to send a post request to auth_app with json of a username and password. That user can then be verified in auth_app and a json response can be sent back to regular_app.

I know that this ins't exactly what we talked about when we made the login diagram but I figured we would need to be able to do something similar to this for a newsletter registration type event anyway so it would be good knowledge to have.

Next step

Have regular_app link to auth_app's login page. Once login has been completed in auth_app send the user back to the page they came from in regular_app (look into http referer as a poss way).

Once I am back in regular_app, make a GET request to auth_app to check the session is valid. My first guess is that regular_app will need an "auth_plug" type of thing that will handle making this request for all incoming requests but we'll see.

@RobStallion
Copy link
Member Author

I have updated my test apps.

regular_app has a link on the landing page that links to auth_app
Once in auth_app I get the http_referer like so...

referer = get_req_header(conn, "referer")
render(conn, "new.html", referer: referer)

and send it to the login form which has it as a hidden field.

I log in as normal in the auth_app. If log in is successful however it redirects back to regular_app like so...

redirect(conn, external: referer)

auth_app creates puts the user_id in the session on login like so...

  def login(conn, user) do
    conn
    |> assign(:current_user, user)
    |> put_session(:user_id, user.id)
    |> configure_session(renew: true)
  end

Not sure on best way of sending this info back to regular_app at the moment.

@nelsonic
Copy link
Member

@RobStallion worth opening a separate issue e.g. in learn-elixir and describing the problem as a "SSCCE" so that you can ask it on SO/Elixir Forum and capture the answer?

@RobStallion
Copy link
Member Author

Have been doing a fair amount of reading up on session vs token based auth...

And the impact that this could have on the way we want to build auth.

The Phoenix book shows us how do auth with session auth, as seen in this comment above

Guardian is a token based authentication library for use with Elixir applications and can be used to create JWTs.

@nelsonic You mentioned that you did not want to use Guardian in this comment but said it was a closer approximation to what we need.

I looked into how it is used in elixir apps (I have never used it personally so needed to look at some examples. The first link above is a good example) and they have made the implementation of it fairly similar to the examples from the book, e.g. they create an auth plug and pipe incoming requests that need to be verified through said plug.

My current understanding of how JWTs are verified is through the "secret" in them. JWTs are made up of header.payload.secret. This secret or signature is what the receiving app uses to verify the request.

I think that we would be able to create an api this way fairly easily. E.g. a user would login by sending a post request to auth_app, auth_app would do the logic and send back json (a JWT).
However, if we want to redirect users to auth_app and then redirect back to regular_app as mentioned, we will need to pass the JWT back in the redirect. I am not sure how we will do this ATM but I think we should be able to do it will Plug.Conn.put_resp_header/3.

Once back in regular_app we will need to be able to verify the JWT when needed. I assume that if regular app has the access to the same secret/signature used in auth_app we will be able to verify the JWT without having to make further requests to auth_app (unless we need a users data of course, in which case we could have a simple api set up for this)

@nelsonic Let me know your thoughts

@nelsonic
Copy link
Member

nelsonic commented Feb 7, 2020

The idea of using ueberauth/guardian is a non-starter for me. 👎

If you read through the docs for Guardian there is a lot of text but not a single diagram. 🤷‍♂
See: https://github.com/ueberauth/guardian/blob/guides/introduction/overview.md 👀
How does someone explain a complex topic like Auth without any diagrams? 🤦‍♂
Something as simple as this: https://github.com/dwyl/hapi-auth-jwt2#understanding-the-request-flow would be a lot better than large blocks of text and nothing visual.
This is not a "niggle", it's a symptom of a bigger problem: complexity.
guardian-uberauth
The first line of the docs informs me that I'm going to have to create an "implementation module".
Why? Why isn't there a default one already included that I can use immediately.

It reminds me of:
image

We can simplify our Auth by an order of magnitude by just building exactly what we need from scratch.
We want our "setup" instructions to be:

  1. Decide where you're deploying your instance of auth. (e.g. localhost, Heroku or AWS) 💡
  2. Define the Environment Variables 🔑
    (it might take someone a few minutes to assemble all the API Keys they need
    e.g: Google API keys for Google Auth and AWS keys for sending emails
    )
  3. Deploy! 🚀

That's it. No more configuration or steps required. Get back to building the features of the app.
Obviously, to achieve this level of "batteries included" simplicity, we have to do a lot of work on our end.

Next: dwyl/app#268 (comment)

@nelsonic nelsonic added the in-progress An issue or pull request that is being worked on by the assigned person label Mar 30, 2020
@nelsonic
Copy link
Member

nelsonic commented Apr 1, 2020

GOTO: #42

@nelsonic nelsonic closed this as completed Apr 1, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in-progress An issue or pull request that is being worked on by the assigned person question A question needs to be answered before progress can be made on this issue
Projects
None yet
Development

No branches or pull requests

2 participants