systemseed / falcon-legacy

4 stars 1 forks source link

[SSO] Notes #13

Open spleshka opened 6 years ago

spleshka commented 6 years ago

Terminology:

  1. SSO - Single Sign On service
  2. Ticket - Authentication token

SSO

  1. Usual Drupal login
  2. Usual Drupal password reset
  3. Not allowed registration (all users should be created manually)

Frontend

  1. Authenticate against SSO. SSO should send back ticket ID, expiration and user name.

  2. Frontend to include ticket number alongside with every request to backends

  3. Frontend to revalidate ticket connection before request to the backend if it expires

  4. Ticket number and expiration to be stored in cookies:

    • concern.net for all *.concern.net domains
    • concern.org.uk for all *.concern.org.uk domains
    • for all *. domains (not mentioned above)
    • *.platform.eu.sh for all p.sh dev environments
    • *.cw2.local for all local environments

Think through security implications. Instead of cookies it can be stored in browser storage.

Any D8 microservice

  1. /user/login takes to sso login (with redirect back)
  2. /user/password takes to sso password restore
  3. /user/register is disabled. User creation should be disabled

Workflows

  1. Initial authentication from the frontend

    • Develop a js login module (including login form). Pack as a standalone js module.
    • Include js login form into every FE
    • Users access FE login form. Form makes request to SSO backend, validates & authenticates user. SSO returns ticket ID and expiration date back to the user.
  2. Making authorized requests to the backend

    • If ticket is not expired, make request straight to the backend as usual. Set ticket ID in header (or can be sent automatically with cookies).
    • If ticket is expired, first make request to SSO to renew the session, then make a usual request to the backend.
  3. Authentication of FE request against backend

    • Take a ticket from the cookie. If this ticket is unknown, make request to SSO and validate ticket. If authorized, save session for ticket expiration date. If not, perform usual request as anonymous user.
    • Automatically create a user if didn't exist. Do not use real users's email. Can use user ID or anything similar. Map existing user roles.
  4. User update (status or roles). Close active SSO session. D8 microservices will pull the new info next time the new ticket ID was sent from the frontend.

  5. Authentication from backend services

    • Redirect to SSO login form. Set cookie and redirect back on success.
  6. Log out

    • Logs out only from the requested domain

Other notes

  1. Ticket expiration: 30-60mins
  2. Ticket renew expiration: 1week
  3. Add a small topbar when user is authenticated with username and logout link.
otarza commented 6 years ago

Initial tech concept for SSO:

Drupal/Backend part

Integration with API Bus

API Bus should just proxy all requests from frontend to SSO Drupal instance as I understand.

Does this mean that we need to implement some kind of auth mechanism in all backend apps and services we have? Maybe process should look like something this: Frontend -> API Bus(token request) -> SSO -> API Bus -> Frontend (Token received) -> API Bus (Auth request) -> some backend service -> SSO (actual auth) -> some backend service -> API Bus (user data received) -> Frontend (user authenticated). I am not sure about this yet. This is something we need to make decision according to what our needs are.

Frontend

Other details

spleshka commented 6 years ago

Hi @otarza, thanks for thorough plan. Can you tell me what are your thoughts on these Qs:

  1. How will backend services be authenticated against SSO?
  2. How will backend services grant permissions to user if the user exists only in SSO? How do you sync users / roles between SSO and backend apps?
  3. How users will be automatically authenticated against all backend applications once they are logged in?
  4. Shall we better use auth form from SSO? As an MVP we could redirect people to SSO login form which sets cookie and redirect back with auth / refresh tokens in GET query.
otarza commented 6 years ago

Hi @spleshka,

Here is what I think for now:

  1. Backend services should use auth token provided by frontend and send it to SSO to to authenticate, if token is valid SSO(simple_oauth) will return user data + info about roles and permissions.
  2. I am not sure about this yet, but I think some kind of "proxy" users should be created for every backend user, to prevent data duplication we don't need to copy all user data to al backend services but we need to store at least user id and maybe roles/permissions data. Anything else should always come from SSO. This is how I imagine it now but it might be wrong approach, I'm not 100% sure.
  3. As I understand now, maybe redirects to SSO will be necessary every time new (not yet authenticated) app is opened.
  4. I agree, Looks like this should be a case.
spleshka commented 6 years ago

Hi @otarza ,

  1. Backend services should use auth token provided by frontend and send it to SSO to to authenticate, if token is valid SSO(simple_oauth) will return user data + info about roles and permissions.

You can't have such complicated trip for every request. Otherwise, the performance will be aweful. There shoudl be a solution to make the request to the SSO only when it's needed, not on every request.

  1. I agree about the "proxy" users. We don't need to copy the permissions - only the roles. The permissions will be set to certain roles per backend app.

  2. Why don't we try to set domain-level cookie for all backend apps (including SSO and API bus)? Then once a user authenticated against sso and the cookie is set, we can authenticate him against all other backend apps using the same cookie. So SSO's cookie with auth data should be accessible for all backend apps, though every app will have its own cookie domain for authentication token within the app (but SSO's cookie is accessible for everyone).

otarza commented 6 years ago

Hi @spleshka,

  1. No not for every request, just for first one and after that backend service itself will store session;
  2. Ok;
  3. I think that was exactly what I was thinking, to make it clearer: user authenticates and gets 1 token, that same token is used for any other app right? if that's what you think, yes I agree, that is the way simple_oauth works too. you don't need to have separate tokens for every app, you just need one token provided by SSO instance and all frontend apps and backend services could share that token.
spleshka commented 6 years ago
  1. Cool
  2. Yes, correct.

Can you update the concept / tasks based on the latest conversation and get started with the proof of concept implementation?

spleshka commented 6 years ago

@otarza actually, I think we can just close this issue and create a new one to run proof of concept.

otarza commented 6 years ago

@spleshka yes we can create one parent Issue but it will be a big one, after that we should break it down to smaller ones.