Search code examples
oauth-2.0identityserver4openid-connect

Should a headless desktop client web-service client be a dynamically-registered OIDC client - or something else?


My set-up has the following:

  • This is a multi-tenant system, so the set of User Claims includes tenant_id which uniquely identifies the tenant that the user belongs to.
  • An IdentityServer4-based web-service (this provides OAuth2/OpenID Connect services): https://identity.example.com.
  • A separate web-service (RESTful web-api): https://random-number-generator-service.example.com.
  • A headless program (Windows Service) that runs on on-premises computers at many locations: RandomNumberConsumer.exe. This program makes use of random-number-generator-service in the context of a tenant_id so a user needs to authenticate at some point somehow but otherwise the program does not care about the user's details, only the user's tenant's details.

I understand this means that both random-number-generator-service and RandomNumberConsumer.exe are "clients".

Within IdentityServer all client software must be registered (either statically as a hardcoded list of Client object instances or with some kind of dynamic registration using a database to store client details. Obviously random-number-generator-service will have a static registration, but how should RandomNumberConsumer.exe also be registered?

Some options:

  1. Add a new web-application that users can login-to using a web-browser and register their RandomNumberConsumer.exe installation (which adds a new Client registration in identity.example.com's Client database, complete with a client secret) then the user manually copies and pastes the client secret into RandomNumberConsumer.exe's configuration file. The internal database maps each client registration with the tenant_id. This has the advantage of allowing individual client access revocation, but requires the user to perform manual configuration steps which are undesirable.
  2. Have a single Client registration for RandomNumberConsumer.exe without any Client Secret, but the Client application needs a GUI component with which it can authenticate the user and it stores the user's associated access_token and refresh_token in its local configuration. This has the advantage of having a much simpler user-experience (as the user would open a RandomNumberConsumerConfiguration.exe program which then opens the web-browser to access the authentication page and gets the data using a redirect_uri with a temporary localhost or custom URI scheme value) but it means the RandomNumberConsumer.exe instance is associated with an individual human user when we only want it to be associated with the tenant instead.

Are there any other approaches that could be used instead?


Solution

  • Every instance of a client should have it's own id. random-number-generator-service should have one id (even when it runs in a web farm).

    RandomNumberConsumer.exe is installed on different machines outside the domain, so should have a unique id per installation.

    A client has nothing to do with a user as the sub claim is missing. The only time the client includes the sub claim is when it acts on behalf (and with consent) of the user. This can be the case for random-number-generator-service, but not for RandomNumberConsumer.exe where there is no user interaction (as it is a Windows Service) and consent is not needed as it is given when the user requested the installation.

    When you are talking about a Windows Service then it is inevitable to configure the service. You can however implement configuration steps in the installer. So instead of having to build UI or hacking a configuration file, you can take the following approach:

    1. User requests an installation of the program. When approved a client is created and attached to the tenant (ClientClaims), based on the user.
    2. The user starts the download of the installer and receives the id/secret (on screen, email).
    3. User starts the installation and in one of the steps the user has to enter the id/secret. This is acceptable since it is quite common when installing software.

    This has the advantages you want and takes minimal steps from the user.

    If the service has more configuration options and you want to give the user a UI to maintain the options then add a configuration program to the installer. This is quite common for routers and printers. There is no need for the user to login as it runs local (localhost website). You can add a link for the browser as shortcut.