edgexr / edge-cloud-platform

Apache License 2.0
1 stars 0 forks source link

Keycloak Integration #373

Open vinay03 opened 4 days ago

vinay03 commented 4 days ago

Summary

We can setup Keycloak as an Identity Provider (IdP) for both authentication and authorization while maintaining the existing user management system as the primary user system. For this we will have to use user storage provider interface. For e.g. https://github.com/b1-systems/keycloak-user-storage-test

This way, we would be able to use Keycloak for handling authentication and token management, while the pre-existing user system manages the user data and business logic. The whole integration will work as an optional extension to the current existing user management system. There are some builtin mechanism like clients to manage SaaS infrastructure in keycloak for supporting Multi-tenancy. And also we can integrate keycloak roles module using the existing casbin library that we are already using in EdgeCloud code.

Flows

  1. Login Flow a. User Clicks on ‘Login using SSO` button to login. b. User browser is redirected to keycloak login page. c. Keycloak will login user and authenticates the credentials by communicating through Identity Provider(IdP) d. Once authenticated, keycloak will provide JWT Token. Which should be used in later requests. e. In Later requests, the JWT token received at mc controller side, can be validated by communicating with keycloak to receive user and tenant information.
  2. Register Flow a. User clicks on 'Join using SSO' button and gets redirected to Keyclock UI for registration. b. User completes registration and redirects back to login / home page to perform login using a flow described above.

Code Changes

We have to implement a Keycloak User Federation Provider and a user storage provider interface which will communicate with existing user system either internally or via API. This will handle user authentication, and lookups allowing Keycloak to validate credentials and retrieve user data.

Design Changes

  1. Login Form We can add a Login using SSO button below the existing Log In button. image

  2. Register Form We can add Join using SSO button before the Create New Account title on register form. image

@levshvarts @gainsley Could you please share your thoughts on this to have more clarity?

gainsley commented 3 days ago

Hi @vinay03 this is great to have oauth2/openID connect integration, this is a super useful and highly requested feature. I don't have any experience using keycloak so I hope you can help me clear up some questions I have.

  1. It may be helpful to break this problem into two parts: (a) changes for supporting an OIDC provider, and (b) using Keycloak as that OIDC provider. Much of the changes here should apply regardless of whether keycloak is the OIDC provider, or if another OIDC provider is used. Specifically, I would like to avoid hard-coding references to keycloak when it is not necessary. For example, the OIDC provider should be configured in MC, and the UI should retrieve that information from MC via an API to then populate the URL for the SSO page. So the UI should not assume that the OIDC provider is a local keycloak server. Similarly, any kind of RBAC logic should not assume that we can configure role in keycloak, RBAC should work regardless of whether keycloak is the provider, google IDP is the provider, or google IDP via keycloak is the provider. I would even suggest to split the changes into two steps, an initial OIDC support change that can be tested against both keycloak and google directly, and then the actual keycloak integration (most of that code will probably end up in the edge-cloud-deploy repo).
  2. MC implements an LDAP server (although not fully featured). It's how Harbor authenticates users against MC's user database. Rather than messing with a custom user-storage provider to access users from our postgres db, I think it would be better to start with trying to have keycloak access our user db via LDAP, which it supports natively. You may find that more work is needed on our LDAP server to fully support keycloak, but as long as keycloak is not trying to write data via LDAP it should probably not be too much effort.
  3. I would like to understand how you imagine RBAC working. My belief is that our RBAC is too fine-grained and specific to be fully implemented via OIDC roles/scopes, especially if you consider cases where we configure an external IDP like google, or ideally OTC if it supports it. To me that means any external user authenticated via OIDC (from keycloak/google/OTC/etc) will need to also have a local user entry in our postgres DB and RBAC will be managed via our APIs/UI as is currently. Does this mesh with what you had imagined? I don't really have experience implementing this kind of thing so I may be missing something here. Keep in mind that our roles are scoped to organizations, so our logic is based around user+org+resource+action.
  4. We allow users to create API keys, for programmatic access on behalf of the user. These API keys can be assigned a subset of permissions of the user. Will this still work for OIDC-based users?
  5. If keycloak is using LDAP (or something else) against our user DB as the list of users and their credentials, then effectively there are two ways a user could log in - via the existing login flow, or via keycloak SSO. I find this a little confusing, and I think the two paths may be inconsistent, for example if the keycloak path is configured for 2FA and MC is not (I think this is possible but maybe I'm wrong). Also, I assume since the user and credentials are managed by MC, that creating a new user, updating/resetting passwords, etc all continue to go via the existing MC APIs, and not via keycloak. In that case the register flow you mentioned going via keycloak doesn't make sense. If the intent is to register users and update passwords via keycloak (and I'm sure our LDAP doesn't support that), then does that disable the existing user create/password update APIs on MC?
  6. Finally, what about mcctl, our CLI? If we are using an external IDP like google, how does a user authenticate on the CLI? I see two possibilities here: 1) as an example, if you login to Azure via az login, it will actually pop up a web browser page asking you to authenticate. I don't actually know how the token gets back the cli tool. 2) we can require the user to create an API key for CLI logins, rather than redirecting to a web page, so this is a different auth flow than user login. This is what github requires if you've enabled 2FA on your account. I would probably suggest this latter flow as I can understand how it works.