openactive / customer-accounts-api

Repository for discussions broadly related to Customer Accounts
MIT License
0 stars 0 forks source link

Dependent accounts and booking on-behalf-of #5

Open nickevansuk opened 2 years ago

nickevansuk commented 2 years ago

Requirements

Dependent accounts

The membership proposal already covers the basic creation and linking of Customer Accounts. This works well for the case when the account holder has an email address and is able to use the Broker interface themselves.

However for scenarios where the Broker system is being used on behalf of children and other adults, there is no mechanism for creating Customer Accounts for these individuals.

Additionally some Sellers might require that new junior accounts are linked to an adult account.

Specific use cases include:

Observations:

Booking "on behalf of"

Allowing one individual to book on behalf of another.

Specific use cases include:

Payments are out of scope of the specifications and handled by the Broker, so the focus of this proposal is on how the booking is achieved.

Concept Options for Dependent accounts

Options are presented below. The last of these is recommended by this proposal.

1) Model full groups and permissions

Different booking systems have different internal models of linking Customer Accounts. One approach is to attempt to create a flexible abstraction from these models, and expose that to the Broker.

For example, by modelling groups similar to WhatsApp groups, or YouTube brand accounts. This attempts to abstract the Booking System's own groups model and permit the Broker to access and update it.

Request examples

GET /customer-account-groups/0
POST /customer-account-groups/0/members
POST /customer-account-groups/0/owner
POST /customer-account-groups/0/administrators
POST /customer-account-groups/0/invites
DELETE /customer-account-groups/0/owner?id=
DELETE /customer-account-groups/0/administrators?id=
DELETE /customer-account-groups/0/members?id=
DELETE /customer-account-groups/0/invites?id=
Response example

{
  "@context": "https://openactive.io/",
  "@type": "CustomerAccountGroup",
  "@id": "https://eg.com/customer-account-groups/fdc14503-275e-46d3-9922-45b986c9f9aa",
  "identifier": "fdc14503-275e-46d3-9922-45b986c9f9aa",
  "name": "Family",
  "administrator": [
    "https://eg.com/customer-accounts/fdc14503-275e-46d3-9922-45b986c9f9aa"
  ],
  "member": [
    {
      "@type": "CustomerAccount",
      "@id": "https://eg.com/customer-accounts/fdc14503-275e-46d3-9922-45b986c9f9aa",
      "identifier": "fdc14503-275e-46d3-9922-45b986c9f9aa",
      "accountNumber": "CA00000123"
      "customer": {
        "@type": "Person",
        "email": "geoffcapes@example.com",
        "telephone": "020 811 8055",
        "givenName": "Geoff",
        "familyName": "Capes"
      }
    }
  ],
  "invited": [
    "https://eg.com/customer-accounts/fdc14503-275e-46d3-9922-45b986c9f9aa"
  ]
}

Customer Accounts can have Dependent Accounts with the following constraints:

To allow extensibility in the future, this is modelled as a single "group" which the "primary" Customer Account is an "admin" of (analogous to WhatsApp groups). This allows for the model to evolve in future to allow multiple groups to include a single Customer Account, inviting of existing Customer Accounts to a group, and promotion of those accounts to "primary" status.

Administrators are a subset of members, and are only available in implementations that support group privileges, where they will always contain the current user (and where removing the current user will have them leave the group, or delete the group if they are the last administrator).

Example actions:

Dependent records are accessed and updated by replacing "me" with the Dependent Account identifier in the endpoints specified in Appendix D.

Advantages

Disadvantages

2) managedBy model for dependent accounts

Rather than attempting to abstract the group model, this approach only abstracts concept of the "owner" of the dependent account.

This means that the Broker is able to add "subaccounts" to the primary authenticated accounts that has been linked, using the OAuth token of the primary account.

E.g. managedBy must include only the current customer account, to simplify implementation, and make the intention explicit.

This Customer Account is accessible only via the OAuth2 keys for the managedBy accounts listed

