Skip to content

Offline delegation: let approved applications act on behalf of an absent user #1814

Description

@DmytroZaichenkoDev

Problem

An application that runs when the user is not present — the Scheduler is the motivating case —
needs to call DIAL as that user, with that user's current permissions, days after the user set
the task up.

Today this is done with an OAuth external service: the user logs in at the identity provider and a
stored refresh token is redeemed before each run. It works, but the login is per application and
per service
, so every application that wants offline behaviour drags the user through its own IdP
round-trip and keeps its own refresh token. Each one is a separate long-lived credential to store,
rotate and revoke.

Proposal

Move the round-trip rather than remove it: once per user, platform-wide, instead of once per
application.

Two decisions, made by two different people:

Who Decides Recorded as
The user may DIAL act as me while I am away? offline credentials — one refresh token, platform-wide, never handed to an application
A DIAL admin may this application use that, for anyone? admin consent — one record per (application, service)

Neither works alone: credentials with no consent reach no application, and consent with no
credentials has no identity to act with.

The user is not asked about individual applications. Their consent is to offline use of their own
identity; which applications may exercise it is an administrative decision. This is a real trade
and should be agreed deliberately
— an admin's approval reaches every user who has enabled offline
credentials, not only users who opted into that application. It mirrors how enterprise IdPs handle
admin consent, and it is what keeps the feature deployable without prompting every user about every
app.

Scope — core

  • GET/POST /v1/user/offline-credentials, /signin, /signout — the user's own credentials.
    Status doubles as "how to connect", so chat needs no per-provider configuration of its own.
  • A per-provider offline OAuth client in the identity-provider settings, distinct from chat's
    client. Its refresh token is what scheduled runs depend on.
  • POST/DELETE /v1/applications/{appId}/external-services/{id}/consent — admin only.
  • A DIAL_NATIVE authentication type, and a redemption branch on /obo-credentials that checks
    consent, refreshes only when the stored token has expired, and returns the access token.
  • Audit events naming the application and the owner — the only record tying an action to an app.
  • A status contract that does not pretend a per-service login exists for this type.

🤖 Generated with Claude Code

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    Status
    No status

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions