Add PKCE, token-body extras, AuthURL templating to OAuth2 → Add settings structs for Pattern-2 connector providers
- Add PKCE, token-body extras, AuthURL templating to OAuth2 - Add 13 connector provider enum values - Add scopes, display names, name resolvers for 13 providers - Add settings structs for Pattern-2 connector providers Signed-off-by: Aurélien Sibiril <81782+aureliensibiril@users.noreply.github.com>
This commit is contained in:
@@ -14,7 +14,12 @@
|
||||
|
||||
package connector
|
||||
|
||||
import "go.gearno.de/kit/httpclient"
|
||||
import (
|
||||
"maps"
|
||||
"strings"
|
||||
|
||||
"go.gearno.de/kit/httpclient"
|
||||
)
|
||||
|
||||
// CallbackPath is the HTTP path for the OAuth2 callback endpoint.
|
||||
const CallbackPath = "/api/console/v1/connectors/complete"
|
||||
@@ -30,6 +35,14 @@ type providerDefinition struct {
|
||||
ExtraAuthParams map[string]string
|
||||
TokenEndpointAuth string // "post-form" (default), "basic-form", or "basic-json"
|
||||
SupportsIncrementalAuth bool
|
||||
// RequiresPKCE enables RFC 7636 PKCE (S256) on the authorization
|
||||
// request and replays the verifier on the token exchange. Default
|
||||
// false; existing providers are unaffected.
|
||||
RequiresPKCE bool
|
||||
// TokenExtraParams are merged into the token-exchange request body
|
||||
// (form-encoded for "post-form"/"basic-form", JSON for "basic-json").
|
||||
// Used by providers like Lever that require an `audience` parameter.
|
||||
TokenExtraParams map[string]string
|
||||
}
|
||||
|
||||
// providerDefinitions maps provider names to their static OAuth2 definitions.
|
||||
@@ -91,6 +104,83 @@ var (
|
||||
AuthURL: "https://linear.app/oauth/authorize",
|
||||
TokenURL: "https://api.linear.app/oauth/token",
|
||||
},
|
||||
"GITLAB": {
|
||||
AuthURL: "https://gitlab.com/oauth/authorize",
|
||||
TokenURL: "https://gitlab.com/oauth/token",
|
||||
},
|
||||
// Bitbucket scopes are pinned on the OAuth consumer at registration
|
||||
// time (`account` for workspace membership). They are not passed in
|
||||
// the authorize URL and not configured here.
|
||||
"BITBUCKET": {
|
||||
AuthURL: "https://bitbucket.org/site/oauth2/authorize",
|
||||
TokenURL: "https://bitbucket.org/site/oauth2/access_token",
|
||||
},
|
||||
"HEROKU": {
|
||||
AuthURL: "https://id.heroku.com/oauth/authorize",
|
||||
TokenURL: "https://id.heroku.com/oauth/token",
|
||||
},
|
||||
"PAGERDUTY": {
|
||||
AuthURL: "https://identity.pagerduty.com/oauth/authorize",
|
||||
TokenURL: "https://identity.pagerduty.com/oauth/token",
|
||||
RequiresPKCE: true,
|
||||
},
|
||||
"ASANA": {
|
||||
AuthURL: "https://app.asana.com/-/oauth_authorize",
|
||||
TokenURL: "https://app.asana.com/-/oauth_token",
|
||||
},
|
||||
"SNYK": {
|
||||
AuthURL: "https://app.snyk.io/oauth2/authorize",
|
||||
TokenURL: "https://api.snyk.io/oauth2/token",
|
||||
RequiresPKCE: true,
|
||||
},
|
||||
"NETLIFY": {
|
||||
AuthURL: "https://app.netlify.com/authorize",
|
||||
TokenURL: "https://api.netlify.com/oauth/token",
|
||||
},
|
||||
"RAMP": {
|
||||
AuthURL: "https://app.ramp.com/v1/authorize",
|
||||
TokenURL: "https://api.ramp.com/developer/v1/token",
|
||||
TokenEndpointAuth: "basic-form",
|
||||
},
|
||||
"CLICKUP": {
|
||||
AuthURL: "https://app.clickup.com/api",
|
||||
TokenURL: "https://api.clickup.com/api/v2/oauth/token",
|
||||
},
|
||||
// Vercel uses a templated AuthURL: the operator supplies an
|
||||
// `integration-slug` config field which is resolved into the
|
||||
// "{integration_slug}" placeholder by ApplyProviderDefaults.
|
||||
// Vercel does not use OAuth scopes — capabilities are pinned on
|
||||
// the integration registration in the Vercel dashboard.
|
||||
"VERCEL": {
|
||||
AuthURL: "https://vercel.com/integrations/{integration_slug}/new",
|
||||
TokenURL: "https://api.vercel.com/v2/oauth/access_token",
|
||||
},
|
||||
"MONDAY": {
|
||||
AuthURL: "https://auth.monday.com/oauth2/authorize",
|
||||
TokenURL: "https://auth.monday.com/oauth2/token",
|
||||
},
|
||||
// Lever runs on Auth0: the `audience` parameter is required in
|
||||
// BOTH the authorize URL and the token-exchange POST body. The
|
||||
// trailing slash on the audience value is mandatory.
|
||||
"LEVER": {
|
||||
AuthURL: "https://auth.lever.co/authorize",
|
||||
TokenURL: "https://auth.lever.co/oauth/token",
|
||||
ExtraAuthParams: map[string]string{
|
||||
"audience": "https://api.lever.co/v1/",
|
||||
"prompt": "consent",
|
||||
},
|
||||
TokenExtraParams: map[string]string{
|
||||
"audience": "https://api.lever.co/v1/",
|
||||
},
|
||||
},
|
||||
// Deel: the token endpoint path is "/oauth2/tokens" (plural) —
|
||||
// Deel's docs are inconsistent on the singular vs plural form.
|
||||
// The API base host (api.letsdeel.com) differs from the auth host
|
||||
// (app.deel.com).
|
||||
"DEEL": {
|
||||
AuthURL: "https://app.deel.com/oauth2/authorize",
|
||||
TokenURL: "https://app.deel.com/oauth2/tokens",
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
@@ -108,5 +198,22 @@ func ApplyProviderDefaults(provider string, redirectURI string, c *OAuth2Connect
|
||||
c.ExtraAuthParams = def.ExtraAuthParams
|
||||
c.TokenEndpointAuth = def.TokenEndpointAuth
|
||||
c.SupportsIncrementalAuth = def.SupportsIncrementalAuth
|
||||
c.RequiresPKCE = def.RequiresPKCE
|
||||
|
||||
// Deep copy TokenExtraParams so per-connector mutations cannot
|
||||
// alias back into the shared providerDefinitions map.
|
||||
if len(def.TokenExtraParams) > 0 {
|
||||
tokenExtra := make(map[string]string, len(def.TokenExtraParams))
|
||||
maps.Copy(tokenExtra, def.TokenExtraParams)
|
||||
c.TokenExtraParams = tokenExtra
|
||||
}
|
||||
|
||||
// Resolve operator-supplied placeholders in the static AuthURL
|
||||
// (for example Vercel's "{integration_slug}"). Providers without
|
||||
// placeholders are unaffected; the loop is a no-op when
|
||||
// AuthURLParams is empty.
|
||||
for k, v := range c.AuthURLParams {
|
||||
c.AuthURL = strings.ReplaceAll(c.AuthURL, "{"+k+"}", v)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user