The result of the endpoint below are similar to initialisation, and the account is created with permission to the Broker from a bookings perspective

POST /customer-accounts

{
  "@context": "https://openactive.io/",
  "@type": "CustomerAccount",
  "managedBy": [ 
    {
      "@type": "CustomerAccount",
      "@id": "https://eg.com/customer-accounts/fdc14503-275e-46d3-9922-45b986c9f9aa"
    }
  ],
  "customer": {
    "@type": "Person",
    "email": "geoffcapes@example.com",
    "telephone": "020 811 8055",
    "givenName": "Geoff",
    "familyName": "Capes",
    "birthDate": "1970-01-01",
    "gender": "https://schema.org/Female",
    "address": {
      "@type": "PostalAddress",
      "streetAddress": "Raynes Park High School, 46A West Barnes Lane",
      "addressLocality": "New Malden",
      "addressRegion": "London",
      "postalCode": "NW5 3DU",
      "addressCountry": "GB"
    },
    "emergencyContact": {
      "@type": "Person",
      "name": "Ralph Capes",
      "telephone": "020 811 8055"
    }
  }
}

Advantages

Disadvantages

3) Broker managed child accounts

To remove the need to synchronise any relationships with the Booking System, the Broker could exclusively manage dependent accounts.

This approach allows the Broker to create dependent accounts that are not connected to any primary account, but instead are managed entirely by the Broker.

Advantages

Disadvantages

4) Dependent accounts are handled within the OpenID Connect Flow (Recommended)

To get around the need for the Broker to model dependent accounts, simply put the dependent account creation step within the OpenID Connect flow.

For example by the following additional parameters: allow_delegation=true

allow_signup and allow_delegation may not be used together, as they specify the mechanism by which a new account is created. allow_signup should be used for the primary Broker account, whereas allow_delegation should be used for all subsequent accounts. This encourages best practice of the authenticated user being the actual user, while allowing for legacy accounts that require the actual user to use another user's credentials.

At least one primary account should have been successfully linked to the Broker in order for allow_delegation to be used. It is expected that the Booking System persists the authenticated session in a cookie so that the user does not need to log in to the Booking System again.

For compatibility with Booking Systems that require an email address for each account, an additional parameter delegation_login_hint is provided, which can optionally be used by the Booking System to inform the user of the email address that is being used to create the account. For such systems this may default to the authenticated user's email address, if the delegation_login_hint is not provided.

Additionally a parameter of delegation_name_hint allows the UI of the Booking System to display the name of the Broker account to be linked, to help signpost the user appropriately.

When a user is created via allow_delegation, the email address is optionally set via initialisation, and the email field is not required.

An illustration of the allow_delegation flow can be seen in the screenshot below. Note the middle screen would be skipped if the primary account was already logged in, e.g. if they had linked an account previously.

Screenshot 2022-01-20 at 10 52 33

An example of a delegated account creation screen within a system that requires email address for each account, along with an example of a delegated account linking screen is as follows:

Screenshot 2022-01-20 at 10 52 40

For systems that do not require an email address for each account, the email field in the first screen above could simply be omitted.

Dependent Accounts are simply accessed via the endpoints specified in Appendix D, as from the Broker's perspective they appear as standard Customer Accounts, with their own tokens.

It is expected that the Booking System will provide a means to display which Brokers an account is connected to, such that if the Dependent is switched to a different Primary, the new Primary may view a list of connected Brokers and choose to disconnect them.

Advantages

Disadvantages

Concept Options for accounts booking "on behalf of"

Options are presented below. The last of these is recommended by this proposal.

1) Consent synchronisation

In this approach, the consent for users to book on behalf of each other is synchronised between the Broker and the Booking System, for example:

Alternatively, the /accept endpoint only exists on the accounts that are offering access to their personal data, in order to minimise the number of API calls.

If not applied as part of Option 1 above ("Model full groups and permissions") then this would require e.g. one API call for each member of a group.

Advantages

Disadvantages

