From 8c413daf9a4d6587d52302e596a9f01e172a03cb Mon Sep 17 00:00:00 2001 From: Jon Langevin Date: Wed, 13 May 2026 06:44:41 -0400 Subject: [PATCH] fix: close 3 strict-proto config-field gaps surfaced by BMW local smoke MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit BMW local smoke against workflow v0.51.5 surfaced three step types whose typed config protos were rejecting BMW-supplied fields. v0.2.2 adds the missing fields and a new config message: - AuthMethodsPolicyConfig / AuthMethodsPolicyInput (step.auth_methods_policy, step.auth_policy_audit): add jwt_secret, sms_auth_enabled, and 6 oauth client_id/secret fields (facebook/instagram/x). - AuthPolicyGateConfig (step.auth_policy_gate): add tenant_id. - step.auth_challenge_verify: replace EmptyConfig with new AuthChallengeVerifyConfig { signing_secret }. Handler now falls back to the config value when input does not carry one. Also adds .github/workflows/workflow-compat.yml — daily + per-PR job that installs the LATEST published wfctl release, builds this plugin, and validates a fixture pipeline exercising every step type. Catches drift between this plugin's proto descriptors and the next workflow release the day it ships, rather than the next time BMW smokes. Deferred (BMW yaml bug — no plugin change): step.auth_oauth_exchange currently receives `code` inside its config: block, but the handler reads `code` from OAuthProviderInput. BMW must move `code` to a runtime input. Co-Authored-By: Claude Opus 4.7 (1M context) --- .github/fixtures/workflow-compat.yaml | 179 ++++++++++ .github/workflows/workflow-compat.yml | 73 +++++ CHANGELOG.md | 33 ++ internal/contracts/auth.pb.go | 448 +++++++++++++++++++------- internal/contracts/auth.proto | 21 ++ internal/plugin.go | 4 +- internal/step_challenge.go | 14 +- internal/strict_proto_fields_test.go | 122 +++++++ plugin.contracts.json | 2 +- plugin.json | 10 +- 10 files changed, 773 insertions(+), 133 deletions(-) create mode 100644 .github/fixtures/workflow-compat.yaml create mode 100644 .github/workflows/workflow-compat.yml create mode 100644 CHANGELOG.md create mode 100644 internal/strict_proto_fields_test.go diff --git a/.github/fixtures/workflow-compat.yaml b/.github/fixtures/workflow-compat.yaml new file mode 100644 index 0000000..ed5df3e --- /dev/null +++ b/.github/fixtures/workflow-compat.yaml @@ -0,0 +1,179 @@ +# Smoke fixture for workflow-compat CI: exercises every step type this +# plugin exposes, using the BMW-supplied config field shapes that v0.2.2 +# closed. Validated by `wfctl validate` against the LATEST wfctl release +# in .github/workflows/workflow-compat.yml. + +modules: + - name: auth-credential + type: auth.credential + config: + rp_display_name: "Compat Smoke" + rp_id: "example.test" + origin: "https://example.test" + optional: true + +workflows: + smoke: + trigger: + type: http + config: + path: /smoke + method: POST + steps: + - name: methods_policy + type: step.auth_methods_policy + config: + environment: "development" + password_auth_enabled: true + totp_auth_enabled: false + webauthn_rp_id: "example.test" + webauthn_origin: "https://example.test" + smtp_host: "smtp.example.test" + smtp_from: "noreply@example.test" + auth_routes_enabled: true + routes_enabled: true + oauth_routes_enabled: true + google_oauth_client_id: "google-client" + google_oauth_client_secret: "google-secret" + google_oauth_redirect_url: "https://example.test/cb" + # Fields added in v0.2.2 — strict-proto rejection gaps closed: + jwt_secret: "test-jwt-secret" + sms_auth_enabled: false + facebook_oauth_client_id: "fb-client" + facebook_oauth_client_secret: "fb-secret" + instagram_oauth_client_id: "ig-client" + instagram_oauth_client_secret: "ig-secret" + x_oauth_client_id: "x-client" + x_oauth_client_secret: "x-secret" + twilio_verify_service_sid: "VA000" + twilio_account_sid: "AC000" + twilio_auth_token: "twilio-token" + twilio_api_key_sid: "SK000" + twilio_api_key_secret: "twilio-key-secret" + password_hash_count: 0 + + - name: policy_gate + type: step.auth_policy_gate + config: + policy_step: methods_policy + signing_secret: "test-secret" + jwt_secret: "test-jwt-secret" + required_runtime_keys: + - tenant_id + oauth_supported_providers: + - google + # Added in v0.2.2: + tenant_id: "tenant-smoke" + + - name: methods_response + type: step.auth_methods_response + + - name: policy_audit + type: step.auth_policy_audit + config: + environment: "development" + password_auth_enabled: true + jwt_secret: "test-jwt-secret" + + - name: passkey_begin_register + type: step.auth_passkey_begin_register + config: + module: auth-credential + + - name: passkey_finish_register + type: step.auth_passkey_finish_register + config: + module: auth-credential + + - name: passkey_begin_login + type: step.auth_passkey_begin_login + config: + module: auth-credential + + - name: passkey_finish_login + type: step.auth_passkey_finish_login + config: + module: auth-credential + + - name: totp_generate_secret + type: step.auth_totp_generate_secret + + - name: totp_verify + type: step.auth_totp_verify + + - name: totp_recovery_codes + type: step.auth_totp_recovery_codes + + - name: magic_link_generate + type: step.auth_magic_link_generate + + - name: magic_link_verify + type: step.auth_magic_link_verify + + - name: magic_link_send + type: step.auth_magic_link_send + config: + smtp_host: "smtp.example.test" + smtp_port: 587 + smtp_user: "smtp-user" + smtp_pass: "smtp-pass" + from_address: "noreply@example.test" + + - name: password_hash + type: step.auth_password_hash + + - name: password_verify + type: step.auth_password_verify + + - name: challenge_generate + type: step.auth_challenge_generate + + - name: challenge_verify + type: step.auth_challenge_verify + config: + # Field added in v0.2.2 (replaced EmptyConfig): + signing_secret: "test-secret" + + - name: normalize_phone + type: step.auth_normalize_phone + + - name: oauth_provider_config + type: step.auth_oauth_provider_config + config: + provider: google + google_oauth_client_id: "google-client" + google_oauth_client_secret: "google-secret" + google_oauth_redirect_url: "https://example.test/cb" + + - name: oauth_start + type: step.auth_oauth_start + config: + provider: google + google_oauth_client_id: "google-client" + google_oauth_client_secret: "google-secret" + google_oauth_redirect_url: "https://example.test/cb" + + - name: oauth_exchange + type: step.auth_oauth_exchange + config: + provider: google + google_oauth_client_id: "google-client" + google_oauth_client_secret: "google-secret" + google_oauth_redirect_url: "https://example.test/cb" + # Note: BMW currently passes `code` here — that is a BMW yaml bug. + # `code` belongs in OAuthProviderInput (i.e. via a preceding + # step.set or trigger.query). Not present in this fixture. + + - name: oauth_userinfo + type: step.auth_oauth_userinfo + config: + provider: google + google_oauth_client_id: "google-client" + google_oauth_client_secret: "google-secret" + google_oauth_redirect_url: "https://example.test/cb" + + - name: credential_list + type: step.auth_credential_list + + - name: credential_revoke + type: step.auth_credential_revoke diff --git a/.github/workflows/workflow-compat.yml b/.github/workflows/workflow-compat.yml new file mode 100644 index 0000000..bcba59e --- /dev/null +++ b/.github/workflows/workflow-compat.yml @@ -0,0 +1,73 @@ +name: Workflow Compat (latest wfctl) + +# Continuously verify this plugin's strict-proto contracts stay compatible +# with the LATEST published wfctl release — independently of the SDK +# version pinned in go.mod. Surfaces drift the same day a workflow release +# introduces a stricter validator. + +on: + push: + branches: [main] + pull_request: + branches: [main] + schedule: + # Daily at 09:00 UTC so any post-merge workflow release surfaces drift. + - cron: "0 9 * * *" + +permissions: + contents: read + +env: + GOPRIVATE: github.com/GoCodeAlone/* + +jobs: + validate-against-latest: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-go@v5 + with: + go-version-file: go.mod + + - name: Configure Git for private repos + env: + RELEASES_TOKEN: ${{ secrets.RELEASES_TOKEN }} + run: | + if [ -n "$RELEASES_TOKEN" ]; then + git config --global url."https://x-access-token:${RELEASES_TOKEN}@github.com/".insteadOf "https://github.com/" + fi + + - name: Resolve latest wfctl release tag + id: wfctl + run: | + tag=$(curl -fsSL https://api.github.com/repos/GoCodeAlone/workflow/releases/latest | jq -r .tag_name) + echo "tag=$tag" >> "$GITHUB_OUTPUT" + echo "Latest wfctl tag: $tag" + + - uses: GoCodeAlone/setup-wfctl@bcd880980f5bbe8d192d0c20ff6279d25331f956 + with: + version: ${{ steps.wfctl.outputs.tag }} + + - name: Validate plugin manifest strict-contracts + run: wfctl plugin validate --file plugin.json --strict-contracts + + - name: Build plugin binary + run: | + mkdir -p bin + go build -o bin/workflow-plugin-auth ./cmd/workflow-plugin-auth + + - name: Stage plugin for wfctl plugin-dir discovery + run: | + mkdir -p /tmp/wfctl-plugins/workflow-plugin-auth + cp bin/workflow-plugin-auth plugin.json plugin.contracts.json /tmp/wfctl-plugins/workflow-plugin-auth/ + + - name: Validate fixture pipeline (latest wfctl + plugin discovery) + run: | + # Smoke fixture exercises every plugin step type. plugin-dir + # makes wfctl load this plugin's contracts, so any drift between + # the BMW-supplied config shapes and the plugin's strict-proto + # descriptors will surface as a config-validation failure. + wfctl validate \ + --plugin-dir /tmp/wfctl-plugins \ + -allow-no-entry-points \ + .github/fixtures/workflow-compat.yaml diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..75d2ce2 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,33 @@ +# Changelog + +## v0.2.2 (2026-05-13) + +### Strict-proto config-field gaps closed (BMW local smoke vs workflow v0.51.5) + +- `AuthMethodsPolicyConfig`/`AuthMethodsPolicyInput` (used by `step.auth_methods_policy` + and `step.auth_policy_audit`): added BMW-supplied fields that the typed proto + was rejecting under strict-contracts: + - `jwt_secret` (string, tag 24) + - `sms_auth_enabled` (optional bool, tag 25) — alongside existing `sms_enabled` + - `facebook_oauth_client_id`, `facebook_oauth_client_secret` (tags 26-27) + - `instagram_oauth_client_id`, `instagram_oauth_client_secret` (tags 28-29) + - `x_oauth_client_id`, `x_oauth_client_secret` (tags 30-31) +- `AuthPolicyGateConfig` (used by `step.auth_policy_gate`): added + - `tenant_id` (string, tag 6) — BMW supplies this directly in the gate config block +- `step.auth_challenge_verify`: replaced `EmptyConfig` with new + `AuthChallengeVerifyConfig { string signing_secret = 1; }`. The handler now + falls back to `config.signing_secret` when input does not carry one. + +### Known deferred (BMW yaml bug — does not require plugin change) + +- `step.auth_oauth_exchange`: BMW currently passes `code` inside the step's + `config:` block. The handler reads `code` from `req.Input` (or merged + `current`) — `code` belongs in `OAuthProviderInput`, not `OAuthProviderConfig`. + BMW must move it to a runtime input (e.g. `current.code`, supplied via a + preceding `step.set` from `parse_request.query.code`). No plugin change made. + +### CI + +- New `.github/workflows/workflow-compat.yml` runs on every PR: + builds the plugin, installs latest `wfctl` release, and validates a + minimal smoke pipeline that exercises every plugin step type. diff --git a/internal/contracts/auth.pb.go b/internal/contracts/auth.pb.go index 62824bd..e66d036 100644 --- a/internal/contracts/auth.pb.go +++ b/internal/contracts/auth.pb.go @@ -2167,32 +2167,40 @@ func (x *NormalizePhoneOutput) GetError() string { } type AuthMethodsPolicyConfig struct { - state protoimpl.MessageState `protogen:"open.v1"` - Environment string `protobuf:"bytes,1,opt,name=environment,proto3" json:"environment,omitempty"` - PasswordAuthEnabled *bool `protobuf:"varint,2,opt,name=password_auth_enabled,json=passwordAuthEnabled,proto3,oneof" json:"password_auth_enabled,omitempty"` - PasswordEnabled *bool `protobuf:"varint,3,opt,name=password_enabled,json=passwordEnabled,proto3,oneof" json:"password_enabled,omitempty"` - TotpAuthEnabled *bool `protobuf:"varint,4,opt,name=totp_auth_enabled,json=totpAuthEnabled,proto3,oneof" json:"totp_auth_enabled,omitempty"` - TotpEnabled *bool `protobuf:"varint,5,opt,name=totp_enabled,json=totpEnabled,proto3,oneof" json:"totp_enabled,omitempty"` - WebauthnRpId string `protobuf:"bytes,6,opt,name=webauthn_rp_id,json=webauthnRpId,proto3" json:"webauthn_rp_id,omitempty"` - WebauthnOrigin string `protobuf:"bytes,7,opt,name=webauthn_origin,json=webauthnOrigin,proto3" json:"webauthn_origin,omitempty"` - SmtpHost string `protobuf:"bytes,8,opt,name=smtp_host,json=smtpHost,proto3" json:"smtp_host,omitempty"` - SmtpFrom string `protobuf:"bytes,9,opt,name=smtp_from,json=smtpFrom,proto3" json:"smtp_from,omitempty"` - AuthRoutesEnabled *bool `protobuf:"varint,10,opt,name=auth_routes_enabled,json=authRoutesEnabled,proto3,oneof" json:"auth_routes_enabled,omitempty"` - RoutesEnabled *bool `protobuf:"varint,11,opt,name=routes_enabled,json=routesEnabled,proto3,oneof" json:"routes_enabled,omitempty"` - OauthRoutesEnabled *bool `protobuf:"varint,12,opt,name=oauth_routes_enabled,json=oauthRoutesEnabled,proto3,oneof" json:"oauth_routes_enabled,omitempty"` - GoogleOauthClientId string `protobuf:"bytes,13,opt,name=google_oauth_client_id,json=googleOauthClientId,proto3" json:"google_oauth_client_id,omitempty"` - GoogleOauthClientSecret string `protobuf:"bytes,14,opt,name=google_oauth_client_secret,json=googleOauthClientSecret,proto3" json:"google_oauth_client_secret,omitempty"` - GoogleOauthRedirectUrl string `protobuf:"bytes,15,opt,name=google_oauth_redirect_url,json=googleOauthRedirectUrl,proto3" json:"google_oauth_redirect_url,omitempty"` - OauthProvider string `protobuf:"bytes,16,opt,name=oauth_provider,json=oauthProvider,proto3" json:"oauth_provider,omitempty"` - SmsEnabled *bool `protobuf:"varint,17,opt,name=sms_enabled,json=smsEnabled,proto3,oneof" json:"sms_enabled,omitempty"` - TwilioVerifyServiceSid string `protobuf:"bytes,18,opt,name=twilio_verify_service_sid,json=twilioVerifyServiceSid,proto3" json:"twilio_verify_service_sid,omitempty"` - TwilioAccountSid string `protobuf:"bytes,19,opt,name=twilio_account_sid,json=twilioAccountSid,proto3" json:"twilio_account_sid,omitempty"` - TwilioAuthToken string `protobuf:"bytes,20,opt,name=twilio_auth_token,json=twilioAuthToken,proto3" json:"twilio_auth_token,omitempty"` - TwilioApiKeySid string `protobuf:"bytes,21,opt,name=twilio_api_key_sid,json=twilioApiKeySid,proto3" json:"twilio_api_key_sid,omitempty"` - TwilioApiKeySecret string `protobuf:"bytes,22,opt,name=twilio_api_key_secret,json=twilioApiKeySecret,proto3" json:"twilio_api_key_secret,omitempty"` - PasswordHashCount int32 `protobuf:"varint,23,opt,name=password_hash_count,json=passwordHashCount,proto3" json:"password_hash_count,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Environment string `protobuf:"bytes,1,opt,name=environment,proto3" json:"environment,omitempty"` + PasswordAuthEnabled *bool `protobuf:"varint,2,opt,name=password_auth_enabled,json=passwordAuthEnabled,proto3,oneof" json:"password_auth_enabled,omitempty"` + PasswordEnabled *bool `protobuf:"varint,3,opt,name=password_enabled,json=passwordEnabled,proto3,oneof" json:"password_enabled,omitempty"` + TotpAuthEnabled *bool `protobuf:"varint,4,opt,name=totp_auth_enabled,json=totpAuthEnabled,proto3,oneof" json:"totp_auth_enabled,omitempty"` + TotpEnabled *bool `protobuf:"varint,5,opt,name=totp_enabled,json=totpEnabled,proto3,oneof" json:"totp_enabled,omitempty"` + WebauthnRpId string `protobuf:"bytes,6,opt,name=webauthn_rp_id,json=webauthnRpId,proto3" json:"webauthn_rp_id,omitempty"` + WebauthnOrigin string `protobuf:"bytes,7,opt,name=webauthn_origin,json=webauthnOrigin,proto3" json:"webauthn_origin,omitempty"` + SmtpHost string `protobuf:"bytes,8,opt,name=smtp_host,json=smtpHost,proto3" json:"smtp_host,omitempty"` + SmtpFrom string `protobuf:"bytes,9,opt,name=smtp_from,json=smtpFrom,proto3" json:"smtp_from,omitempty"` + AuthRoutesEnabled *bool `protobuf:"varint,10,opt,name=auth_routes_enabled,json=authRoutesEnabled,proto3,oneof" json:"auth_routes_enabled,omitempty"` + RoutesEnabled *bool `protobuf:"varint,11,opt,name=routes_enabled,json=routesEnabled,proto3,oneof" json:"routes_enabled,omitempty"` + OauthRoutesEnabled *bool `protobuf:"varint,12,opt,name=oauth_routes_enabled,json=oauthRoutesEnabled,proto3,oneof" json:"oauth_routes_enabled,omitempty"` + GoogleOauthClientId string `protobuf:"bytes,13,opt,name=google_oauth_client_id,json=googleOauthClientId,proto3" json:"google_oauth_client_id,omitempty"` + GoogleOauthClientSecret string `protobuf:"bytes,14,opt,name=google_oauth_client_secret,json=googleOauthClientSecret,proto3" json:"google_oauth_client_secret,omitempty"` + GoogleOauthRedirectUrl string `protobuf:"bytes,15,opt,name=google_oauth_redirect_url,json=googleOauthRedirectUrl,proto3" json:"google_oauth_redirect_url,omitempty"` + OauthProvider string `protobuf:"bytes,16,opt,name=oauth_provider,json=oauthProvider,proto3" json:"oauth_provider,omitempty"` + SmsEnabled *bool `protobuf:"varint,17,opt,name=sms_enabled,json=smsEnabled,proto3,oneof" json:"sms_enabled,omitempty"` + TwilioVerifyServiceSid string `protobuf:"bytes,18,opt,name=twilio_verify_service_sid,json=twilioVerifyServiceSid,proto3" json:"twilio_verify_service_sid,omitempty"` + TwilioAccountSid string `protobuf:"bytes,19,opt,name=twilio_account_sid,json=twilioAccountSid,proto3" json:"twilio_account_sid,omitempty"` + TwilioAuthToken string `protobuf:"bytes,20,opt,name=twilio_auth_token,json=twilioAuthToken,proto3" json:"twilio_auth_token,omitempty"` + TwilioApiKeySid string `protobuf:"bytes,21,opt,name=twilio_api_key_sid,json=twilioApiKeySid,proto3" json:"twilio_api_key_sid,omitempty"` + TwilioApiKeySecret string `protobuf:"bytes,22,opt,name=twilio_api_key_secret,json=twilioApiKeySecret,proto3" json:"twilio_api_key_secret,omitempty"` + PasswordHashCount int32 `protobuf:"varint,23,opt,name=password_hash_count,json=passwordHashCount,proto3" json:"password_hash_count,omitempty"` + JwtSecret string `protobuf:"bytes,24,opt,name=jwt_secret,json=jwtSecret,proto3" json:"jwt_secret,omitempty"` + SmsAuthEnabled *bool `protobuf:"varint,25,opt,name=sms_auth_enabled,json=smsAuthEnabled,proto3,oneof" json:"sms_auth_enabled,omitempty"` + FacebookOauthClientId string `protobuf:"bytes,26,opt,name=facebook_oauth_client_id,json=facebookOauthClientId,proto3" json:"facebook_oauth_client_id,omitempty"` + FacebookOauthClientSecret string `protobuf:"bytes,27,opt,name=facebook_oauth_client_secret,json=facebookOauthClientSecret,proto3" json:"facebook_oauth_client_secret,omitempty"` + InstagramOauthClientId string `protobuf:"bytes,28,opt,name=instagram_oauth_client_id,json=instagramOauthClientId,proto3" json:"instagram_oauth_client_id,omitempty"` + InstagramOauthClientSecret string `protobuf:"bytes,29,opt,name=instagram_oauth_client_secret,json=instagramOauthClientSecret,proto3" json:"instagram_oauth_client_secret,omitempty"` + XOauthClientId string `protobuf:"bytes,30,opt,name=x_oauth_client_id,json=xOauthClientId,proto3" json:"x_oauth_client_id,omitempty"` + XOauthClientSecret string `protobuf:"bytes,31,opt,name=x_oauth_client_secret,json=xOauthClientSecret,proto3" json:"x_oauth_client_secret,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *AuthMethodsPolicyConfig) Reset() { @@ -2386,33 +2394,97 @@ func (x *AuthMethodsPolicyConfig) GetPasswordHashCount() int32 { return 0 } +func (x *AuthMethodsPolicyConfig) GetJwtSecret() string { + if x != nil { + return x.JwtSecret + } + return "" +} + +func (x *AuthMethodsPolicyConfig) GetSmsAuthEnabled() bool { + if x != nil && x.SmsAuthEnabled != nil { + return *x.SmsAuthEnabled + } + return false +} + +func (x *AuthMethodsPolicyConfig) GetFacebookOauthClientId() string { + if x != nil { + return x.FacebookOauthClientId + } + return "" +} + +func (x *AuthMethodsPolicyConfig) GetFacebookOauthClientSecret() string { + if x != nil { + return x.FacebookOauthClientSecret + } + return "" +} + +func (x *AuthMethodsPolicyConfig) GetInstagramOauthClientId() string { + if x != nil { + return x.InstagramOauthClientId + } + return "" +} + +func (x *AuthMethodsPolicyConfig) GetInstagramOauthClientSecret() string { + if x != nil { + return x.InstagramOauthClientSecret + } + return "" +} + +func (x *AuthMethodsPolicyConfig) GetXOauthClientId() string { + if x != nil { + return x.XOauthClientId + } + return "" +} + +func (x *AuthMethodsPolicyConfig) GetXOauthClientSecret() string { + if x != nil { + return x.XOauthClientSecret + } + return "" +} + type AuthMethodsPolicyInput struct { - state protoimpl.MessageState `protogen:"open.v1"` - Environment string `protobuf:"bytes,1,opt,name=environment,proto3" json:"environment,omitempty"` - PasswordAuthEnabled *bool `protobuf:"varint,2,opt,name=password_auth_enabled,json=passwordAuthEnabled,proto3,oneof" json:"password_auth_enabled,omitempty"` - PasswordEnabled *bool `protobuf:"varint,3,opt,name=password_enabled,json=passwordEnabled,proto3,oneof" json:"password_enabled,omitempty"` - TotpAuthEnabled *bool `protobuf:"varint,4,opt,name=totp_auth_enabled,json=totpAuthEnabled,proto3,oneof" json:"totp_auth_enabled,omitempty"` - TotpEnabled *bool `protobuf:"varint,5,opt,name=totp_enabled,json=totpEnabled,proto3,oneof" json:"totp_enabled,omitempty"` - WebauthnRpId string `protobuf:"bytes,6,opt,name=webauthn_rp_id,json=webauthnRpId,proto3" json:"webauthn_rp_id,omitempty"` - WebauthnOrigin string `protobuf:"bytes,7,opt,name=webauthn_origin,json=webauthnOrigin,proto3" json:"webauthn_origin,omitempty"` - SmtpHost string `protobuf:"bytes,8,opt,name=smtp_host,json=smtpHost,proto3" json:"smtp_host,omitempty"` - SmtpFrom string `protobuf:"bytes,9,opt,name=smtp_from,json=smtpFrom,proto3" json:"smtp_from,omitempty"` - AuthRoutesEnabled *bool `protobuf:"varint,10,opt,name=auth_routes_enabled,json=authRoutesEnabled,proto3,oneof" json:"auth_routes_enabled,omitempty"` - RoutesEnabled *bool `protobuf:"varint,11,opt,name=routes_enabled,json=routesEnabled,proto3,oneof" json:"routes_enabled,omitempty"` - OauthRoutesEnabled *bool `protobuf:"varint,12,opt,name=oauth_routes_enabled,json=oauthRoutesEnabled,proto3,oneof" json:"oauth_routes_enabled,omitempty"` - GoogleOauthClientId string `protobuf:"bytes,13,opt,name=google_oauth_client_id,json=googleOauthClientId,proto3" json:"google_oauth_client_id,omitempty"` - GoogleOauthClientSecret string `protobuf:"bytes,14,opt,name=google_oauth_client_secret,json=googleOauthClientSecret,proto3" json:"google_oauth_client_secret,omitempty"` - GoogleOauthRedirectUrl string `protobuf:"bytes,15,opt,name=google_oauth_redirect_url,json=googleOauthRedirectUrl,proto3" json:"google_oauth_redirect_url,omitempty"` - OauthProvider string `protobuf:"bytes,16,opt,name=oauth_provider,json=oauthProvider,proto3" json:"oauth_provider,omitempty"` - SmsEnabled *bool `protobuf:"varint,17,opt,name=sms_enabled,json=smsEnabled,proto3,oneof" json:"sms_enabled,omitempty"` - TwilioVerifyServiceSid string `protobuf:"bytes,18,opt,name=twilio_verify_service_sid,json=twilioVerifyServiceSid,proto3" json:"twilio_verify_service_sid,omitempty"` - TwilioAccountSid string `protobuf:"bytes,19,opt,name=twilio_account_sid,json=twilioAccountSid,proto3" json:"twilio_account_sid,omitempty"` - TwilioAuthToken string `protobuf:"bytes,20,opt,name=twilio_auth_token,json=twilioAuthToken,proto3" json:"twilio_auth_token,omitempty"` - TwilioApiKeySid string `protobuf:"bytes,21,opt,name=twilio_api_key_sid,json=twilioApiKeySid,proto3" json:"twilio_api_key_sid,omitempty"` - TwilioApiKeySecret string `protobuf:"bytes,22,opt,name=twilio_api_key_secret,json=twilioApiKeySecret,proto3" json:"twilio_api_key_secret,omitempty"` - PasswordHashCount int32 `protobuf:"varint,23,opt,name=password_hash_count,json=passwordHashCount,proto3" json:"password_hash_count,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Environment string `protobuf:"bytes,1,opt,name=environment,proto3" json:"environment,omitempty"` + PasswordAuthEnabled *bool `protobuf:"varint,2,opt,name=password_auth_enabled,json=passwordAuthEnabled,proto3,oneof" json:"password_auth_enabled,omitempty"` + PasswordEnabled *bool `protobuf:"varint,3,opt,name=password_enabled,json=passwordEnabled,proto3,oneof" json:"password_enabled,omitempty"` + TotpAuthEnabled *bool `protobuf:"varint,4,opt,name=totp_auth_enabled,json=totpAuthEnabled,proto3,oneof" json:"totp_auth_enabled,omitempty"` + TotpEnabled *bool `protobuf:"varint,5,opt,name=totp_enabled,json=totpEnabled,proto3,oneof" json:"totp_enabled,omitempty"` + WebauthnRpId string `protobuf:"bytes,6,opt,name=webauthn_rp_id,json=webauthnRpId,proto3" json:"webauthn_rp_id,omitempty"` + WebauthnOrigin string `protobuf:"bytes,7,opt,name=webauthn_origin,json=webauthnOrigin,proto3" json:"webauthn_origin,omitempty"` + SmtpHost string `protobuf:"bytes,8,opt,name=smtp_host,json=smtpHost,proto3" json:"smtp_host,omitempty"` + SmtpFrom string `protobuf:"bytes,9,opt,name=smtp_from,json=smtpFrom,proto3" json:"smtp_from,omitempty"` + AuthRoutesEnabled *bool `protobuf:"varint,10,opt,name=auth_routes_enabled,json=authRoutesEnabled,proto3,oneof" json:"auth_routes_enabled,omitempty"` + RoutesEnabled *bool `protobuf:"varint,11,opt,name=routes_enabled,json=routesEnabled,proto3,oneof" json:"routes_enabled,omitempty"` + OauthRoutesEnabled *bool `protobuf:"varint,12,opt,name=oauth_routes_enabled,json=oauthRoutesEnabled,proto3,oneof" json:"oauth_routes_enabled,omitempty"` + GoogleOauthClientId string `protobuf:"bytes,13,opt,name=google_oauth_client_id,json=googleOauthClientId,proto3" json:"google_oauth_client_id,omitempty"` + GoogleOauthClientSecret string `protobuf:"bytes,14,opt,name=google_oauth_client_secret,json=googleOauthClientSecret,proto3" json:"google_oauth_client_secret,omitempty"` + GoogleOauthRedirectUrl string `protobuf:"bytes,15,opt,name=google_oauth_redirect_url,json=googleOauthRedirectUrl,proto3" json:"google_oauth_redirect_url,omitempty"` + OauthProvider string `protobuf:"bytes,16,opt,name=oauth_provider,json=oauthProvider,proto3" json:"oauth_provider,omitempty"` + SmsEnabled *bool `protobuf:"varint,17,opt,name=sms_enabled,json=smsEnabled,proto3,oneof" json:"sms_enabled,omitempty"` + TwilioVerifyServiceSid string `protobuf:"bytes,18,opt,name=twilio_verify_service_sid,json=twilioVerifyServiceSid,proto3" json:"twilio_verify_service_sid,omitempty"` + TwilioAccountSid string `protobuf:"bytes,19,opt,name=twilio_account_sid,json=twilioAccountSid,proto3" json:"twilio_account_sid,omitempty"` + TwilioAuthToken string `protobuf:"bytes,20,opt,name=twilio_auth_token,json=twilioAuthToken,proto3" json:"twilio_auth_token,omitempty"` + TwilioApiKeySid string `protobuf:"bytes,21,opt,name=twilio_api_key_sid,json=twilioApiKeySid,proto3" json:"twilio_api_key_sid,omitempty"` + TwilioApiKeySecret string `protobuf:"bytes,22,opt,name=twilio_api_key_secret,json=twilioApiKeySecret,proto3" json:"twilio_api_key_secret,omitempty"` + PasswordHashCount int32 `protobuf:"varint,23,opt,name=password_hash_count,json=passwordHashCount,proto3" json:"password_hash_count,omitempty"` + JwtSecret string `protobuf:"bytes,24,opt,name=jwt_secret,json=jwtSecret,proto3" json:"jwt_secret,omitempty"` + SmsAuthEnabled *bool `protobuf:"varint,25,opt,name=sms_auth_enabled,json=smsAuthEnabled,proto3,oneof" json:"sms_auth_enabled,omitempty"` + FacebookOauthClientId string `protobuf:"bytes,26,opt,name=facebook_oauth_client_id,json=facebookOauthClientId,proto3" json:"facebook_oauth_client_id,omitempty"` + FacebookOauthClientSecret string `protobuf:"bytes,27,opt,name=facebook_oauth_client_secret,json=facebookOauthClientSecret,proto3" json:"facebook_oauth_client_secret,omitempty"` + InstagramOauthClientId string `protobuf:"bytes,28,opt,name=instagram_oauth_client_id,json=instagramOauthClientId,proto3" json:"instagram_oauth_client_id,omitempty"` + InstagramOauthClientSecret string `protobuf:"bytes,29,opt,name=instagram_oauth_client_secret,json=instagramOauthClientSecret,proto3" json:"instagram_oauth_client_secret,omitempty"` + XOauthClientId string `protobuf:"bytes,30,opt,name=x_oauth_client_id,json=xOauthClientId,proto3" json:"x_oauth_client_id,omitempty"` + XOauthClientSecret string `protobuf:"bytes,31,opt,name=x_oauth_client_secret,json=xOauthClientSecret,proto3" json:"x_oauth_client_secret,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *AuthMethodsPolicyInput) Reset() { @@ -2606,6 +2678,62 @@ func (x *AuthMethodsPolicyInput) GetPasswordHashCount() int32 { return 0 } +func (x *AuthMethodsPolicyInput) GetJwtSecret() string { + if x != nil { + return x.JwtSecret + } + return "" +} + +func (x *AuthMethodsPolicyInput) GetSmsAuthEnabled() bool { + if x != nil && x.SmsAuthEnabled != nil { + return *x.SmsAuthEnabled + } + return false +} + +func (x *AuthMethodsPolicyInput) GetFacebookOauthClientId() string { + if x != nil { + return x.FacebookOauthClientId + } + return "" +} + +func (x *AuthMethodsPolicyInput) GetFacebookOauthClientSecret() string { + if x != nil { + return x.FacebookOauthClientSecret + } + return "" +} + +func (x *AuthMethodsPolicyInput) GetInstagramOauthClientId() string { + if x != nil { + return x.InstagramOauthClientId + } + return "" +} + +func (x *AuthMethodsPolicyInput) GetInstagramOauthClientSecret() string { + if x != nil { + return x.InstagramOauthClientSecret + } + return "" +} + +func (x *AuthMethodsPolicyInput) GetXOauthClientId() string { + if x != nil { + return x.XOauthClientId + } + return "" +} + +func (x *AuthMethodsPolicyInput) GetXOauthClientSecret() string { + if x != nil { + return x.XOauthClientSecret + } + return "" +} + type AuthMethodsPolicyOutput struct { state protoimpl.MessageState `protogen:"open.v1"` PasskeyEnabled bool `protobuf:"varint,1,opt,name=passkey_enabled,json=passkeyEnabled,proto3" json:"passkey_enabled,omitempty"` @@ -2721,6 +2849,7 @@ type AuthPolicyGateConfig struct { JwtSecret string `protobuf:"bytes,3,opt,name=jwt_secret,json=jwtSecret,proto3" json:"jwt_secret,omitempty"` RequiredRuntimeKeys []string `protobuf:"bytes,4,rep,name=required_runtime_keys,json=requiredRuntimeKeys,proto3" json:"required_runtime_keys,omitempty"` OauthSupportedProviders []string `protobuf:"bytes,5,rep,name=oauth_supported_providers,json=oauthSupportedProviders,proto3" json:"oauth_supported_providers,omitempty"` + TenantId string `protobuf:"bytes,6,opt,name=tenant_id,json=tenantId,proto3" json:"tenant_id,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } @@ -2790,6 +2919,57 @@ func (x *AuthPolicyGateConfig) GetOauthSupportedProviders() []string { return nil } +func (x *AuthPolicyGateConfig) GetTenantId() string { + if x != nil { + return x.TenantId + } + return "" +} + +type AuthChallengeVerifyConfig struct { + state protoimpl.MessageState `protogen:"open.v1"` + SigningSecret string `protobuf:"bytes,1,opt,name=signing_secret,json=signingSecret,proto3" json:"signing_secret,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *AuthChallengeVerifyConfig) Reset() { + *x = AuthChallengeVerifyConfig{} + mi := &file_internal_contracts_auth_proto_msgTypes[38] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *AuthChallengeVerifyConfig) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AuthChallengeVerifyConfig) ProtoMessage() {} + +func (x *AuthChallengeVerifyConfig) ProtoReflect() protoreflect.Message { + mi := &file_internal_contracts_auth_proto_msgTypes[38] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use AuthChallengeVerifyConfig.ProtoReflect.Descriptor instead. +func (*AuthChallengeVerifyConfig) Descriptor() ([]byte, []int) { + return file_internal_contracts_auth_proto_rawDescGZIP(), []int{38} +} + +func (x *AuthChallengeVerifyConfig) GetSigningSecret() string { + if x != nil { + return x.SigningSecret + } + return "" +} + type AuthPolicyGateInput struct { state protoimpl.MessageState `protogen:"open.v1"` PasskeyEnabled bool `protobuf:"varint,1,opt,name=passkey_enabled,json=passkeyEnabled,proto3" json:"passkey_enabled,omitempty"` @@ -2808,7 +2988,7 @@ type AuthPolicyGateInput struct { func (x *AuthPolicyGateInput) Reset() { *x = AuthPolicyGateInput{} - mi := &file_internal_contracts_auth_proto_msgTypes[38] + mi := &file_internal_contracts_auth_proto_msgTypes[39] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2820,7 +3000,7 @@ func (x *AuthPolicyGateInput) String() string { func (*AuthPolicyGateInput) ProtoMessage() {} func (x *AuthPolicyGateInput) ProtoReflect() protoreflect.Message { - mi := &file_internal_contracts_auth_proto_msgTypes[38] + mi := &file_internal_contracts_auth_proto_msgTypes[39] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2833,7 +3013,7 @@ func (x *AuthPolicyGateInput) ProtoReflect() protoreflect.Message { // Deprecated: Use AuthPolicyGateInput.ProtoReflect.Descriptor instead. func (*AuthPolicyGateInput) Descriptor() ([]byte, []int) { - return file_internal_contracts_auth_proto_rawDescGZIP(), []int{38} + return file_internal_contracts_auth_proto_rawDescGZIP(), []int{39} } func (x *AuthPolicyGateInput) GetPasskeyEnabled() bool { @@ -2924,7 +3104,7 @@ type AuthMethodsResponseOutput struct { func (x *AuthMethodsResponseOutput) Reset() { *x = AuthMethodsResponseOutput{} - mi := &file_internal_contracts_auth_proto_msgTypes[39] + mi := &file_internal_contracts_auth_proto_msgTypes[40] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2936,7 +3116,7 @@ func (x *AuthMethodsResponseOutput) String() string { func (*AuthMethodsResponseOutput) ProtoMessage() {} func (x *AuthMethodsResponseOutput) ProtoReflect() protoreflect.Message { - mi := &file_internal_contracts_auth_proto_msgTypes[39] + mi := &file_internal_contracts_auth_proto_msgTypes[40] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2949,7 +3129,7 @@ func (x *AuthMethodsResponseOutput) ProtoReflect() protoreflect.Message { // Deprecated: Use AuthMethodsResponseOutput.ProtoReflect.Descriptor instead. func (*AuthMethodsResponseOutput) Descriptor() ([]byte, []int) { - return file_internal_contracts_auth_proto_rawDescGZIP(), []int{39} + return file_internal_contracts_auth_proto_rawDescGZIP(), []int{40} } func (x *AuthMethodsResponseOutput) GetPasskeyEnabled() bool { @@ -3033,7 +3213,7 @@ type AuthPolicyAuditOutput struct { func (x *AuthPolicyAuditOutput) Reset() { *x = AuthPolicyAuditOutput{} - mi := &file_internal_contracts_auth_proto_msgTypes[40] + mi := &file_internal_contracts_auth_proto_msgTypes[41] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3045,7 +3225,7 @@ func (x *AuthPolicyAuditOutput) String() string { func (*AuthPolicyAuditOutput) ProtoMessage() {} func (x *AuthPolicyAuditOutput) ProtoReflect() protoreflect.Message { - mi := &file_internal_contracts_auth_proto_msgTypes[40] + mi := &file_internal_contracts_auth_proto_msgTypes[41] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3058,7 +3238,7 @@ func (x *AuthPolicyAuditOutput) ProtoReflect() protoreflect.Message { // Deprecated: Use AuthPolicyAuditOutput.ProtoReflect.Descriptor instead. func (*AuthPolicyAuditOutput) Descriptor() ([]byte, []int) { - return file_internal_contracts_auth_proto_rawDescGZIP(), []int{40} + return file_internal_contracts_auth_proto_rawDescGZIP(), []int{41} } func (x *AuthPolicyAuditOutput) GetPassed() bool { @@ -3100,7 +3280,7 @@ type OAuthProviderConfig struct { func (x *OAuthProviderConfig) Reset() { *x = OAuthProviderConfig{} - mi := &file_internal_contracts_auth_proto_msgTypes[41] + mi := &file_internal_contracts_auth_proto_msgTypes[42] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3112,7 +3292,7 @@ func (x *OAuthProviderConfig) String() string { func (*OAuthProviderConfig) ProtoMessage() {} func (x *OAuthProviderConfig) ProtoReflect() protoreflect.Message { - mi := &file_internal_contracts_auth_proto_msgTypes[41] + mi := &file_internal_contracts_auth_proto_msgTypes[42] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3125,7 +3305,7 @@ func (x *OAuthProviderConfig) ProtoReflect() protoreflect.Message { // Deprecated: Use OAuthProviderConfig.ProtoReflect.Descriptor instead. func (*OAuthProviderConfig) Descriptor() ([]byte, []int) { - return file_internal_contracts_auth_proto_rawDescGZIP(), []int{41} + return file_internal_contracts_auth_proto_rawDescGZIP(), []int{42} } func (x *OAuthProviderConfig) GetProvider() string { @@ -3212,7 +3392,7 @@ type OAuthProviderInput struct { func (x *OAuthProviderInput) Reset() { *x = OAuthProviderInput{} - mi := &file_internal_contracts_auth_proto_msgTypes[42] + mi := &file_internal_contracts_auth_proto_msgTypes[43] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3224,7 +3404,7 @@ func (x *OAuthProviderInput) String() string { func (*OAuthProviderInput) ProtoMessage() {} func (x *OAuthProviderInput) ProtoReflect() protoreflect.Message { - mi := &file_internal_contracts_auth_proto_msgTypes[42] + mi := &file_internal_contracts_auth_proto_msgTypes[43] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3237,7 +3417,7 @@ func (x *OAuthProviderInput) ProtoReflect() protoreflect.Message { // Deprecated: Use OAuthProviderInput.ProtoReflect.Descriptor instead. func (*OAuthProviderInput) Descriptor() ([]byte, []int) { - return file_internal_contracts_auth_proto_rawDescGZIP(), []int{42} + return file_internal_contracts_auth_proto_rawDescGZIP(), []int{43} } func (x *OAuthProviderInput) GetProvider() string { @@ -3300,7 +3480,7 @@ type OAuthProviderConfigOutput struct { func (x *OAuthProviderConfigOutput) Reset() { *x = OAuthProviderConfigOutput{} - mi := &file_internal_contracts_auth_proto_msgTypes[43] + mi := &file_internal_contracts_auth_proto_msgTypes[44] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3312,7 +3492,7 @@ func (x *OAuthProviderConfigOutput) String() string { func (*OAuthProviderConfigOutput) ProtoMessage() {} func (x *OAuthProviderConfigOutput) ProtoReflect() protoreflect.Message { - mi := &file_internal_contracts_auth_proto_msgTypes[43] + mi := &file_internal_contracts_auth_proto_msgTypes[44] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3325,7 +3505,7 @@ func (x *OAuthProviderConfigOutput) ProtoReflect() protoreflect.Message { // Deprecated: Use OAuthProviderConfigOutput.ProtoReflect.Descriptor instead. func (*OAuthProviderConfigOutput) Descriptor() ([]byte, []int) { - return file_internal_contracts_auth_proto_rawDescGZIP(), []int{43} + return file_internal_contracts_auth_proto_rawDescGZIP(), []int{44} } func (x *OAuthProviderConfigOutput) GetProvider() string { @@ -3417,7 +3597,7 @@ type OAuthStartOutput struct { func (x *OAuthStartOutput) Reset() { *x = OAuthStartOutput{} - mi := &file_internal_contracts_auth_proto_msgTypes[44] + mi := &file_internal_contracts_auth_proto_msgTypes[45] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3429,7 +3609,7 @@ func (x *OAuthStartOutput) String() string { func (*OAuthStartOutput) ProtoMessage() {} func (x *OAuthStartOutput) ProtoReflect() protoreflect.Message { - mi := &file_internal_contracts_auth_proto_msgTypes[44] + mi := &file_internal_contracts_auth_proto_msgTypes[45] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3442,7 +3622,7 @@ func (x *OAuthStartOutput) ProtoReflect() protoreflect.Message { // Deprecated: Use OAuthStartOutput.ProtoReflect.Descriptor instead. func (*OAuthStartOutput) Descriptor() ([]byte, []int) { - return file_internal_contracts_auth_proto_rawDescGZIP(), []int{44} + return file_internal_contracts_auth_proto_rawDescGZIP(), []int{45} } func (x *OAuthStartOutput) GetStarted() bool { @@ -3540,7 +3720,7 @@ type OAuthExchangeOutput struct { func (x *OAuthExchangeOutput) Reset() { *x = OAuthExchangeOutput{} - mi := &file_internal_contracts_auth_proto_msgTypes[45] + mi := &file_internal_contracts_auth_proto_msgTypes[46] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3552,7 +3732,7 @@ func (x *OAuthExchangeOutput) String() string { func (*OAuthExchangeOutput) ProtoMessage() {} func (x *OAuthExchangeOutput) ProtoReflect() protoreflect.Message { - mi := &file_internal_contracts_auth_proto_msgTypes[45] + mi := &file_internal_contracts_auth_proto_msgTypes[46] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3565,7 +3745,7 @@ func (x *OAuthExchangeOutput) ProtoReflect() protoreflect.Message { // Deprecated: Use OAuthExchangeOutput.ProtoReflect.Descriptor instead. func (*OAuthExchangeOutput) Descriptor() ([]byte, []int) { - return file_internal_contracts_auth_proto_rawDescGZIP(), []int{45} + return file_internal_contracts_auth_proto_rawDescGZIP(), []int{46} } func (x *OAuthExchangeOutput) GetExchanged() bool { @@ -3656,7 +3836,7 @@ type OAuthUserinfoOutput struct { func (x *OAuthUserinfoOutput) Reset() { *x = OAuthUserinfoOutput{} - mi := &file_internal_contracts_auth_proto_msgTypes[46] + mi := &file_internal_contracts_auth_proto_msgTypes[47] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3668,7 +3848,7 @@ func (x *OAuthUserinfoOutput) String() string { func (*OAuthUserinfoOutput) ProtoMessage() {} func (x *OAuthUserinfoOutput) ProtoReflect() protoreflect.Message { - mi := &file_internal_contracts_auth_proto_msgTypes[46] + mi := &file_internal_contracts_auth_proto_msgTypes[47] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3681,7 +3861,7 @@ func (x *OAuthUserinfoOutput) ProtoReflect() protoreflect.Message { // Deprecated: Use OAuthUserinfoOutput.ProtoReflect.Descriptor instead. func (*OAuthUserinfoOutput) Descriptor() ([]byte, []int) { - return file_internal_contracts_auth_proto_rawDescGZIP(), []int{46} + return file_internal_contracts_auth_proto_rawDescGZIP(), []int{47} } func (x *OAuthUserinfoOutput) GetFetched() bool { @@ -3763,7 +3943,7 @@ type CredentialListInput struct { func (x *CredentialListInput) Reset() { *x = CredentialListInput{} - mi := &file_internal_contracts_auth_proto_msgTypes[47] + mi := &file_internal_contracts_auth_proto_msgTypes[48] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3775,7 +3955,7 @@ func (x *CredentialListInput) String() string { func (*CredentialListInput) ProtoMessage() {} func (x *CredentialListInput) ProtoReflect() protoreflect.Message { - mi := &file_internal_contracts_auth_proto_msgTypes[47] + mi := &file_internal_contracts_auth_proto_msgTypes[48] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3788,7 +3968,7 @@ func (x *CredentialListInput) ProtoReflect() protoreflect.Message { // Deprecated: Use CredentialListInput.ProtoReflect.Descriptor instead. func (*CredentialListInput) Descriptor() ([]byte, []int) { - return file_internal_contracts_auth_proto_rawDescGZIP(), []int{47} + return file_internal_contracts_auth_proto_rawDescGZIP(), []int{48} } func (x *CredentialListInput) GetCredentialsJson() string { @@ -3811,7 +3991,7 @@ type CredentialSummary struct { func (x *CredentialSummary) Reset() { *x = CredentialSummary{} - mi := &file_internal_contracts_auth_proto_msgTypes[48] + mi := &file_internal_contracts_auth_proto_msgTypes[49] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3823,7 +4003,7 @@ func (x *CredentialSummary) String() string { func (*CredentialSummary) ProtoMessage() {} func (x *CredentialSummary) ProtoReflect() protoreflect.Message { - mi := &file_internal_contracts_auth_proto_msgTypes[48] + mi := &file_internal_contracts_auth_proto_msgTypes[49] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3836,7 +4016,7 @@ func (x *CredentialSummary) ProtoReflect() protoreflect.Message { // Deprecated: Use CredentialSummary.ProtoReflect.Descriptor instead. func (*CredentialSummary) Descriptor() ([]byte, []int) { - return file_internal_contracts_auth_proto_rawDescGZIP(), []int{48} + return file_internal_contracts_auth_proto_rawDescGZIP(), []int{49} } func (x *CredentialSummary) GetId() string { @@ -3885,7 +4065,7 @@ type CredentialListOutput struct { func (x *CredentialListOutput) Reset() { *x = CredentialListOutput{} - mi := &file_internal_contracts_auth_proto_msgTypes[49] + mi := &file_internal_contracts_auth_proto_msgTypes[50] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3897,7 +4077,7 @@ func (x *CredentialListOutput) String() string { func (*CredentialListOutput) ProtoMessage() {} func (x *CredentialListOutput) ProtoReflect() protoreflect.Message { - mi := &file_internal_contracts_auth_proto_msgTypes[49] + mi := &file_internal_contracts_auth_proto_msgTypes[50] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3910,7 +4090,7 @@ func (x *CredentialListOutput) ProtoReflect() protoreflect.Message { // Deprecated: Use CredentialListOutput.ProtoReflect.Descriptor instead. func (*CredentialListOutput) Descriptor() ([]byte, []int) { - return file_internal_contracts_auth_proto_rawDescGZIP(), []int{49} + return file_internal_contracts_auth_proto_rawDescGZIP(), []int{50} } func (x *CredentialListOutput) GetCredentials() []*CredentialSummary { @@ -3945,7 +4125,7 @@ type CredentialRevokeInput struct { func (x *CredentialRevokeInput) Reset() { *x = CredentialRevokeInput{} - mi := &file_internal_contracts_auth_proto_msgTypes[50] + mi := &file_internal_contracts_auth_proto_msgTypes[51] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3957,7 +4137,7 @@ func (x *CredentialRevokeInput) String() string { func (*CredentialRevokeInput) ProtoMessage() {} func (x *CredentialRevokeInput) ProtoReflect() protoreflect.Message { - mi := &file_internal_contracts_auth_proto_msgTypes[50] + mi := &file_internal_contracts_auth_proto_msgTypes[51] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3970,7 +4150,7 @@ func (x *CredentialRevokeInput) ProtoReflect() protoreflect.Message { // Deprecated: Use CredentialRevokeInput.ProtoReflect.Descriptor instead. func (*CredentialRevokeInput) Descriptor() ([]byte, []int) { - return file_internal_contracts_auth_proto_rawDescGZIP(), []int{50} + return file_internal_contracts_auth_proto_rawDescGZIP(), []int{51} } func (x *CredentialRevokeInput) GetCredentialId() string { @@ -4005,7 +4185,7 @@ type CredentialRevokeOutput struct { func (x *CredentialRevokeOutput) Reset() { *x = CredentialRevokeOutput{} - mi := &file_internal_contracts_auth_proto_msgTypes[51] + mi := &file_internal_contracts_auth_proto_msgTypes[52] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4017,7 +4197,7 @@ func (x *CredentialRevokeOutput) String() string { func (*CredentialRevokeOutput) ProtoMessage() {} func (x *CredentialRevokeOutput) ProtoReflect() protoreflect.Message { - mi := &file_internal_contracts_auth_proto_msgTypes[51] + mi := &file_internal_contracts_auth_proto_msgTypes[52] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4030,7 +4210,7 @@ func (x *CredentialRevokeOutput) ProtoReflect() protoreflect.Message { // Deprecated: Use CredentialRevokeOutput.ProtoReflect.Descriptor instead. func (*CredentialRevokeOutput) Descriptor() ([]byte, []int) { - return file_internal_contracts_auth_proto_rawDescGZIP(), []int{51} + return file_internal_contracts_auth_proto_rawDescGZIP(), []int{52} } func (x *CredentialRevokeOutput) GetAuthorized() bool { @@ -4222,7 +4402,7 @@ const file_internal_contracts_auth_proto_rawDesc = "" + "\x05phone\x18\x04 \x01(\tR\x05phone\x12\x1f\n" + "\vphone_valid\x18\x05 \x01(\bR\n" + "phoneValid\x12\x14\n" + - "\x05error\x18d \x01(\tR\x05error\"\xe7\t\n" + + "\x05error\x18d \x01(\tR\x05error\"\xa0\r\n" + "\x17AuthMethodsPolicyConfig\x12 \n" + "\venvironment\x18\x01 \x01(\tR\venvironment\x127\n" + "\x15password_auth_enabled\x18\x02 \x01(\bH\x00R\x13passwordAuthEnabled\x88\x01\x01\x12.\n" + @@ -4248,7 +4428,16 @@ const file_internal_contracts_auth_proto_rawDesc = "" + "\x11twilio_auth_token\x18\x14 \x01(\tR\x0ftwilioAuthToken\x12+\n" + "\x12twilio_api_key_sid\x18\x15 \x01(\tR\x0ftwilioApiKeySid\x121\n" + "\x15twilio_api_key_secret\x18\x16 \x01(\tR\x12twilioApiKeySecret\x12.\n" + - "\x13password_hash_count\x18\x17 \x01(\x05R\x11passwordHashCountB\x18\n" + + "\x13password_hash_count\x18\x17 \x01(\x05R\x11passwordHashCount\x12\x1d\n" + + "\n" + + "jwt_secret\x18\x18 \x01(\tR\tjwtSecret\x12-\n" + + "\x10sms_auth_enabled\x18\x19 \x01(\bH\bR\x0esmsAuthEnabled\x88\x01\x01\x127\n" + + "\x18facebook_oauth_client_id\x18\x1a \x01(\tR\x15facebookOauthClientId\x12?\n" + + "\x1cfacebook_oauth_client_secret\x18\x1b \x01(\tR\x19facebookOauthClientSecret\x129\n" + + "\x19instagram_oauth_client_id\x18\x1c \x01(\tR\x16instagramOauthClientId\x12A\n" + + "\x1dinstagram_oauth_client_secret\x18\x1d \x01(\tR\x1ainstagramOauthClientSecret\x12)\n" + + "\x11x_oauth_client_id\x18\x1e \x01(\tR\x0exOauthClientId\x121\n" + + "\x15x_oauth_client_secret\x18\x1f \x01(\tR\x12xOauthClientSecretB\x18\n" + "\x16_password_auth_enabledB\x13\n" + "\x11_password_enabledB\x14\n" + "\x12_totp_auth_enabledB\x0f\n" + @@ -4256,7 +4445,8 @@ const file_internal_contracts_auth_proto_rawDesc = "" + "\x14_auth_routes_enabledB\x11\n" + "\x0f_routes_enabledB\x17\n" + "\x15_oauth_routes_enabledB\x0e\n" + - "\f_sms_enabled\"\xe6\t\n" + + "\f_sms_enabledB\x13\n" + + "\x11_sms_auth_enabled\"\x9f\r\n" + "\x16AuthMethodsPolicyInput\x12 \n" + "\venvironment\x18\x01 \x01(\tR\venvironment\x127\n" + "\x15password_auth_enabled\x18\x02 \x01(\bH\x00R\x13passwordAuthEnabled\x88\x01\x01\x12.\n" + @@ -4282,7 +4472,16 @@ const file_internal_contracts_auth_proto_rawDesc = "" + "\x11twilio_auth_token\x18\x14 \x01(\tR\x0ftwilioAuthToken\x12+\n" + "\x12twilio_api_key_sid\x18\x15 \x01(\tR\x0ftwilioApiKeySid\x121\n" + "\x15twilio_api_key_secret\x18\x16 \x01(\tR\x12twilioApiKeySecret\x12.\n" + - "\x13password_hash_count\x18\x17 \x01(\x05R\x11passwordHashCountB\x18\n" + + "\x13password_hash_count\x18\x17 \x01(\x05R\x11passwordHashCount\x12\x1d\n" + + "\n" + + "jwt_secret\x18\x18 \x01(\tR\tjwtSecret\x12-\n" + + "\x10sms_auth_enabled\x18\x19 \x01(\bH\bR\x0esmsAuthEnabled\x88\x01\x01\x127\n" + + "\x18facebook_oauth_client_id\x18\x1a \x01(\tR\x15facebookOauthClientId\x12?\n" + + "\x1cfacebook_oauth_client_secret\x18\x1b \x01(\tR\x19facebookOauthClientSecret\x129\n" + + "\x19instagram_oauth_client_id\x18\x1c \x01(\tR\x16instagramOauthClientId\x12A\n" + + "\x1dinstagram_oauth_client_secret\x18\x1d \x01(\tR\x1ainstagramOauthClientSecret\x12)\n" + + "\x11x_oauth_client_id\x18\x1e \x01(\tR\x0exOauthClientId\x121\n" + + "\x15x_oauth_client_secret\x18\x1f \x01(\tR\x12xOauthClientSecretB\x18\n" + "\x16_password_auth_enabledB\x13\n" + "\x11_password_enabledB\x14\n" + "\x12_totp_auth_enabledB\x0f\n" + @@ -4290,7 +4489,8 @@ const file_internal_contracts_auth_proto_rawDesc = "" + "\x14_auth_routes_enabledB\x11\n" + "\x0f_routes_enabledB\x17\n" + "\x15_oauth_routes_enabledB\x0e\n" + - "\f_sms_enabled\"\x8d\x03\n" + + "\f_sms_enabledB\x13\n" + + "\x11_sms_auth_enabled\"\x8d\x03\n" + "\x17AuthMethodsPolicyOutput\x12'\n" + "\x0fpasskey_enabled\x18\x01 \x01(\bR\x0epasskeyEnabled\x12,\n" + "\x12email_code_enabled\x18\x02 \x01(\bR\x10emailCodeEnabled\x12(\n" + @@ -4300,7 +4500,7 @@ const file_internal_contracts_auth_proto_rawDesc = "" + "\ftotp_enabled\x18\x06 \x01(\bR\vtotpEnabled\x12'\n" + "\x0foauth_providers\x18\a \x03(\tR\x0eoauthProviders\x120\n" + "\x14primary_method_count\x18\b \x01(\x05R\x12primaryMethodCount\x12\x14\n" + - "\x05error\x18d \x01(\tR\x05error\"\xed\x01\n" + + "\x05error\x18d \x01(\tR\x05error\"\x8a\x02\n" + "\x14AuthPolicyGateConfig\x12\x1f\n" + "\vpolicy_step\x18\x01 \x01(\tR\n" + "policyStep\x12%\n" + @@ -4308,7 +4508,10 @@ const file_internal_contracts_auth_proto_rawDesc = "" + "\n" + "jwt_secret\x18\x03 \x01(\tR\tjwtSecret\x122\n" + "\x15required_runtime_keys\x18\x04 \x03(\tR\x13requiredRuntimeKeys\x12:\n" + - "\x19oauth_supported_providers\x18\x05 \x03(\tR\x17oauthSupportedProviders\"\xb9\x03\n" + + "\x19oauth_supported_providers\x18\x05 \x03(\tR\x17oauthSupportedProviders\x12\x1b\n" + + "\ttenant_id\x18\x06 \x01(\tR\btenantId\"B\n" + + "\x19AuthChallengeVerifyConfig\x12%\n" + + "\x0esigning_secret\x18\x01 \x01(\tR\rsigningSecret\"\xb9\x03\n" + "\x13AuthPolicyGateInput\x12'\n" + "\x0fpasskey_enabled\x18\x01 \x01(\bR\x0epasskeyEnabled\x12,\n" + "\x12email_code_enabled\x18\x02 \x01(\bR\x10emailCodeEnabled\x12(\n" + @@ -4449,7 +4652,7 @@ func file_internal_contracts_auth_proto_rawDescGZIP() []byte { return file_internal_contracts_auth_proto_rawDescData } -var file_internal_contracts_auth_proto_msgTypes = make([]protoimpl.MessageInfo, 52) +var file_internal_contracts_auth_proto_msgTypes = make([]protoimpl.MessageInfo, 53) var file_internal_contracts_auth_proto_goTypes = []any{ (*CredentialModuleConfig)(nil), // 0: workflow.plugins.auth.v1.CredentialModuleConfig (*PasskeyStepConfig)(nil), // 1: workflow.plugins.auth.v1.PasskeyStepConfig @@ -4489,26 +4692,27 @@ var file_internal_contracts_auth_proto_goTypes = []any{ (*AuthMethodsPolicyInput)(nil), // 35: workflow.plugins.auth.v1.AuthMethodsPolicyInput (*AuthMethodsPolicyOutput)(nil), // 36: workflow.plugins.auth.v1.AuthMethodsPolicyOutput (*AuthPolicyGateConfig)(nil), // 37: workflow.plugins.auth.v1.AuthPolicyGateConfig - (*AuthPolicyGateInput)(nil), // 38: workflow.plugins.auth.v1.AuthPolicyGateInput - (*AuthMethodsResponseOutput)(nil), // 39: workflow.plugins.auth.v1.AuthMethodsResponseOutput - (*AuthPolicyAuditOutput)(nil), // 40: workflow.plugins.auth.v1.AuthPolicyAuditOutput - (*OAuthProviderConfig)(nil), // 41: workflow.plugins.auth.v1.OAuthProviderConfig - (*OAuthProviderInput)(nil), // 42: workflow.plugins.auth.v1.OAuthProviderInput - (*OAuthProviderConfigOutput)(nil), // 43: workflow.plugins.auth.v1.OAuthProviderConfigOutput - (*OAuthStartOutput)(nil), // 44: workflow.plugins.auth.v1.OAuthStartOutput - (*OAuthExchangeOutput)(nil), // 45: workflow.plugins.auth.v1.OAuthExchangeOutput - (*OAuthUserinfoOutput)(nil), // 46: workflow.plugins.auth.v1.OAuthUserinfoOutput - (*CredentialListInput)(nil), // 47: workflow.plugins.auth.v1.CredentialListInput - (*CredentialSummary)(nil), // 48: workflow.plugins.auth.v1.CredentialSummary - (*CredentialListOutput)(nil), // 49: workflow.plugins.auth.v1.CredentialListOutput - (*CredentialRevokeInput)(nil), // 50: workflow.plugins.auth.v1.CredentialRevokeInput - (*CredentialRevokeOutput)(nil), // 51: workflow.plugins.auth.v1.CredentialRevokeOutput - (*structpb.Struct)(nil), // 52: google.protobuf.Struct + (*AuthChallengeVerifyConfig)(nil), // 38: workflow.plugins.auth.v1.AuthChallengeVerifyConfig + (*AuthPolicyGateInput)(nil), // 39: workflow.plugins.auth.v1.AuthPolicyGateInput + (*AuthMethodsResponseOutput)(nil), // 40: workflow.plugins.auth.v1.AuthMethodsResponseOutput + (*AuthPolicyAuditOutput)(nil), // 41: workflow.plugins.auth.v1.AuthPolicyAuditOutput + (*OAuthProviderConfig)(nil), // 42: workflow.plugins.auth.v1.OAuthProviderConfig + (*OAuthProviderInput)(nil), // 43: workflow.plugins.auth.v1.OAuthProviderInput + (*OAuthProviderConfigOutput)(nil), // 44: workflow.plugins.auth.v1.OAuthProviderConfigOutput + (*OAuthStartOutput)(nil), // 45: workflow.plugins.auth.v1.OAuthStartOutput + (*OAuthExchangeOutput)(nil), // 46: workflow.plugins.auth.v1.OAuthExchangeOutput + (*OAuthUserinfoOutput)(nil), // 47: workflow.plugins.auth.v1.OAuthUserinfoOutput + (*CredentialListInput)(nil), // 48: workflow.plugins.auth.v1.CredentialListInput + (*CredentialSummary)(nil), // 49: workflow.plugins.auth.v1.CredentialSummary + (*CredentialListOutput)(nil), // 50: workflow.plugins.auth.v1.CredentialListOutput + (*CredentialRevokeInput)(nil), // 51: workflow.plugins.auth.v1.CredentialRevokeInput + (*CredentialRevokeOutput)(nil), // 52: workflow.plugins.auth.v1.CredentialRevokeOutput + (*structpb.Struct)(nil), // 53: google.protobuf.Struct } var file_internal_contracts_auth_proto_depIdxs = []int32{ - 52, // 0: workflow.plugins.auth.v1.OAuthExchangeOutput.raw_tokens:type_name -> google.protobuf.Struct - 52, // 1: workflow.plugins.auth.v1.OAuthUserinfoOutput.raw_claims:type_name -> google.protobuf.Struct - 48, // 2: workflow.plugins.auth.v1.CredentialListOutput.credentials:type_name -> workflow.plugins.auth.v1.CredentialSummary + 53, // 0: workflow.plugins.auth.v1.OAuthExchangeOutput.raw_tokens:type_name -> google.protobuf.Struct + 53, // 1: workflow.plugins.auth.v1.OAuthUserinfoOutput.raw_claims:type_name -> google.protobuf.Struct + 49, // 2: workflow.plugins.auth.v1.CredentialListOutput.credentials:type_name -> workflow.plugins.auth.v1.CredentialSummary 3, // [3:3] is the sub-list for method output_type 3, // [3:3] is the sub-list for method input_type 3, // [3:3] is the sub-list for extension type_name @@ -4523,15 +4727,15 @@ func file_internal_contracts_auth_proto_init() { } file_internal_contracts_auth_proto_msgTypes[34].OneofWrappers = []any{} file_internal_contracts_auth_proto_msgTypes[35].OneofWrappers = []any{} - file_internal_contracts_auth_proto_msgTypes[41].OneofWrappers = []any{} file_internal_contracts_auth_proto_msgTypes[42].OneofWrappers = []any{} + file_internal_contracts_auth_proto_msgTypes[43].OneofWrappers = []any{} type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: unsafe.Slice(unsafe.StringData(file_internal_contracts_auth_proto_rawDesc), len(file_internal_contracts_auth_proto_rawDesc)), NumEnums: 0, - NumMessages: 52, + NumMessages: 53, NumExtensions: 0, NumServices: 0, }, diff --git a/internal/contracts/auth.proto b/internal/contracts/auth.proto index c4592e0..97eceb5 100644 --- a/internal/contracts/auth.proto +++ b/internal/contracts/auth.proto @@ -246,6 +246,14 @@ message AuthMethodsPolicyConfig { string twilio_api_key_sid = 21; string twilio_api_key_secret = 22; int32 password_hash_count = 23; + string jwt_secret = 24; + optional bool sms_auth_enabled = 25; + string facebook_oauth_client_id = 26; + string facebook_oauth_client_secret = 27; + string instagram_oauth_client_id = 28; + string instagram_oauth_client_secret = 29; + string x_oauth_client_id = 30; + string x_oauth_client_secret = 31; } message AuthMethodsPolicyInput { @@ -272,6 +280,14 @@ message AuthMethodsPolicyInput { string twilio_api_key_sid = 21; string twilio_api_key_secret = 22; int32 password_hash_count = 23; + string jwt_secret = 24; + optional bool sms_auth_enabled = 25; + string facebook_oauth_client_id = 26; + string facebook_oauth_client_secret = 27; + string instagram_oauth_client_id = 28; + string instagram_oauth_client_secret = 29; + string x_oauth_client_id = 30; + string x_oauth_client_secret = 31; } message AuthMethodsPolicyOutput { @@ -292,6 +308,11 @@ message AuthPolicyGateConfig { string jwt_secret = 3; repeated string required_runtime_keys = 4; repeated string oauth_supported_providers = 5; + string tenant_id = 6; +} + +message AuthChallengeVerifyConfig { + string signing_secret = 1; } message AuthPolicyGateInput { diff --git a/internal/plugin.go b/internal/plugin.go index dd2c3b5..e5d00bb 100644 --- a/internal/plugin.go +++ b/internal/plugin.go @@ -210,7 +210,7 @@ func (p *authPlugin) CreateTypedStep(typeName, name string, config *anypb.Any) ( return newChallengeGenerateStep(name, config) }, &contracts.ChallengeGenerateOutput{})).CreateTypedStep(typeName, name, config) case "step.auth_challenge_verify": - return sdk.NewTypedStepFactory(typeName, &contracts.EmptyConfig{}, &contracts.ChallengeVerifyInput{}, typedLegacyStep[*contracts.EmptyConfig, *contracts.ChallengeVerifyInput, *contracts.ChallengeVerifyOutput](func(name string, config map[string]any) sdk.StepInstance { + return sdk.NewTypedStepFactory(typeName, &contracts.AuthChallengeVerifyConfig{}, &contracts.ChallengeVerifyInput{}, typedLegacyStep[*contracts.AuthChallengeVerifyConfig, *contracts.ChallengeVerifyInput, *contracts.ChallengeVerifyOutput](func(name string, config map[string]any) sdk.StepInstance { return newChallengeVerifyStep(name, config) }, &contracts.ChallengeVerifyOutput{})).CreateTypedStep(typeName, name, config) case "step.auth_normalize_phone": @@ -284,7 +284,7 @@ var authContractRegistry = &pb.ContractRegistry{ stepContract("step.auth_password_hash", "EmptyConfig", "PasswordHashInput", "PasswordHashOutput"), stepContract("step.auth_password_verify", "EmptyConfig", "PasswordVerifyInput", "PasswordVerifyOutput"), stepContract("step.auth_challenge_generate", "EmptyConfig", "ChallengeGenerateInput", "ChallengeGenerateOutput"), - stepContract("step.auth_challenge_verify", "EmptyConfig", "ChallengeVerifyInput", "ChallengeVerifyOutput"), + stepContract("step.auth_challenge_verify", "AuthChallengeVerifyConfig", "ChallengeVerifyInput", "ChallengeVerifyOutput"), stepContract("step.auth_normalize_phone", "EmptyConfig", "NormalizePhoneInput", "NormalizePhoneOutput"), stepContract("step.auth_methods_policy", "AuthMethodsPolicyConfig", "AuthMethodsPolicyInput", "AuthMethodsPolicyOutput"), stepContract("step.auth_policy_gate", "AuthPolicyGateConfig", "AuthPolicyGateInput", "AuthMethodsPolicyOutput"), diff --git a/internal/step_challenge.go b/internal/step_challenge.go index bdf5f5f..c4343d9 100644 --- a/internal/step_challenge.go +++ b/internal/step_challenge.go @@ -52,10 +52,13 @@ func (s *challengeGenerateStep) Execute(_ context.Context, _ map[string]any, _ m }}, nil } -type challengeVerifyStep struct{ name string } +type challengeVerifyStep struct { + name string + config map[string]any +} -func newChallengeVerifyStep(name string, _ map[string]any) *challengeVerifyStep { - return &challengeVerifyStep{name: name} +func newChallengeVerifyStep(name string, config map[string]any) *challengeVerifyStep { + return &challengeVerifyStep{name: name, config: config} } func (s *challengeVerifyStep) Execute(_ context.Context, _ map[string]any, _ map[string]map[string]any, current, _, _ map[string]any) (*sdk.StepResult, error) { @@ -66,6 +69,11 @@ func (s *challengeVerifyStep) Execute(_ context.Context, _ map[string]any, _ map tenantID, _ := current["tenant_id"].(string) purpose, _ := current["purpose"].(string) signingSecret, _ := current["signing_secret"].(string) + if signingSecret == "" { + if v, ok := s.config["signing_secret"].(string); ok { + signingSecret = v + } + } if strings.TrimSpace(channel) == "" || code == "" || codeHash == "" || strings.TrimSpace(destination) == "" || strings.TrimSpace(tenantID) == "" || strings.TrimSpace(purpose) == "" || signingSecret == "" { return &sdk.StepResult{Output: map[string]any{"valid": false, "error": "missing channel, code, code_hash, destination, tenant_id, purpose, or signing_secret"}}, nil } diff --git a/internal/strict_proto_fields_test.go b/internal/strict_proto_fields_test.go new file mode 100644 index 0000000..b9936f9 --- /dev/null +++ b/internal/strict_proto_fields_test.go @@ -0,0 +1,122 @@ +package internal + +import ( + "context" + "testing" + + "github.com/GoCodeAlone/workflow-plugin-auth/internal/contracts" + sdk "github.com/GoCodeAlone/workflow/plugin/external/sdk" + "google.golang.org/protobuf/types/known/anypb" +) + +// TestAuthMethodsPolicyConfig_AcceptsNewBMWFields ensures the typed +// AuthMethodsPolicyConfig accepts every field BMW supplies (closing the gap +// surfaced by BMW local smoke against workflow v0.51.5). +func TestAuthMethodsPolicyConfig_AcceptsNewBMWFields(t *testing.T) { + cfg := &contracts.AuthMethodsPolicyConfig{ + Environment: "development", + JwtSecret: "secret", + SmsAuthEnabled: protoBool(true), + FacebookOauthClientId: "fb-client", + FacebookOauthClientSecret: "fb-secret", + InstagramOauthClientId: "ig-client", + InstagramOauthClientSecret: "ig-secret", + XOauthClientId: "x-client", + XOauthClientSecret: "x-secret", + } + packed, err := anypb.New(cfg) + if err != nil { + t.Fatalf("pack config: %v", err) + } + provider := NewAuthPlugin().(interface { + CreateTypedStep(typeName, name string, config *anypb.Any) (sdk.StepInstance, error) + }) + if _, err := provider.CreateTypedStep("step.auth_methods_policy", "policy", packed); err != nil { + t.Fatalf("CreateTypedStep rejected new BMW fields: %v", err) + } +} + +// TestAuthMethodsPolicy_SmsAuthEnabledTogglesSMS verifies the new +// sms_auth_enabled config field reaches the SMS readiness predicate. +func TestAuthMethodsPolicy_SmsAuthEnabledTogglesSMS(t *testing.T) { + output := executeMethodsPolicy(t, map[string]any{ + "auth_routes_enabled": true, + "sms_auth_enabled": true, + "twilio_verify_service_sid": "VA123", + "twilio_account_sid": "AC123", + "twilio_auth_token": "token", + }) + assertBool(t, output, "sms_code_enabled", true) +} + +// TestAuthPolicyGateConfig_AcceptsTenantID ensures BMW's tenant_id config +// supplied to step.auth_policy_gate passes strict-proto validation. +func TestAuthPolicyGateConfig_AcceptsTenantID(t *testing.T) { + cfg := &contracts.AuthPolicyGateConfig{ + PolicyStep: "policy", + RequiredRuntimeKeys: []string{"tenant_id"}, + TenantId: "tenant-123", + } + packed, err := anypb.New(cfg) + if err != nil { + t.Fatalf("pack config: %v", err) + } + provider := NewAuthPlugin().(interface { + CreateTypedStep(typeName, name string, config *anypb.Any) (sdk.StepInstance, error) + }) + if _, err := provider.CreateTypedStep("step.auth_policy_gate", "gate", packed); err != nil { + t.Fatalf("CreateTypedStep rejected tenant_id: %v", err) + } +} + +// TestAuthChallengeVerifyConfig_AcceptsSigningSecret ensures the new +// AuthChallengeVerifyConfig accepts BMW's signing_secret config field. +func TestAuthChallengeVerifyConfig_AcceptsSigningSecret(t *testing.T) { + cfg := &contracts.AuthChallengeVerifyConfig{SigningSecret: "secret"} + packed, err := anypb.New(cfg) + if err != nil { + t.Fatalf("pack config: %v", err) + } + provider := NewAuthPlugin().(interface { + CreateTypedStep(typeName, name string, config *anypb.Any) (sdk.StepInstance, error) + }) + if _, err := provider.CreateTypedStep("step.auth_challenge_verify", "verify", packed); err != nil { + t.Fatalf("CreateTypedStep rejected signing_secret config: %v", err) + } +} + +// TestChallengeVerify_FallsBackToConfigSigningSecret ensures signing_secret +// supplied via config (not input) is honored by the handler. +func TestChallengeVerify_FallsBackToConfigSigningSecret(t *testing.T) { + gen := newChallengeGenerateStep("generate", nil) + genResult, err := gen.Execute(context.Background(), nil, nil, map[string]any{ + "channel": "email", + "destination": "user@example.com", + "tenant_id": "tenant-123", + "purpose": "login", + "signing_secret": "shared-secret", + }, nil, nil) + if err != nil { + t.Fatalf("generate: %v", err) + } + code, _ := genResult.Output["code"].(string) + codeHash, _ := genResult.Output["code_hash"].(string) + + verify := newChallengeVerifyStep("verify", map[string]any{ + "signing_secret": "shared-secret", + }) + verifyResult, err := verify.Execute(context.Background(), nil, nil, map[string]any{ + "channel": "email", + "destination": "user@example.com", + "tenant_id": "tenant-123", + "purpose": "login", + "code": code, + "code_hash": codeHash, + }, nil, nil) + if err != nil { + t.Fatalf("verify: %v", err) + } + if got, _ := verifyResult.Output["valid"].(bool); !got { + t.Fatalf("expected valid=true when signing_secret only supplied via config, got %#v", verifyResult.Output) + } +} diff --git a/plugin.contracts.json b/plugin.contracts.json index 17568c2..b3689f8 100644 --- a/plugin.contracts.json +++ b/plugin.contracts.json @@ -115,7 +115,7 @@ "kind": "step", "type": "step.auth_challenge_verify", "mode": "strict", - "config": "workflow.plugins.auth.v1.EmptyConfig", + "config": "workflow.plugins.auth.v1.AuthChallengeVerifyConfig", "input": "workflow.plugins.auth.v1.ChallengeVerifyInput", "output": "workflow.plugins.auth.v1.ChallengeVerifyOutput" }, diff --git a/plugin.json b/plugin.json index 828cd22..1003f2a 100644 --- a/plugin.json +++ b/plugin.json @@ -1,6 +1,6 @@ { "name": "workflow-plugin-auth", - "version": "0.2.1", + "version": "0.2.2", "description": "Passwordless authentication plugin: WebAuthn/passkeys, TOTP, email magic links", "author": "GoCodeAlone", "license": "MIT", @@ -22,22 +22,22 @@ { "os": "linux", "arch": "amd64", - "url": "https://github.com/GoCodeAlone/workflow-plugin-auth/releases/download/v0.2.1/workflow-plugin-auth_0.2.1_linux_amd64.tar.gz" + "url": "https://github.com/GoCodeAlone/workflow-plugin-auth/releases/download/v0.2.2/workflow-plugin-auth_0.2.2_linux_amd64.tar.gz" }, { "os": "linux", "arch": "arm64", - "url": "https://github.com/GoCodeAlone/workflow-plugin-auth/releases/download/v0.2.1/workflow-plugin-auth_0.2.1_linux_arm64.tar.gz" + "url": "https://github.com/GoCodeAlone/workflow-plugin-auth/releases/download/v0.2.2/workflow-plugin-auth_0.2.2_linux_arm64.tar.gz" }, { "os": "darwin", "arch": "amd64", - "url": "https://github.com/GoCodeAlone/workflow-plugin-auth/releases/download/v0.2.1/workflow-plugin-auth_0.2.1_darwin_amd64.tar.gz" + "url": "https://github.com/GoCodeAlone/workflow-plugin-auth/releases/download/v0.2.2/workflow-plugin-auth_0.2.2_darwin_amd64.tar.gz" }, { "os": "darwin", "arch": "arm64", - "url": "https://github.com/GoCodeAlone/workflow-plugin-auth/releases/download/v0.2.1/workflow-plugin-auth_0.2.1_darwin_arm64.tar.gz" + "url": "https://github.com/GoCodeAlone/workflow-plugin-auth/releases/download/v0.2.2/workflow-plugin-auth_0.2.2_darwin_arm64.tar.gz" } ], "moduleTypes": [