Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 13 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2562,15 +2562,16 @@ security:


#### OIDC
| Parameter | Description | Default |
|:---------------------------------|:---------------------------------------------------------------|:--------------|
| `security.oidc` | OpenID Connect configuration | `{}` |
| `security.oidc.issuer-url` | Issuer URL | Required `""` |
| `security.oidc.redirect-url` | Redirect URL. Must end with `/authorization-code/callback` | Required `""` |
| `security.oidc.client-id` | Client id | Required `""` |
| `security.oidc.client-secret` | Client secret | Required `""` |
| `security.oidc.scopes` | Scopes to request. The only scope you need is `openid`. | Required `[]` |
| `security.oidc.allowed-subjects` | List of subjects to allow. If empty, all subjects are allowed. | `[]` |
| Parameter | Description | Default |
|:---------------------------------|:-------------------------------------------------------------------------------|:--------------|
| `security.oidc` | OpenID Connect configuration | `{}` |
| `security.oidc.issuer-url` | Issuer URL | Required `""` |
| `security.oidc.redirect-url` | Redirect URL. Must end with `/authorization-code/callback` | Required `""` |
| `security.oidc.client-id` | Client id | Required `""` |
| `security.oidc.client-secret` | Client secret | Required `""` |
| `security.oidc.scopes` | Scopes to request. The only scope you need is `openid`. | Required `[]` |
| `security.oidc.allowed-subjects` | List of subjects to allow. If empty, all subjects are allowed. | `[]` |
| `security.oidc.login-redirect` | Automatically redirect to login page, without showing the "OIDC Login" button. | `false` |

```yaml
security:
Expand All @@ -2582,6 +2583,9 @@ security:
scopes: ["openid"]
# You may optionally specify a list of allowed subjects. If this is not specified, all subjects will be allowed.
#allowed-subjects: ["[email protected]"]
# You can also redirect to login page directly. This is useful when using one OIDC session for multiple applications,
# so if you log in once, you want to skip login flow in any of them.
#login-redirect: true
```

Confused? Read [Securing Gatus with OIDC using Auth0](https://twin.sh/articles/56/securing-gatus-with-oidc-using-auth0).
Expand Down
3 changes: 3 additions & 0 deletions api/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,19 @@ type ConfigHandler struct {

func (handler ConfigHandler) GetConfig(c *fiber.Ctx) error {
hasOIDC := false
loginRedirect := false
isAuthenticated := true // Default to true if no security config is set
if handler.securityConfig != nil {
hasOIDC = handler.securityConfig.OIDC != nil
loginRedirect = hasOIDC && handler.securityConfig.OIDC.LoginRedirect
isAuthenticated = handler.securityConfig.IsAuthenticated(c)
}

// Prepare response with announcements
response := map[string]interface{}{
"oidc": hasOIDC,
"authenticated": isAuthenticated,
"loginRedirect": loginRedirect,
}
// Add announcements if available, otherwise use empty slice
if handler.config != nil && handler.config.Announcements != nil && len(handler.config.Announcements) > 0 {
Expand Down
5 changes: 3 additions & 2 deletions api/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ func TestConfigHandler_ServeHTTP(t *testing.T) {
RedirectURL: "http://localhost:80/authorization-code/callback",
Scopes: []string{"openid"},
AllowedSubjects: []string{"[email protected]"},
LoginRedirect: true,
},
}
handler := ConfigHandler{securityConfig: securityConfig}
Expand All @@ -40,7 +41,7 @@ func TestConfigHandler_ServeHTTP(t *testing.T) {
if err != nil {
t.Error("expected err to be nil, but was", err)
}
if string(body) != `{"announcements":[],"authenticated":false,"oidc":true}` {
t.Error("expected body to be `{\"announcements\":[],\"authenticated\":false,\"oidc\":true}`, but was", string(body))
if string(body) != `{"announcements":[],"authenticated":false,"loginRedirect":true,"oidc":true}` {
t.Error("expected body to be `{\"announcements\":[],\"authenticated\":false,\"loginRedirect\":true,\"oidc\":true}`, but was", string(body))
}
}
1 change: 1 addition & 0 deletions security/oidc.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ type OIDCConfig struct {
ClientSecret string `yaml:"client-secret"`
Scopes []string `yaml:"scopes"` // e.g. ["openid"]
AllowedSubjects []string `yaml:"allowed-subjects"` // e.g. ["[email protected]"]. If empty, all subjects are allowed
LoginRedirect bool `yaml:"login-redirect"`

oauth2Config oauth2.Config
verifier *oidc.IDTokenVerifier
Expand Down
11 changes: 9 additions & 2 deletions web/app/src/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@

<script setup>
/* eslint-disable no-undef */
import { ref, computed, onMounted, onUnmounted } from 'vue'
import { ref, computed, onMounted, onUnmounted, onUpdated } from 'vue'
import { useRoute } from 'vue-router'
import { Menu, X, LogIn } from 'lucide-vue-next'
import { Button } from '@/components/ui/button'
Expand All @@ -168,7 +168,7 @@ const route = useRoute()

// State
const retrievedConfig = ref(false)
const config = ref({ oidc: false, authenticated: true })
const config = ref({ oidc: false, authenticated: true, loginRedirect: false })
const announcements = ref([])
const tooltip = ref({})
const mobileMenuOpen = ref(false)
Expand Down Expand Up @@ -220,6 +220,13 @@ onMounted(() => {
configInterval = setInterval(fetchConfig, 600000)
})

// Redirect to OIDC login if configured
onUpdated(() => {
if (!config.value.authenticated && config.value.loginRedirect) {
window.location.href = '/oidc/login';
}
})

// Clean up interval on unmount
onUnmounted(() => {
if (configInterval) {
Expand Down
2 changes: 1 addition & 1 deletion web/static/js/app.js

Large diffs are not rendered by default.