-
Notifications
You must be signed in to change notification settings - Fork 161
adr: Add thoughts about guest users #2183
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
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,192 @@ | ||||||||||||||||||
| --- | ||||||||||||||||||
| title: "Guest users in OpenCloud" | ||||||||||||||||||
| --- | ||||||||||||||||||
|
|
||||||||||||||||||
| * Status: pending | ||||||||||||||||||
| * Deciders: [] | ||||||||||||||||||
| * Date: 2026-01-20 | ||||||||||||||||||
|
|
||||||||||||||||||
| Reference: https://github.com/opencloud-eu/opencloud/issues/2111 | ||||||||||||||||||
|
|
||||||||||||||||||
| ## Context and Problem statement | ||||||||||||||||||
|
|
||||||||||||||||||
| To allow collaboration with external Users (Users that don't yet have an | ||||||||||||||||||
| account in the IDP, and might be external to the organization), it should | ||||||||||||||||||
| be possible to invite "Guest Users" into and OpenCloud instance. | ||||||||||||||||||
|
|
||||||||||||||||||
| ## Requirements | ||||||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I agree with the requirements. Maybe we need to add that the process can be asynchonous and take some time because we are crossing a lot of boundaries between different systems. |
||||||||||||||||||
|
|
||||||||||||||||||
| - the audit trail of the external user accessing the resource needs to | ||||||||||||||||||
| be maintained, that means sharing via a password protected public link | ||||||||||||||||||
| is not sufficient as access to that one is tracked as if the creator | ||||||||||||||||||
| of the link accessed the resource | ||||||||||||||||||
| - external users need to be authenticated just like "normal" users, when | ||||||||||||||||||
| accessing the shared resource (including the possibility to use 2FA) | ||||||||||||||||||
| - the ability to invite external users is tied to a separate permission | ||||||||||||||||||
| (e.g. "can invite guest users") | ||||||||||||||||||
| - make it work with all (most) of the user-management configurations we support | ||||||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not for Lico, right? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. fine for me. |
||||||||||||||||||
| - avoid creating "Shadow IT" Infrastructure, e.g. we don't want to | ||||||||||||||||||
| create/maintain a separate IDP instance just for Guest User that would | ||||||||||||||||||
| allow bypassing corporate rules for Identity Management | ||||||||||||||||||
|
|
||||||||||||||||||
| ## Questions still to be answered | ||||||||||||||||||
|
|
||||||||||||||||||
| - what's the life cycle of a guest user? | ||||||||||||||||||
| - Who's responsible for deprovisioning? | ||||||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I suggest users with the role "admin" |
||||||||||||||||||
| - Do guest users expire after a certain time? | ||||||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. default: guest user accounts expire after 120 days of inactivity (=no login), can be configured. the invitation expires after 30 days per default. can be configured. |
||||||||||||||||||
| - Do we need to keep track of who invited whom and when? (not just in | ||||||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yes. there needs to be a lowlevel option to manage guest users eg. via cmd. list all email adresses:
actions:
|
||||||||||||||||||
| the audit log?) | ||||||||||||||||||
| - who can see the list of guest users? | ||||||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. list of all guest users: users with the role oc-admin |
||||||||||||||||||
| - once a guest user is created, is everyone in the organization able to | ||||||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yes |
||||||||||||||||||
| share with that guest user? | ||||||||||||||||||
| - what are guest user allowed to do? (are they able to share, lookup | ||||||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||||||||||||||||||
| other users?) | ||||||||||||||||||
| - should this be really tied just to creating shares? Or should we have | ||||||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. guest users should get access to the system via a share or space membership. |
||||||||||||||||||
| a more generic "invite user" feature that can be used in other | ||||||||||||||||||
| contexts as well? | ||||||||||||||||||
| - What if the user already exists but used a different mail address in | ||||||||||||||||||
| his account (e.g. sub-addressing?). | ||||||||||||||||||
|
|
||||||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can guest users be converted to "regular" users and keep their shares?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ideally yes. I guess we should add that to the requirements. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ideally yes. |
||||||||||||||||||
| ## Obstacles | ||||||||||||||||||
|
|
||||||||||||||||||
| ### UserIDs | ||||||||||||||||||
|
|
||||||||||||||||||
| - Every user in OpenCloud needs to have a userid assigned | ||||||||||||||||||
| - Sharing, as many other features, needs that userid for storing the | ||||||||||||||||||
| share (share service) and for assigning the grants on the shared | ||||||||||||||||||
| resources (storage provider) | ||||||||||||||||||
| - When an external IDP is used the generation of that userid is usually | ||||||||||||||||||
| not in control of OpenCloud (exception User-Autoprovisioning, or when | ||||||||||||||||||
| the Provisioning/Education API is used), but where taking the userid | ||||||||||||||||||
| from some LDAP Attribute maintained in the external system | ||||||||||||||||||
|
Comment on lines
+58
to
+61
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||||||
|
|
||||||||||||||||||
| ### Lots of identity management options | ||||||||||||||||||
|
|
||||||||||||||||||
| - OpenCloud provides many different ways to consume user-accounts. Guest | ||||||||||||||||||
| users are supposed to be working with all/most of them: | ||||||||||||||||||
| - Internal IDP, with internal LDAP service | ||||||||||||||||||
| - External IDP, with external LDAP service | ||||||||||||||||||
| - External IDP, with manual provisioning via the | ||||||||||||||||||
| Education/Provisioning APIs (to a local OpenCloud specific LDAP | ||||||||||||||||||
| service) - e.g. in multi-tenant setups | ||||||||||||||||||
| - External IDP, with User-Autoprovisioning (also to a local OpenCloud | ||||||||||||||||||
| specific LDAP service) | ||||||||||||||||||
| - everything in-between and outside of the above | ||||||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I suggest to explicitly not support the internal IDP
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ok There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yep. I consider the internal IDP to become a legacy system in the next years, as long as it does not support MFA. Having no MFA or other strong authentication like passkeys will become a nogo in the next years i guess. |
||||||||||||||||||
| - Each of these options have different ways for user-provisioning and in | ||||||||||||||||||
| the way userids are generated and managed | ||||||||||||||||||
|
|
||||||||||||||||||
| ### How do we keep track of invitations? | ||||||||||||||||||
|
|
||||||||||||||||||
| - Completely rely on external system? | ||||||||||||||||||
| - Track creation and acceptance of invitations somehow? | ||||||||||||||||||
| - Do invitation expire at some point? | ||||||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. By default invitations expire after 30 days. can be configured |
||||||||||||||||||
|
|
||||||||||||||||||
| ## Possible solutions | ||||||||||||||||||
|
|
||||||||||||||||||
| ### Re-vitalize the PoC implementation of the invitations service and finalize it (<https://github.com/opencloud-eu/opencloud/blob/main/services/invitations/README.md>) | ||||||||||||||||||
|
|
||||||||||||||||||
| - Implements parts of the MSGraph Invitation Specification | ||||||||||||||||||
| (<https://learn.microsoft.com/en-us/graph/api/resources/invitation?view=graph-rest-1.0>) | ||||||||||||||||||
| - Currently there's just a single backend that allows creating users, | ||||||||||||||||||
| using the Keycloak Admin API | ||||||||||||||||||
| - As part of the user creation keycloak triggers an email to be sent to | ||||||||||||||||||
| the invited user to get him to verify his email address and set a | ||||||||||||||||||
| password. This is not really and invitation email. | ||||||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That is not enough. We need to be in control of that EMail probably.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What exactly do you mean by that? |
||||||||||||||||||
|
|
||||||||||||||||||
| #### Pros | ||||||||||||||||||
|
|
||||||||||||||||||
| - A partial implementation already exists | ||||||||||||||||||
| - no shadow IT | ||||||||||||||||||
|
|
||||||||||||||||||
| #### Cons | ||||||||||||||||||
|
|
||||||||||||||||||
| - while the emails sent by keycloak can be themed. There is no way | ||||||||||||||||||
| to add custom content, like: "you've being invited by user X to | ||||||||||||||||||
| access resource Y" | ||||||||||||||||||
| - the keycloak admin API does not return the password reset link in | ||||||||||||||||||
| the response, so we can't use that to send a custom email | ||||||||||||||||||
| - the keycloak implementation is not a real "user invitation" | ||||||||||||||||||
| workflow, the user experience for the invited user is not ideal | ||||||||||||||||||
| - The workflow likely only works with a limited set of setups. | ||||||||||||||||||
| (Specifically: a keycloak that is able to write into a connected | ||||||||||||||||||
| LDAP database, that OpenCloud can consume) | ||||||||||||||||||
| - As the invitations are not really tracked, e.g. we don't really | ||||||||||||||||||
| "know" if an invitation was accepted | ||||||||||||||||||
| - Requires direct access to the Identity Management System | ||||||||||||||||||
|
|
||||||||||||||||||
| ### Invitation Service + support for pending shares in the share manager | ||||||||||||||||||
|
|
||||||||||||||||||
| - Create some form in invitation manager and provide tools/documentation | ||||||||||||||||||
| for customers to hook that up with their Identity Management System | ||||||||||||||||||
| - User's with the "right" privileges are able to create invitations, | ||||||||||||||||||
| invitations get a unique identifier. Other data maintained on the | ||||||||||||||||||
| invitation: | ||||||||||||||||||
| - Invited user's email address | ||||||||||||||||||
| - Invited user's userid (once the user account was provisioned) | ||||||||||||||||||
| - Inviting user's userid | ||||||||||||||||||
| - Creation timestamp | ||||||||||||||||||
| - Invitation State (Pending, Accepted, …) | ||||||||||||||||||
| - (more probably) | ||||||||||||||||||
| - our sharing API | ||||||||||||||||||
| ('graph/v1beta1/drives/{drive-id}/items/{item-id}/invite') is enhanced | ||||||||||||||||||
| to allow creating shares that target an invitation as the share | ||||||||||||||||||
| recipient. (That share would only be persisted in the 'shares' service | ||||||||||||||||||
| and would not yet crate any grants on the filesystem, or send out | ||||||||||||||||||
| sharing notifications). (Requires changes to the CS3 sharing APIs) | ||||||||||||||||||
| - A middleware (specific to the Identity Management System) is | ||||||||||||||||||
| "informed" (e.g. via web hooks or a message queue) when a new | ||||||||||||||||||
| invitation is created. That middleware is responsible for provisioning | ||||||||||||||||||
| the user account of the guest user. Whatever this process looks like | ||||||||||||||||||
| it completely up to the middleware (maybe it triggers some invitation | ||||||||||||||||||
| workflow or it could just even open a support ticket with the IDP | ||||||||||||||||||
| admin) | ||||||||||||||||||
| - once the user is provisioned the middleware calls back into our | ||||||||||||||||||
| invitations service,marks the invitation as "accepted" and provides | ||||||||||||||||||
| the "userid" of the guest user. The invitations service then triggers | ||||||||||||||||||
| the "pending" shares to be processes, which causes the filesystem | ||||||||||||||||||
| grants to be written and notifications to be send out to the guest | ||||||||||||||||||
| user. | ||||||||||||||||||
| - We'd provide a reference implementation of that middleware, that works | ||||||||||||||||||
| with keycloak | ||||||||||||||||||
|
|
||||||||||||||||||
| #### Pros | ||||||||||||||||||
|
|
||||||||||||||||||
| - Agnostic to whatever Identity Management System is used | ||||||||||||||||||
| - We have an audittrail about who was invited by whom at what point | ||||||||||||||||||
| in time | ||||||||||||||||||
| - no shadow IT | ||||||||||||||||||
|
|
||||||||||||||||||
| #### Cons | ||||||||||||||||||
|
|
||||||||||||||||||
| - somewhat complex | ||||||||||||||||||
| - likely requires changes to the CS3 APIs | ||||||||||||||||||
|
|
||||||||||||||||||
| #### Implementation Obstacles | ||||||||||||||||||
|
|
||||||||||||||||||
| - Permissions on spaces are currently not tracked in the share | ||||||||||||||||||
| manager, the are purely managed via grants. So currently the share | ||||||||||||||||||
| manager service currently does not know anything about (invited) | ||||||||||||||||||
| users being assigned to spaces | ||||||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why does the share manager need to know about invited or even accepted guest users? Is't that just a second call to the invitation manager to get that info where needed?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Could you please elaborate on that? |
||||||||||||||||||
|
|
||||||||||||||||||
| ## Additional thoughts | ||||||||||||||||||
|
|
||||||||||||||||||
| If OpenCloud were responsible for allocating the UserIDs of all users | ||||||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good point! I was wondering also, if that could simplify things in the future and let us get rid of the LDAP dependency.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. AFAICT always having opencloud generate a userid would allow us to get rid of the shared ldap deployment mode. The ldap server would only be used to find recipients (users or groups) in an organization. We always only send invitations into some form of inbox of a user. This could literally be an email. Or an internal nats queue with invites. Anyway, IIRC we bounced around the idea of exchanging the sub+iss, basic auth or app password credentials in the proxy with a userid generated by opencloud years ago already. It has seeveral benefits:
The last point addresses the problem that if a user shares with a guest, aka an email address, that needs to trigger an onboarding process for the new guest. If we just create a new user in a keycloak that we have write permission to we are back at the same shadow it user management as before. We could use OpenID Connect Discovery to find the external issuer and trust that to authenticate users. OIDC in theory is federated. However, in practice our clients would have to dynamically register with the guests IdP ... which does not seem to be widely supported, yet. I think we should use a list of trusted identity providers, this would allow a single instance to use multiple identity providers, eg for multi tenancy use cases or when organization merge and multiple idps exist for a wile or to better reflect the sovereignty of organizations. If no idp is responsible for the guest email, we can use a fallback idp that is only used for guest accounts. We already have the webfinger service that we can use for the issuer discovery. So ... yes, please ... make opencloud generate a userid. |
||||||||||||||||||
| the solution sketch above would likely loose some of its complexity. We | ||||||||||||||||||
| would "roll" the userid for the invited user already when creating the | ||||||||||||||||||
| invite. And could skip the step of creating a "pending" Share with an | ||||||||||||||||||
| invitation assigned. As we have an ID already we could just create a | ||||||||||||||||||
| "normal" share an even populated the grants on the filesystem for that | ||||||||||||||||||
| share (or space) | ||||||||||||||||||
|
Comment on lines
+176
to
+179
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||||||
|
|
||||||||||||||||||
| We've been pondering on the idea of making OpenCloud manage all UserIDs | ||||||||||||||||||
| for quite a while as it would have some additional benefits for the | ||||||||||||||||||
| whole user management story. | ||||||||||||||||||
|
|
||||||||||||||||||
| - We wouldn't rely anymore on the external Identity Management system to | ||||||||||||||||||
| provide a unique id with certain properties. Ideally the only unique | ||||||||||||||||||
| thing we'd need from the external system is the `iss` and `sub` | ||||||||||||||||||
| claims of the IDP and those are required by the OIDC standards. | ||||||||||||||||||
|
|
||||||||||||||||||
| It could be worth to spend some time on figuring out a migration path | ||||||||||||||||||
| towards such a solution, before spending resources on a complex guest | ||||||||||||||||||
| features implementation. | ||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.