Inviting Guests (Proposal) - Orodan/Hilary GitHub Wiki
Requirements
- A user should be able to "invite" a user by email address into the system / a group. This user may or may not already have an account on the system
- The user who is invited should be provided access to the group specified
- The user who is invited should not automatically be affiliated with the tenant to which they were invited if they did not already have an account
- The user who is invited should not be automatically provided full "Logged In" access to the tenant two which they were added
- If the user does not already have an account, there should be a way that this user can be created such that it does not have affiliation with existing institutional tenants
Strategies
Strategy 1: Leverage existing Tenant->User model of tenant owning a user
-
The main issue of leveraging the existing model when considering the requirements is the fact that email addresses and user accounts in the system are not globally unique. However, if you simply make them globally unique then users cannot create accounts to collaborate in multiple tenants and use their email address because only one account in the system can have it
-
Establishing the User
- If the user exists with that email address, simply add them to the group (Keeping in mind the current issue with there potentially being several accounts with the same email)
- If the user does not exist with that email address, create a user account in the tenant that is specified to "own" that email domain
- If the user does not exist and no tenant "owns" the email domain, create a user in a designated "Guest" or "Rest of the World" tenant
-
Providing access to the group
- The link that the user clicks on in the email will have an expiring token on it. That token will reference data in the database that indicates the user being added and the target group to add them to
- If the user who authenticated is not the same as the user being added, no one should be added. However, if this happens the token should not be deleted. The user should be able to try again until they are able to authenticate as the proper user or until the token expires
-
Pros:
- The user is not affiliated with the tenant of the user who invited them
- The user does not gain access to all "logged in" items
- Quicker to implement
-
Cons:
- The user has no workflow to become affiliated with a tenant afterward. To be a part of another tenant afterward, they must create a new account
- The user will never be able to gain full "loggedin" access to the target tenant in this workflow
- User will have to become fully "public" in order for those from the target tenant to discover them
- Since users can have a user profile per tenant, users can have multiple profiles and therefore email addresses cannot be unique. When inviting, which account to grant access to the group?
Strategy 2: Separating users from tenants, establishing global user accounts with unique email
Implementation steps
- Authentication Providers become entities rather than a configuration property
- In admin UI, global administrator can create preconfigure authentication providers based
on strategies that are registered in the code
- Creates an instance of a configured provider in the database
- Tenant admin has a section in which they can configure access to their tenant
- They can enable access for all or select users of a preconfigured auth provider
- Backward compatibility considerations:
- If we don't care about backward compatibility, we can immediately remove configured authentication providers from the system. However this means there is a period of not having authentication until all auth providers can be pre-configured
- The current "legacy" configured authentication providers are synonymous to having a preconfigured authentication provider with "all" users allowed
- When determining the auth providers available, there will be a new endpoint that
consults both the config and the selected preconfigured authentication providers
- The endpoint will have to provide the UI with enough information to determine which authentication provider allows "all" and which ones allow select users. This is so that the UI can "stash away" excessive numbers of auxiliary authentication providers are displayed for login. The "main" case will likely be the "all users" providers
- User-facing improvement:
- More granular control of who has access to your tenant
- Gets closer to The Fold use case, where they can provide access to individual or full institutions (however, users who log in to The Fold tenant will be given duplicate accounts)
- What issues remain:
- A user still must create an account in another tenant to be a "member" of it
- When user authenticates to a tenant using a preconfigured provider, they still get a new account scoped to that tenant
- External IDs are still scoped to tenant
- Emails are still non-unique
- Affiliations: User can add affiliations to their profile
-
User can add additional affiliations. Adding an affiliation involves specifying the tenant and authenticating with one of the tenant's authentication providers
- "Primary" affiliation is always that of the tenant to which the user "belongs"
- In the future the user can change the primary affiliation, but I think this requirement is necessary until a user can log in to any tenant without risk of having duplicate accounts created
-
When an affiliation is added, not only does the user gain "loggedin" access to all resources inside that tenant (when authenticated to their "Primary" tenant), users affiliated with that tenant gain access to view their profile if the user is "loggedin"
- How does this impact libraries? Maybe when a user views another user's library, we use the search feed -- this is probably ok. Maybe "synchronous" library feed is actually only private (for when a user adds something to their library), and for other views (loggedin and public) it is fueled by search
- For search, I think we can pass affiliated tenants as part of the query similar to passing group membership for private content items
- For canInteract, it takes into consideration all affiliations
-
The reason this is proposed to happen before making emails globally unique is because once we make emails globally unique, it degrades the potential of having accounts in multiple tenants which is still a valid use-case to have users participate as "loggedin" users in multiple contexts. Once affiliations have been implemented, it allows this functionality to be covered without requiring the user to have accounts in the respective tenants
-
User-facing improvements:
- User does not need to create another account in a different tenant to get the benefits of being treated like a member of that tenant. But if they do log in to that tenant they still get a duplicate account
- It is no longer necessary for a user to create multiple accounts in the system
-
What issues remain:
- A user will still always get a new account when they successfully authenticate to a tenant they haven't before
- External IDs are still scoped to a tenant
- Emails are still non-unique
-
At this point, we have covered The Fold's use case. Although user's who have been provided access should not log in to the tenant, they have full capability to interact within that tenant.
- The Fold adds John Norman from the "Raven" auth provider to have access to the tenant. John then adds "The Fold" tenant as an affiliation. Now, he can now search and interact with all of The Fold's public/loggedin content while authenticated to the Cambridge tenant.
- Make emails globally unique
- Since a user can fully collaborate in any tenant using affiliations, there is no reason for them to have an account in different contexts. Therefore we can make email globally unique and throw an error when a user tries to create an account in a different tenant with duplicate email (e.g., from their external provider)
- Implement email verification
- Migrations are performed:
- Index all existing email addresses
- Duplicate email addresses need to be reconciled or just "blanked" in all but one account
- Do we simply "trust" all existing emails that have been provided but have not been verified?
- Index all existing email addresses
- At this point, we have the pre-requisites to implement inviting guests
Applying to "Inviting Guests"
-
Resolving the invited user
- The user can be resolved reliably VIA their email address. If exists, simply add that user as a member of the group
- If the user has an identity in some authentication provider that has access to the tenant, they can optionally specify the tenant as an affiliation, otherwise they cannot gain 'Logged In' access to any resources of the inviting tenant. Similar to the current tenancy model
- If the user does not exist, the user is directed to a page where they can select an institution that they belong to and authenticate with one of their provider's
- If their email domain matches one of an institution that has an existing tenancy, that tenant will be the default displayed with an option to authenticate using one of their available providers
- If their email domain does not match, the default will be the "Rest of the World" tenant and its available authentication providers
- This implies it is some kind of "Where Are You From?" page that can show a default tenancy
- The user can be resolved reliably VIA their email address. If exists, simply add that user as a member of the group
-
Pros:
- The user can now be reliably identified by their email address
- The user can now operate in multiple contexts as a "Logged In User" without having to maintain multiple user accounts, and have full control over which tenants they "belong" to
- Good for the use-case of Community Tenants such as The Fold who likely don't have their own user provider, but could provide access to users VIA GMail, and users who already have accounts in other tenants can be affiliated without
- There exists a workflow for a user to be created in one context (e.g., Rest of the World), and then switch affiliation later when a tenant for their organization becomes available
- Allows ability to provide access for users from other providers that the tenant doesn't necessarily "own"
-
Cons:
- This is a large chunk of work that is working toward use-cases in the system other than Inviting Guests, probably best to be split into iterations that first cover the functionality that would be needed to satisfy "Inviting Guests" requirements
- Significant UX implications on user management. Would be important for the simple 1-account case that there isn't additional complexity added for a user
- Might not be feasible to have inviting guests wait for this kind of work, and the Pro's might be questionable