2) Broker has full authority to make bookings (Recommended)

In this approach, the Booking System allows any accounts that have granted permission to a particular Broker to be used as the subject of an "on-behalf-of" booking.

This is achieved by the Broker simply specifying the @id of any connected Customer Account as the attendee of a booking.

For security, attendee details are not included in the response from C1/C2/B, and must be dereferenced by the Broker if required. The customer details are still included in the response from C1/C2/B, as the customer is always based on the authenticating API key.

For security, an additional /connect/revocation endpoint is required to allow the Customer to explicitly disconnect from the Broker (rather than simply forgetting its authentication tokens). Implementation of this endpoint is also best practice, so it might be helpful to make this explicit in the specification.

Booking on-behalf-of follows the same approach as specified in the Customer Accounts API proposal under the section "Online Booking through a Customer Account", using an @id reference to the relevant Customer Account for the attendee.

C1, C2 and B request extract:

    "attendee": {
      "@type": "Person",
      "hasAccount": "https://eg.com/customer-accounts/fdc14503-275e-46d3-9922-45b986c9f9aa"
    },

Advantages

Disadvantages

matdavies commented 2 years ago

Thanks Nick, very comprehensive write up of the potential solutions.

I must admit that I haven't had a chance to go through all of the proposed solutions with a fine toothed comb, but I'm not sure that will even be necessary if we can go through some of the required use cases and apply them to the recommended solution on one of the calls? IE, take as an assumption that the recommended solution is the right one, and then work through the use cases to figure out exactly and technically how they would work, and to confirm then that there are no GDPR or duplication (which seem to be the major sticking points) issues.

The use cases you have listed are:

For dependent accounts:

For booking on behalf of:

I think it would be useful to go through the process in a "simple" use case (parent creates child and wants to book a slot on behalf of that child, or set the child as the attendee) and a "complex" use case, and given that the free swimming one is the most contentious one, I think it would be helpful to go through that one in detail. IE, how that would work both in the case where the parent and the child already have an account with the booking system, and in the case where neither of them do and are just signing up via the broker. How does that all work from a technical standpoint? That would help me to get a better understanding of the technical implications and might shake out any issues.

One thing I did notice was this comment:

Note to facilitate this flow, the primary account must also set a password when created as a new user via the standard flow.

IIRC, the ability to skip that requirement had some very attractive advantages in the standard membership sign up bits - though I can't 100% remember what they were. I think it simplified things as it allowed the user to create the account with the booking system and the understanding would be that to log in they would follow the standard password reset process in the booking system and off they go. What are the modified implications on the booking system impl if this is no longer the case?

nickevansuk commented 2 years ago

Thanks @matdavies! Your comment has prompted me to rethink the proposal above regarding passwords - the updated proposal above now removes the need for password setting.

Main implications of setting a password were that the user is being asked to set a few different passwords at once if they're hitting the OpenID Connect flow as part of a flow for registering to the Broker, which could be confusing. Additionally the previous proposal for (4) above required users to log out and log in when linking multiple accounts, which creates additional unnecessary steps for the most common use case (i.e. a young family or couple linking accounts together).

I've outlined the old proposal you commented on above below for reference, so we can focus on the issue above in the call shortly. We should be able to address your other comments on the call too.


4b) Dependent accounts are handled within the OpenID Connect Flow, without linking existing accounts

If we remove the ability to link existing accounts from Option 4 described above, then an illustration of the allow_delegation flow can be seen in the screenshot below. Note the middle screen would be skipped if the primary account was already logged in, e.g. if they had linked an account previously.

Screenshot 2022-01-17 at 22 10 00

Note to facilitate this flow, the primary account must also set a password when created as a new user via the standard flow.

To facilitate the flow above when a user is expected to log out and log in to multiple accounts (for example when linking a whole family), it would likely improve the UX for the primary account creation screen to also set a password. This allows the user to log out of the account (for example to connect another account), then log in again to create a delegated subaccount within it, without needing to reset their password and check their email. An example primary account creation screen updated to reflect this is below:

