Add DocuSign partner OAuth2 with PKCE and picker
DocuSign approved our partner integration, so the connector can now
complete a real OAuth2 authorization-code flow. The integration key
has PKCE enabled, so RequiresPKCE is set; the confidential grant still
authenticates the token exchange with Basic auth and replays the
verifier as the documented hardening layer.
A DocuSign user may have access to several accounts, so this replaces
the previous auto-default-account behavior with a Pattern-1 picker:
the user chooses the account after OAuth, the choice is stored on
DocuSignConnectorSettings, and the driver and name resolver resolve
the selected account's data-center base URI from /oauth/userinfo.
Other changes:
- Request the extended scope so the refresh token's 30-day window
rolls on each use; without it the token hard-expires 30 days after
consent and breaks the connection.
- Drop API-key support: DocuSign has no static API key, only OAuth.
- Return ("", nil) from the name resolver on terminal failures so the
source-name worker does not retry a revoked token forever.
- Add a driver test and cassette; the test previously skipped in CI
for lack of a cassette.
Signed-off-by: Aurélien Sibiril <81782+aureliensibiril@users.noreply.github.com>
This commit is contained in:
@@ -16,6 +16,7 @@ package provider
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"go.gearno.de/kit/log"
|
||||
@@ -31,13 +32,40 @@ func docusignRegistration() *Registration {
|
||||
TokenURL: "https://account.docusign.com/oauth/token",
|
||||
TokenEndpointAuth: "basic-form",
|
||||
ProbeURL: "https://account.docusign.com/oauth/userinfo",
|
||||
OAuth2Scopes: []string{"signature"},
|
||||
SupportsAPIKey: true,
|
||||
NewDriver: func(_ context.Context, c *http.Client, _ *coredata.Connector, _ *log.Logger) (drivers.Driver, error) {
|
||||
return drivers.NewDocuSignDriver(c), nil
|
||||
// signature grants the eSignature REST API (the userinfo probe and
|
||||
// the account users list). extended rolls the 30-day refresh-token
|
||||
// window on every refresh so the connection survives long-term — the
|
||||
// review engine persists the rotated token on each poll. Without it
|
||||
// the refresh token hard-expires 30 days after the initial consent.
|
||||
OAuth2Scopes: []string{"signature", "extended"},
|
||||
// DocuSign enables PKCE (S256) on the integration key. The confidential
|
||||
// authorization-code grant still authenticates the token exchange with
|
||||
// Basic auth (basic-form); PKCE rides along as the documented hardening
|
||||
// layer, replaying the verifier in the token request body.
|
||||
RequiresPKCE: true,
|
||||
NewDriver: func(_ context.Context, c *http.Client, conn *coredata.Connector, _ *log.Logger) (drivers.Driver, error) {
|
||||
s, err := coredata.ConnectorSettings[coredata.DocuSignConnectorSettings](conn)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot read docusign connector settings: %w", err)
|
||||
}
|
||||
|
||||
if s.AccountID == "" {
|
||||
return nil, fmt.Errorf("cannot create docusign driver: account_id is required")
|
||||
}
|
||||
|
||||
return drivers.NewDocuSignDriver(c, s.AccountID), nil
|
||||
},
|
||||
NewNameResolver: func(_ context.Context, c *http.Client, _ *coredata.Connector, _ *log.Logger) drivers.NameResolver {
|
||||
return drivers.NewDocuSignNameResolver(c)
|
||||
NewNameResolver: func(ctx context.Context, c *http.Client, conn *coredata.Connector, logger *log.Logger) drivers.NameResolver {
|
||||
s, err := coredata.ConnectorSettings[coredata.DocuSignConnectorSettings](conn)
|
||||
if err != nil {
|
||||
logger.ErrorCtx(ctx, "cannot read docusign connector settings", log.Error(err))
|
||||
return nil
|
||||
}
|
||||
|
||||
return drivers.NewDocuSignNameResolver(c, s.AccountID)
|
||||
},
|
||||
SetOrganizationSettings: func(c *coredata.Connector, accountID string) error {
|
||||
return c.SetSettings(&coredata.DocuSignConnectorSettings{AccountID: accountID})
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user