diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml
deleted file mode 100644
index ec5ab42349..0000000000
--- a/.github/workflows/ci.yaml
+++ /dev/null
@@ -1,69 +0,0 @@
-name: Continuous Integration
-
-on:
- push:
- branches:
- - '**'
- # - $default-branch
- pull_request:
- branches:
- - '**'
- # - $default-branch
-
-jobs:
- build:
- env:
- COVER: true
- runs-on: ubuntu-22.04
- steps:
-
- - name: Check out code
- uses: actions/checkout@v3
-
- - name: Set up Go 1.19
- uses: actions/setup-go@v2
- with:
- go-version: 1.19.x
- id: go
-
- - name: Get dependencies
- run: |
- curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(go env GOPATH)/bin v1.50.0
- curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > ./cc-test-reporter
- chmod +x ./cc-test-reporter
-
- - name: Verify Code Generation
- run: |
- make verify-generate
-
- - name: Lint
- run: |
- make lint
-
- - name: Build
- run: |
- make build
-
- - name: Test
- env:
- CC_TEST_REPORTER_ID: ${{ secrets.CC_TEST_REPORTER_ID }}
- run: |
- ./.github/workflows/test.sh
-
- docker:
- runs-on: ubuntu-22.04
- steps:
-
- - name: Check out code
- uses: actions/checkout@v3
-
- - name: Set up QEMU
- uses: docker/setup-qemu-action@v2
-
- - name: Set up Docker Buildx
- id: buildx
- uses: docker/setup-buildx-action@v2
-
- - name: Docker Build
- run: |
- make docker
diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml
deleted file mode 100644
index 1b95fcb8c1..0000000000
--- a/.github/workflows/codeql.yml
+++ /dev/null
@@ -1,57 +0,0 @@
-name: "Code scanning - action"
-
-on:
- push:
- branches: [master, ]
- pull_request:
- # The branches below must be a subset of the branches above
- branches: [master]
- schedule:
- - cron: '0 15 * * 2'
-
-jobs:
- CodeQL-Build:
-
- strategy:
- fail-fast: false
-
- # CodeQL runs on ubuntu-latest and windows-latest
- runs-on: ubuntu-latest
-
- steps:
- - name: Checkout repository
- uses: actions/checkout@v3
- with:
- # We must fetch at least the immediate parents so that if this is
- # a pull request then we can checkout the head.
- fetch-depth: 2
-
- # If this run was triggered by a pull request event, then checkout
- # the head of the pull request instead of the merge commit.
- - run: git checkout HEAD^2
- if: ${{ github.event_name == 'pull_request' }}
-
- # Initializes the CodeQL tools for scanning.
- - name: Initialize CodeQL
- uses: github/codeql-action/init@v2
- with:
- languages: go
-
- # Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
- # If this step fails, then you should remove it and run the build manually (see below)
- - name: Autobuild
- uses: github/codeql-action/autobuild@v2
-
- # âšī¸ Command-line programs to run using the OS shell.
- # đ https://git.io/JvXDl
-
- # âī¸ If the Autobuild fails above, remove it and uncomment the following three lines
- # and modify them (or add more) to build your code if your project
- # uses a compiled language
-
- #- run: |
- # make bootstrap
- # make release
-
- - name: Perform CodeQL Analysis
- uses: github/codeql-action/analyze@v2
diff --git a/.github/workflows/docs.yaml b/.github/workflows/docs.yaml
deleted file mode 100644
index 514219d86a..0000000000
--- a/.github/workflows/docs.yaml
+++ /dev/null
@@ -1,72 +0,0 @@
-name: documentation
-
-on:
- pull_request:
- branches: [master]
- paths: ['docs/**']
- push:
- branches: [master]
- paths: ['docs/**']
-
-jobs:
- pull-request-check:
- if: github.event_name == 'pull_request'
- runs-on: ubuntu-latest
- steps:
- - uses: actions/checkout@v4
-
- - uses: actions/setup-node@v3
- with:
- node-version: 18
-
- - name: Test Build
- working-directory: ./docs
- run: |
- npm ci
- npm run build
-
- gh-pages-release:
- if: github.event_name == 'push'
- runs-on: ubuntu-latest
- permissions:
- contents: write
- steps:
- - uses: actions/checkout@v4
- with:
- path: master
-
- - uses: actions/checkout@v4
- with:
- ref: gh-pages
- path: gh-pages
-
- - uses: actions/setup-node@v3
- with:
- node-version: 18
-
- - name: Build docusaurus
- working-directory: master/docs
- id: build
- run: |
- echo "sha=$(git rev-parse HEAD)" >> $GITHUB_OUTPUT
- npm ci
- npm run build
-
- - name: Release to github pages
- env:
- GIT_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- working-directory: gh-pages
- run: |
- git config --local user.name "github-actions[bot]"
- git config --local user.email "41898282+github-actions[bot]@users.noreply.github.com"
-
- # Remove all files except .git
- git rm -r *
-
- # Copy the build files from master/docs/build to gh-pages
- cp -r ../master/docs/build/* .
-
- # Commit and push
- git add .
- git commit -m "Update documentation based on ${{ steps.build.outputs.sha }}"
- git push origin gh-pages
diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml
deleted file mode 100644
index d0b902c6f3..0000000000
--- a/.github/workflows/stale.yml
+++ /dev/null
@@ -1,17 +0,0 @@
-name: Mark stale issues and pull requests
-
-on:
- schedule:
- - cron: "0 0 * * *"
-
-jobs:
- stale:
-
- runs-on: ubuntu-latest
-
- steps:
- - uses: actions/stale@v8
- with:
- repo-token: ${{ secrets.GITHUB_TOKEN }}
- stale-issue-message: 'This issue has been inactive for 60 days. If the issue is still relevant please comment to re-activate the issue. If no action is taken within 7 days, the issue will be marked closed.'
- stale-pr-message: 'This pull request has been inactive for 60 days. If the pull request is still relevant please comment to re-activate the pull request. If no action is taken within 7 days, the pull request will be marked closed.'
diff --git a/.github/workflows/test.sh b/.github/workflows/test.sh
deleted file mode 100755
index 794b528f08..0000000000
--- a/.github/workflows/test.sh
+++ /dev/null
@@ -1,26 +0,0 @@
-#!/bin/bash
-# manually exiting from script, because after-build needs to run always
-set +e
-
-if [ -z $CC_TEST_REPORTER_ID ]; then
- echo "1. CC_TEST_REPORTER_ID is unset, skipping"
-else
- echo "1. Running before-build"
- ./cc-test-reporter before-build
-fi
-
-echo "2. Running test"
-make test
-TEST_STATUS=$?
-
-if [ -z $CC_TEST_REPORTER_ID ]; then
- echo "3. CC_TEST_REPORTER_ID is unset, skipping"
-else
- echo "3. Running after-build"
- ./cc-test-reporter after-build --exit-code $TEST_STATUS -t gocov --prefix $(go list -m)
-fi
-
-if [ "$TEST_STATUS" -ne 0 ]; then
- echo "Test failed, status code: $TEST_STATUS"
- exit $TEST_STATUS
-fi
diff --git a/CHANGELOG.md b/CHANGELOG.md
index fe8355c2f6..6d469f083e 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,9 @@
# Changelog
+### 7.5.1-0.3.2 (upcoming)
+
+* [PLT-3581] Add configurable sign-out URL via `--sign-out-url` / `OAUTH2_PROXY_SIGN_OUT_URL` to support non-standard IdP logout flows (e.g. Autentica/REDSARA)
+
### 7.5.1-0.3.1 (2025-06-30)
* [PLT-2291] Fix: Handle missing JWT cookie on oauth2-proxy logout
diff --git a/docs/docs/configuration/alpha_config.md b/docs/docs/configuration/alpha_config.md
index ad2f768297..1e79a3a580 100644
--- a/docs/docs/configuration/alpha_config.md
+++ b/docs/docs/configuration/alpha_config.md
@@ -410,6 +410,7 @@ Provider holds all configuration for a single provider
| `googleConfig` | _[GoogleOptions](#googleoptions)_ | GoogleConfig holds all configurations for Google provider. |
| `oidcConfig` | _[OIDCOptions](#oidcoptions)_ | OIDCConfig holds all configurations for OIDC provider
or providers utilize OIDC configurations. |
| `loginGovConfig` | _[LoginGovOptions](#logingovoptions)_ | LoginGovConfig holds all configurations for LoginGov provider. |
+| `sisConfig` | _[SISOptions](#sisoptions)_ | SISConfig holds all configurations for SIS provider. |
| `id` | _string_ | ID should be a unique identifier for the provider.
This value is required for all providers. |
| `provider` | _[ProviderType](#providertype)_ | Type is the OAuth provider
must be set from the supported providers group,
otherwise 'Google' is set as default |
| `name` | _string_ | Name is the providers display name
if set, it will be shown to the users in the login page. |
@@ -423,6 +424,7 @@ Provider holds all configuration for a single provider
| `scope` | _string_ | Scope is the OAuth scope specification |
| `allowedGroups` | _[]string_ | AllowedGroups is a list of restrict logins to members of this group |
| `code_challenge_method` | _string_ | The code challenge method |
+| `signOutURL` | _string_ | SignOutURL overrides the provider's default sign-out redirect URL |
### ProviderType
#### (`string` alias)
@@ -444,6 +446,17 @@ and oidc.
Providers is a collection of definitions for providers.
+### SISOptions
+
+(**Appears on:** [Provider](#provider))
+
+
+
+| Field | Type | Description |
+| ----- | ---- | ----------- |
+| `SISRootURL` | _string_ | SISRootURL is the OpenID Connect SISRoot URL |
+| `ClearExtraCookieNames` | _[]string_ | ClearExtraCookieNames sets cookie names to clear after sign out |
+
### SecretSource
(**Appears on:** [ClaimSource](#claimsource), [HeaderValue](#headervalue), [TLS](#tls))
diff --git a/pkg/apis/options/legacy_options.go b/pkg/apis/options/legacy_options.go
index 479818a7b5..7da480cee4 100644
--- a/pkg/apis/options/legacy_options.go
+++ b/pkg/apis/options/legacy_options.go
@@ -502,6 +502,7 @@ type LegacyProvider struct {
GoogleUseApplicationDefaultCredentials bool `flag:"google-use-application-default-credentials" cfg:"google_use_application_default_credentials"`
SISRootURL string `flag:"sis-root-url" cfg:"sis_root_url"`
+ SignOutURL string `flag:"sign-out-url" cfg:"sign_out_url"`
ClearExtraCookieNames []string `flag:"clear-extra-cookie-names" cfg:"clear_extra_cookie_names"`
// These options allow for other providers besides Google, with
@@ -671,6 +672,7 @@ func (l *LegacyProvider) convert() (Providers, error) {
Scope: l.Scope,
AllowedGroups: l.AllowedGroups,
CodeChallengeMethod: l.CodeChallengeMethod,
+ SignOutURL: l.SignOutURL,
}
// This part is out of the switch section for all providers that support OIDC
diff --git a/pkg/apis/options/providers.go b/pkg/apis/options/providers.go
index 80190c6d22..262d30b9aa 100644
--- a/pkg/apis/options/providers.go
+++ b/pkg/apis/options/providers.go
@@ -80,6 +80,8 @@ type Provider struct {
AllowedGroups []string `json:"allowedGroups,omitempty"`
// The code challenge method
CodeChallengeMethod string `json:"code_challenge_method,omitempty"`
+ // SignOutURL overrides the provider's default sign-out redirect URL
+ SignOutURL string `json:"signOutURL,omitempty"`
}
// ProviderType is used to enumerate the different provider type options
diff --git a/providers/providers.go b/providers/providers.go
index 03b2699d2a..04d09cb810 100644
--- a/providers/providers.go
+++ b/providers/providers.go
@@ -124,6 +124,7 @@ func newProviderDataFromConfig(providerConfig options.Provider) (*ProviderData,
"profile": {dst: &p.ProfileURL, raw: providerConfig.ProfileURL},
"validate": {dst: &p.ValidateURL, raw: providerConfig.ValidateURL},
"resource": {dst: &p.ProtectedResource, raw: providerConfig.ProtectedResource},
+ "signout": {dst: &p.SignOutURL, raw: providerConfig.SignOutURL},
} {
var err error
*u.dst, err = url.Parse(u.raw)
diff --git a/providers/sis.go b/providers/sis.go
index 1c6163716a..dc9316ddf1 100644
--- a/providers/sis.go
+++ b/providers/sis.go
@@ -274,8 +274,8 @@ func (p *SISProvider) GetSignOutURL(redirectURI string) string {
// copy URL
redirect := *p.SignOutURL
if redirectURI != "" {
- v := url.Values{}
- v.Add("rd", redirectURI)
+ v := redirect.Query()
+ v.Set("rd", redirectURI)
redirect.RawQuery = v.Encode()
}
return redirect.String()
diff --git a/providers/sis_test.go b/providers/sis_test.go
index 0f305f59cd..329762926b 100644
--- a/providers/sis_test.go
+++ b/providers/sis_test.go
@@ -61,6 +61,41 @@ func TestSISProviderOverrides(t *testing.T) {
assert.Equal(t, "profile", p.Data().Scope)
}
+func TestSISProviderGetSignOutURL(t *testing.T) {
+ tests := []struct {
+ name string
+ signOutURL string
+ redirectURI string
+ expected string
+ }{
+ {
+ name: "no redirect preserves sign-out URL as-is",
+ signOutURL: "https://sis.example.com/sso/logout",
+ redirectURI: "",
+ expected: "https://sis.example.com/sso/logout",
+ },
+ {
+ name: "redirect appended as rd param",
+ signOutURL: "https://sis.example.com/sso/logout",
+ redirectURI: "https://app.example.com/home",
+ expected: "https://sis.example.com/sso/logout?rd=https%3A%2F%2Fapp.example.com%2Fhome",
+ },
+ {
+ name: "existing query params preserved when adding rd",
+ signOutURL: "https://autentica.example.com/logout?appId=5784",
+ redirectURI: "https://app.example.com/home",
+ expected: "https://autentica.example.com/logout?appId=5784&rd=https%3A%2F%2Fapp.example.com%2Fhome",
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ u, _ := url.Parse(tt.signOutURL)
+ p := NewSISProvider(&ProviderData{SignOutURL: u}, options.SISOptions{})
+ assert.Equal(t, tt.expected, p.GetSignOutURL(tt.redirectURI))
+ })
+ }
+}
+
func TestSISProviderRedeem(t *testing.T) {
b := testSISBackend(map[string]string{
"/sso/oauth2.0/accessToken": "access_token=imaginary_access_token&expires=10000",