Screenshot 2022-01-20 at 09 25 27

nickevansuk commented 2 years ago

Further considerations from the Technical Working Group call on 20/01/2020:

Dependent accounts - (4) Dependent accounts are handled within the OpenID Connect Flow

Agreement that this should be the chosen way forward, with some considerations as below.

It is possible that a Booking System may implement account duplication checks, and therefore the account initialisation could fail if a duplicate account is found on the system.

Add a CustomerAccountDuplicateDetectedError to the initialisation call, to ensure that a mechanism exists for the Broker to inform the Customer of the error, and display an appropriate error from the Booking System. Additional wireframes could be added as guidance to show how error could be displayed by the Broker in the case that a duplicate is detected.

What if, within the booking system screens, a primary account attempts to link another primary account that already has its own child accounts:

This scenario can be handled within the OpenID Connect Flow, with a flow determined by the Booking System depending on what makes the most sense within its context. A recommendation is that the "Link accounts" list of the second primary is simply presented to the user when they attempt to link, for the user to select the second primary or any dependent of that primary to link to the Broker.

Note: Guidance in spec should recommend avoiding requiring the primary to log out at any point as part of any common user journey, as the primary may not necessarily have set a password and would have to reset it to log back in.

What if more than one of the parents can be a primary within the Booking System?

This can be handled within the OpenID Connect Flow, with a flow determined by the Booking System depending on what makes the most sense within its context. For example it might be possible to allow the user to select to make a user a "primary" account at the point that they are selected for linking within the OpenID Connect flow - i.e. perhaps when John is created or linked the UI includes a tick box saying "Allow this person to manage linked accounts" or similar. The proposal is flexible to allow any grouping model (single primary, multiple primary, multiple group, etc).

What about Customer Accounts for Organizations?

This can be handled within the OpenID Connect Flow, with a flow determined by the Booking System depending on what makes the most sense within its context. Organizations with sub-Organizations, Organizations with People within them, etc can all be handled provided the user can select a single Customer to link through its journey.

What about emergency contact details, do they need to be captured for each dependent account?

GLL and Everyone Active already capture contact details for each account separately, and there is no assumption that the relationship between accounts has any connection to the emergency contact details.

Booking "on behalf of" - (2) Broker has full authority to make bookings

Is the user going to expect to be booked on behalf of, if they don't provide consent for it within the Booking System?

With all options relating to group synchronisation the Broker is already being given authority to link accounts, and trusted to obtain explicit consent from the Customer. Hence it is the Broker's responsibility to ensure that the Customer is clearly communicated to, and that they have have given explicit consent to enable "book on behalf of" within the Broker system between the relevant users.

Note: "booking on behalf of" permissions must be clearly communicated to the user when they connect their account, along with other permissions.

Are there any GDPR implications of this?

Personal data is not shared via "book-on-behalf-of" in the C1, C2 and B calls, so the Broker must have a valid access token to retrieve personal details for each attendee via the Get Customer Account Details call (in the same way as they would otherwise).

What price will the Customer pay if they are being booked by someone else?

The specification should clarify that the price is expected to be the same price a Customer would pay if they were to book themselves, including any member discounts.

Are there privacy concerns relating the case where an account that's being booked on-behalf-of is banned, has debt, etc.?

For privacy, error messages for failed on-behalf-of bookings that require resolution via a change to the state of the target Customer Account MUST NOT include details of issues relating to that Customer Account (for example, a debt or ban on the account). Such errors at C1/C2/B MUST be generic using the BookingOnBehalfOfError OrderItem error ("A booking could not be made on behalf of this account at this time"), and the resolution MUST be described in an outstandingAction available on the target's Customer Account via their own access tokens. This ensures that debt, bans, etc are issues that remain private to each Customer Account.

What about Customer Accounts for Organizations?

Organizations cannot be specified as attendees, and hence an Organization cannot be the target of an on-behalf-of booking.