Search code examples
authenticationoauth-2.0authorizationopeniddictasp.net-core-7.0

Should I use a single set of client_id/client_secret for my client credentials flow?


I’ve implemented an authorisation server using Asp.Net 7 and OpenIdDict.

The system will have multiple tenants, each with numerous client devices that require authentication.

Here’s the setup:

There’s a single authentication server implemented in Asp.Net 7 using OpenIdDict.

  • There are multiple services (APIs/resource servers).
  • There are multiple tenants.
  • Each tenant has numerous devices, potentially hundreds.
  • Each device is a PC running a Windows/Linux background service application (without a GUI) that needs to authenticate with the authentication server to obtain a JWT access token. This token will be used to connect to the APIs/resource servers.

The process would look like this:

  1. For each device, the tenant would request a configuration file.
  2. This file would contain an encrypted client_id and client_secret specific to the device.
  3. The file would be imported into the device, so it knows its client_id and client_secret.
  4. The device would then use these credentials to obtain an access_token from the authorisation server.

Questions:

  1. Should I use the Client Credentials flow since there’s no GUI on the devices and I don’t want any browser-based interactions? I’ve also considered using the Device Credentials flow, but I’m unsure how this would work without browser support.

  2. There will be many devices across many tenants (potentially thousands), and I’ll need to create clients on request. Is this possible with OpenIdDict?

  3. Should I opt for a single client_id/client_secret combination for all devices, resulting in just one client registration on the auth server? Or should I choose multiple client_id/client_secret pairs, one for each device, resulting in thousands of clients registered on the Auth server)?


Solution

  • Should I use the Client Credentials flow since there’s no GUI on the devices and I don’t want any browser-based interactions? I’ve also considered using the Device Credentials flow, but I’m unsure how this would work without browser support.

    Yes, use the Client Credentials flow.

    You're doing machine-to-machine authorisation with no end-user interaction, via a browser or other medium - which is the use case for this flow.

    The (Limited-Input) Device Authorisation flow wouldn't work as you don't have an end user nor a browser. That flow is for devices that do not have an easy way to enter text e.g. a games console or - but still have an end user. The user is still asked to enter a device_code at a verification_url on a device with richer input capabilities.

    You can't do that via a background service.


    1. There will be many devices across many tenants (potentially thousands), and I’ll need to create clients on request. Is this possible with OpenIdDict?

    That's perfectly possible.

    There's no technical limitations on how many clients you can have, other than limitations imposed by your infrastructure & you can create clients on request.


    1. Should I opt for a single client_id/client_secret combination for all devices, resulting in just one client registration on the auth server? Or should I choose multiple client_id/client_secret pairs, one for each device, resulting in thousands of clients registered on the Auth server)?

    This is dependent on your requirements - there's no universally right or wrong answer.

    The choice between using a single client_id/client_secret or multiple pairs will be primarily related to access control, security, maintenance and isolation.

    For your scenario, I would consider the below:

    1. A client will be tied to a specific set of scopes (resources) that they are allowed to access. If you want to provide different access levels and permissions to each device/tenant, then you need to use multiple clients. This is the biggest factor, as varying levels of access to user data is why I assume you're doing this in the first place.

    2. If you use a single set of credentials for all devices/tenants and credentials for a device/tenant were compromised, you would need to update the credentials on all devices/tenants. This would have a much larger impact than just updating the credentials for one device/tenant.

    3. Managing 1000s of clients is challenging. Try to reach a compromise - if each device for a tenant will share the same access and permissions, then having one client ID per tenant is much easier to manage than having one per device. Having one per device might not really be needed.

    4. Using unique credentials per device/tenant ensures that actions are isolated. This allows you to track exactly when and by whom actions were performed. In multi-tenant environments, clients usually expect isolation and. therefore, at a minimum, you might want to consider implementing one client ID per tenant. This will also help if you want to rate limit devices/tenants or gather stats at a device/tenant level.

    All in all, base it around domains of shared access and your isolation requirements.