mirror of
https://github.com/TwiN/gatus.git
synced 2025-08-19 11:20:56 +02:00
feat(security): added the ability to use a different claim field to match against the allow-subjects list.
In this way you can use 'email' or 'preferred_username' to identify the users. If not specified the default is 'subject'.
This commit is contained in:
@@ -1518,6 +1518,7 @@ security:
|
||||
| `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.claim-to-check` | Name of the field to use to match against `allowed-subjects` | `""` |
|
||||
|
||||
```yaml
|
||||
security:
|
||||
@@ -1529,6 +1530,8 @@ security:
|
||||
scopes: ["openid"]
|
||||
# You may optionally specify a list of allowed subjects. If this is not specified, all subjects will be allowed.
|
||||
#allowed-subjects: ["johndoe@example.com"]
|
||||
# You can specify a different claim field to match against allowed-subjects. If not specified "subject" is used.
|
||||
#claim-to-check: "preferred_username"
|
||||
```
|
||||
|
||||
Confused? Read [Securing Gatus with OIDC using Auth0](https://twin.sh/articles/56/securing-gatus-with-oidc-using-auth0).
|
||||
|
@@ -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. ["user1@example.com"]. If empty, all subjects are allowed
|
||||
ClaimToCheck string `yaml:"claim-to-check"` // e.g. email. If empty, subject is used
|
||||
|
||||
oauth2Config oauth2.Config
|
||||
verifier *oidc.IDTokenVerifier
|
||||
@@ -117,14 +118,35 @@ func (c *OIDCConfig) callbackHandler(w http.ResponseWriter, r *http.Request) { /
|
||||
http.Redirect(w, r, "/", http.StatusFound)
|
||||
return
|
||||
}
|
||||
for _, subject := range c.AllowedSubjects {
|
||||
if strings.ToLower(subject) == strings.ToLower(idToken.Subject) {
|
||||
c.setSessionCookie(w, idToken)
|
||||
http.Redirect(w, r, "/", http.StatusFound)
|
||||
return
|
||||
|
||||
var claimToCheck = c.ClaimToCheck
|
||||
if len(claimToCheck) > 0 {
|
||||
var claimsMap map[string]interface{}
|
||||
if err := idToken.Claims(&claimsMap); err == nil {
|
||||
claimValue, ok := claimsMap[claimToCheck]
|
||||
if ok {
|
||||
for _, subject := range c.AllowedSubjects {
|
||||
if claimValue == subject {
|
||||
c.setSessionCookie(w, idToken)
|
||||
http.Redirect(w, r, "/", http.StatusFound)
|
||||
return
|
||||
}
|
||||
}
|
||||
log.Printf("[security.callbackHandler] Value %s of claim %s doesn't match any element of the list of allowed subjects", claimValue, claimToCheck)
|
||||
} else {
|
||||
log.Printf("[security.callbackHandler] Claim doesn't contain the field %s", claimToCheck)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for _, subject := range c.AllowedSubjects {
|
||||
if strings.ToLower(subject) == strings.ToLower(idToken.Subject) {
|
||||
c.setSessionCookie(w, idToken)
|
||||
http.Redirect(w, r, "/", http.StatusFound)
|
||||
return
|
||||
}
|
||||
}
|
||||
log.Printf("[security.callbackHandler] Subject %s is not in the list of allowed subjects", idToken.Subject)
|
||||
}
|
||||
log.Printf("[security.callbackHandler] Subject %s is not in the list of allowed subjects", idToken.Subject)
|
||||
http.Redirect(w, r, "/?error=access_denied", http.StatusFound)
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user