mirror of
https://github.com/h44z/wg-portal.git
synced 2026-04-13 02:56:25 +00:00
OIDC - support IdP logout (#670)
* OIDC - support IdP logout Signed-off-by: Michael Tupitsyn <michael.tupitsyn@gmail.com> * Add support of logout_idp_session parameter Signed-off-by: Michael Tupitsyn <michael.tupitsyn@gmail.com> * Fix merge conflict issue Signed-off-by: Michael Tupitsyn <michael.tupitsyn@gmail.com> * Restore original package-lock.json Signed-off-by: Michael Tupitsyn <michael.tupitsyn@gmail.com> * Cleanup --------- Signed-off-by: Michael Tupitsyn <michael.tupitsyn@gmail.com> Co-authored-by: Christoph Haas <christoph.h@sprinternet.at>
This commit is contained in:
@@ -47,6 +47,7 @@ auth:
|
|||||||
- https://www.googleapis.com/auth/userinfo.email
|
- https://www.googleapis.com/auth/userinfo.email
|
||||||
- https://www.googleapis.com/auth/userinfo.profile
|
- https://www.googleapis.com/auth/userinfo.profile
|
||||||
registration_enabled: true
|
registration_enabled: true
|
||||||
|
logout_idp_session: true
|
||||||
- id: oidc2
|
- id: oidc2
|
||||||
provider_name: google2
|
provider_name: google2
|
||||||
display_name: Login with</br>Google2
|
display_name: Login with</br>Google2
|
||||||
@@ -57,6 +58,7 @@ auth:
|
|||||||
- https://www.googleapis.com/auth/userinfo.email
|
- https://www.googleapis.com/auth/userinfo.email
|
||||||
- https://www.googleapis.com/auth/userinfo.profile
|
- https://www.googleapis.com/auth/userinfo.profile
|
||||||
registration_enabled: true
|
registration_enabled: true
|
||||||
|
logout_idp_session: true
|
||||||
oauth:
|
oauth:
|
||||||
- id: google_plain_oauth
|
- id: google_plain_oauth
|
||||||
provider_name: google3
|
provider_name: google3
|
||||||
|
|||||||
@@ -600,6 +600,10 @@ Below are the properties for each OIDC provider entry inside `auth.oidc`:
|
|||||||
- **Description:** If `true`, sensitive OIDC user data, such as tokens and raw responses, will be logged at the trace level upon login (for debugging).
|
- **Description:** If `true`, sensitive OIDC user data, such as tokens and raw responses, will be logged at the trace level upon login (for debugging).
|
||||||
- **Important:** Keep this setting disabled in production environments! Remove logs once you finished debugging authentication issues.
|
- **Important:** Keep this setting disabled in production environments! Remove logs once you finished debugging authentication issues.
|
||||||
|
|
||||||
|
#### `logout_idp_session`
|
||||||
|
- **Default:** `true`
|
||||||
|
- **Description:** If `true` (default), WireGuard Portal will redirect the user to the OIDC provider's `end_session_endpoint` after local logout, terminating the session at the IdP as well. Set to `false` to only invalidate the local WireGuard Portal session without touching the IdP session.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### OAuth
|
### OAuth
|
||||||
|
|||||||
@@ -108,12 +108,19 @@ export const authStore = defineStore('auth',{
|
|||||||
this.setUserInfo(null)
|
this.setUserInfo(null)
|
||||||
this.ResetReturnUrl() // just to be sure^^
|
this.ResetReturnUrl() // just to be sure^^
|
||||||
|
|
||||||
|
let logoutResponse = null
|
||||||
try {
|
try {
|
||||||
await apiWrapper.post(`/auth/logout`)
|
logoutResponse = await apiWrapper.post(`/auth/logout`)
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log("Logout request failed:", e)
|
console.log("Logout request failed:", e)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const redirectUrl = logoutResponse?.RedirectUrl
|
||||||
|
if (redirectUrl) {
|
||||||
|
window.location.href = redirectUrl
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
notify({
|
notify({
|
||||||
title: "Logged Out",
|
title: "Logged Out",
|
||||||
text: "Logout successful!",
|
text: "Logout successful!",
|
||||||
|
|||||||
@@ -25,7 +25,9 @@ type AuthenticationService interface {
|
|||||||
// OauthLoginStep1 initiates the OAuth login flow.
|
// OauthLoginStep1 initiates the OAuth login flow.
|
||||||
OauthLoginStep1(_ context.Context, providerId string) (authCodeUrl, state, nonce string, err error)
|
OauthLoginStep1(_ context.Context, providerId string) (authCodeUrl, state, nonce string, err error)
|
||||||
// OauthLoginStep2 completes the OAuth login flow and logins the user in.
|
// OauthLoginStep2 completes the OAuth login flow and logins the user in.
|
||||||
OauthLoginStep2(ctx context.Context, providerId, nonce, code string) (*domain.User, error)
|
OauthLoginStep2(ctx context.Context, providerId, nonce, code string) (*domain.User, string, error)
|
||||||
|
// OauthProviderLogoutUrl returns an IdP logout URL for the given provider if supported.
|
||||||
|
OauthProviderLogoutUrl(providerId, idTokenHint, postLogoutRedirectUri string) (string, bool)
|
||||||
}
|
}
|
||||||
|
|
||||||
type WebAuthnService interface {
|
type WebAuthnService interface {
|
||||||
@@ -331,7 +333,7 @@ func (e AuthEndpoint) handleOauthCallbackGet() http.HandlerFunc {
|
|||||||
}
|
}
|
||||||
|
|
||||||
loginCtx, cancel := context.WithTimeout(context.Background(), 30*time.Second) // avoid long waits
|
loginCtx, cancel := context.WithTimeout(context.Background(), 30*time.Second) // avoid long waits
|
||||||
user, err := e.authService.OauthLoginStep2(loginCtx, provider, currentSession.OauthNonce,
|
user, idTokenHint, err := e.authService.OauthLoginStep2(loginCtx, provider, currentSession.OauthNonce,
|
||||||
oauthCode)
|
oauthCode)
|
||||||
cancel()
|
cancel()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -346,7 +348,7 @@ func (e AuthEndpoint) handleOauthCallbackGet() http.HandlerFunc {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
e.setAuthenticatedUser(r, user)
|
e.setAuthenticatedUser(r, user, provider, idTokenHint)
|
||||||
|
|
||||||
if returnUrl != nil && e.isValidReturnUrl(returnUrl.String()) {
|
if returnUrl != nil && e.isValidReturnUrl(returnUrl.String()) {
|
||||||
queryParams := returnUrl.Query()
|
queryParams := returnUrl.Query()
|
||||||
@@ -359,7 +361,7 @@ func (e AuthEndpoint) handleOauthCallbackGet() http.HandlerFunc {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e AuthEndpoint) setAuthenticatedUser(r *http.Request, user *domain.User) {
|
func (e AuthEndpoint) setAuthenticatedUser(r *http.Request, user *domain.User, oauthProvider, idTokenHint string) {
|
||||||
// start a fresh session
|
// start a fresh session
|
||||||
e.session.DestroyData(r.Context())
|
e.session.DestroyData(r.Context())
|
||||||
|
|
||||||
@@ -374,8 +376,9 @@ func (e AuthEndpoint) setAuthenticatedUser(r *http.Request, user *domain.User) {
|
|||||||
|
|
||||||
currentSession.OauthState = ""
|
currentSession.OauthState = ""
|
||||||
currentSession.OauthNonce = ""
|
currentSession.OauthNonce = ""
|
||||||
currentSession.OauthProvider = ""
|
currentSession.OauthProvider = oauthProvider
|
||||||
currentSession.OauthReturnTo = ""
|
currentSession.OauthReturnTo = ""
|
||||||
|
currentSession.OauthIdToken = idTokenHint
|
||||||
|
|
||||||
e.session.SetData(r.Context(), currentSession)
|
e.session.SetData(r.Context(), currentSession)
|
||||||
}
|
}
|
||||||
@@ -418,7 +421,7 @@ func (e AuthEndpoint) handleLoginPost() http.HandlerFunc {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
e.setAuthenticatedUser(r, user)
|
e.setAuthenticatedUser(r, user, "", "")
|
||||||
|
|
||||||
respond.JSON(w, http.StatusOK, user)
|
respond.JSON(w, http.StatusOK, user)
|
||||||
}
|
}
|
||||||
@@ -430,19 +433,33 @@ func (e AuthEndpoint) handleLoginPost() http.HandlerFunc {
|
|||||||
// @Tags Authentication
|
// @Tags Authentication
|
||||||
// @Summary Get all available external login providers.
|
// @Summary Get all available external login providers.
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Success 200 {object} model.Error
|
// @Success 200 {object} model.LogoutResponse
|
||||||
// @Router /auth/logout [post]
|
// @Router /auth/logout [post]
|
||||||
func (e AuthEndpoint) handleLogoutPost() http.HandlerFunc {
|
func (e AuthEndpoint) handleLogoutPost() http.HandlerFunc {
|
||||||
return func(w http.ResponseWriter, r *http.Request) {
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
currentSession := e.session.GetData(r.Context())
|
currentSession := e.session.GetData(r.Context())
|
||||||
|
|
||||||
if !currentSession.LoggedIn { // Not logged in
|
if !currentSession.LoggedIn { // Not logged in
|
||||||
respond.JSON(w, http.StatusOK, model.Error{Code: http.StatusOK, Message: "not logged in"})
|
respond.JSON(w, http.StatusOK, model.LogoutResponse{Message: "not logged in"})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
postLogoutRedirectUri := e.cfg.Web.ExternalUrl
|
||||||
|
if e.cfg.Web.BasePath != "" {
|
||||||
|
postLogoutRedirectUri += e.cfg.Web.BasePath
|
||||||
|
}
|
||||||
|
postLogoutRedirectUri += "/#/login"
|
||||||
|
|
||||||
|
var redirectUrl *string
|
||||||
|
if currentSession.OauthProvider != "" {
|
||||||
|
if idpLogoutUrl, ok := e.authService.OauthProviderLogoutUrl(currentSession.OauthProvider,
|
||||||
|
currentSession.OauthIdToken, postLogoutRedirectUri); ok {
|
||||||
|
redirectUrl = &idpLogoutUrl
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
e.session.DestroyData(r.Context())
|
e.session.DestroyData(r.Context())
|
||||||
respond.JSON(w, http.StatusOK, model.Error{Code: http.StatusOK, Message: "logout ok"})
|
respond.JSON(w, http.StatusOK, model.LogoutResponse{Message: "logout ok", RedirectUrl: redirectUrl})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -693,7 +710,7 @@ func (e AuthEndpoint) handleWebAuthnLoginFinish() http.HandlerFunc {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
e.setAuthenticatedUser(r, user)
|
e.setAuthenticatedUser(r, user, "", "")
|
||||||
|
|
||||||
respond.JSON(w, http.StatusOK, model.NewUser(user, false))
|
respond.JSON(w, http.StatusOK, model.NewUser(user, false))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ type SessionData struct {
|
|||||||
OauthNonce string
|
OauthNonce string
|
||||||
OauthProvider string
|
OauthProvider string
|
||||||
OauthReturnTo string
|
OauthReturnTo string
|
||||||
|
OauthIdToken string
|
||||||
|
|
||||||
WebAuthnData string
|
WebAuthnData string
|
||||||
|
|
||||||
@@ -89,5 +90,6 @@ func (s *SessionWrapper) defaultSessionData() SessionData {
|
|||||||
OauthNonce: "",
|
OauthNonce: "",
|
||||||
OauthProvider: "",
|
OauthProvider: "",
|
||||||
OauthReturnTo: "",
|
OauthReturnTo: "",
|
||||||
|
OauthIdToken: "",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,6 +45,11 @@ type OauthInitiationResponse struct {
|
|||||||
State string
|
State string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type LogoutResponse struct {
|
||||||
|
Message string `json:"Message"`
|
||||||
|
RedirectUrl *string `json:"RedirectUrl,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
type WebAuthnCredentialRequest struct {
|
type WebAuthnCredentialRequest struct {
|
||||||
Name string `json:"Name"`
|
Name string `json:"Name"`
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -68,6 +68,8 @@ type AuthenticatorOauth interface {
|
|||||||
// GetAllowedUserGroups returns the list of whitelisted user groups.
|
// GetAllowedUserGroups returns the list of whitelisted user groups.
|
||||||
// If non-empty, at least one user group must match.
|
// If non-empty, at least one user group must match.
|
||||||
GetAllowedUserGroups() []string
|
GetAllowedUserGroups() []string
|
||||||
|
// GetLogoutUrl returns an IdP logout URL if supported by the provider.
|
||||||
|
GetLogoutUrl(idTokenHint, postLogoutRedirectUri string) (string, bool)
|
||||||
}
|
}
|
||||||
|
|
||||||
// AuthenticatorLdap is the interface for all LDAP authenticators.
|
// AuthenticatorLdap is the interface for all LDAP authenticators.
|
||||||
@@ -529,33 +531,34 @@ func isAnyAllowedUserGroup(userGroups, allowedUserGroups []string) bool {
|
|||||||
|
|
||||||
// OauthLoginStep2 finishes the oauth authentication flow by exchanging the code for an access token and
|
// OauthLoginStep2 finishes the oauth authentication flow by exchanging the code for an access token and
|
||||||
// fetching the user information.
|
// fetching the user information.
|
||||||
func (a *Authenticator) OauthLoginStep2(ctx context.Context, providerId, nonce, code string) (*domain.User, error) {
|
func (a *Authenticator) OauthLoginStep2(ctx context.Context, providerId, nonce, code string) (*domain.User, string, error) {
|
||||||
oauthProvider, ok := a.oauthAuthenticators[providerId]
|
oauthProvider, ok := a.oauthAuthenticators[providerId]
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("missing oauth provider %s", providerId)
|
return nil, "", fmt.Errorf("missing oauth provider %s", providerId)
|
||||||
}
|
}
|
||||||
|
|
||||||
oauth2Token, err := oauthProvider.Exchange(ctx, code)
|
oauth2Token, err := oauthProvider.Exchange(ctx, code)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("unable to exchange code: %w", err)
|
return nil, "", fmt.Errorf("unable to exchange code: %w", err)
|
||||||
}
|
}
|
||||||
|
idTokenHint, _ := oauth2Token.Extra("id_token").(string)
|
||||||
|
|
||||||
rawUserInfo, err := oauthProvider.GetUserInfo(ctx, oauth2Token, nonce)
|
rawUserInfo, err := oauthProvider.GetUserInfo(ctx, oauth2Token, nonce)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("unable to fetch user information: %w", err)
|
return nil, "", fmt.Errorf("unable to fetch user information: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
userInfo, err := oauthProvider.ParseUserInfo(rawUserInfo)
|
userInfo, err := oauthProvider.ParseUserInfo(rawUserInfo)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("unable to parse user information: %w", err)
|
return nil, "", fmt.Errorf("unable to parse user information: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if !isDomainAllowed(userInfo.Email, oauthProvider.GetAllowedDomains()) {
|
if !isDomainAllowed(userInfo.Email, oauthProvider.GetAllowedDomains()) {
|
||||||
return nil, fmt.Errorf("user %s is not in allowed domains", userInfo.Email)
|
return nil, "", fmt.Errorf("user %s is not in allowed domains", userInfo.Email)
|
||||||
}
|
}
|
||||||
|
|
||||||
if !isAnyAllowedUserGroup(userInfo.UserGroups, oauthProvider.GetAllowedUserGroups()) {
|
if !isAnyAllowedUserGroup(userInfo.UserGroups, oauthProvider.GetAllowedUserGroups()) {
|
||||||
return nil, fmt.Errorf("user %s is not in allowed user groups", userInfo.Identifier)
|
return nil, "", fmt.Errorf("user %s is not in allowed user groups", userInfo.Identifier)
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx = domain.SetUserInfo(ctx,
|
ctx = domain.SetUserInfo(ctx,
|
||||||
@@ -571,7 +574,7 @@ func (a *Authenticator) OauthLoginStep2(ctx context.Context, providerId, nonce,
|
|||||||
Error: err.Error(),
|
Error: err.Error(),
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
return nil, fmt.Errorf("unable to process user information: %w", err)
|
return nil, "", fmt.Errorf("unable to process user information: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if user.IsLocked() || user.IsDisabled() {
|
if user.IsLocked() || user.IsDisabled() {
|
||||||
@@ -583,7 +586,7 @@ func (a *Authenticator) OauthLoginStep2(ctx context.Context, providerId, nonce,
|
|||||||
Error: "user is locked",
|
Error: "user is locked",
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
return nil, errors.New("user is locked")
|
return nil, "", errors.New("user is locked")
|
||||||
}
|
}
|
||||||
|
|
||||||
a.bus.Publish(app.TopicAuthLogin, user.Identifier)
|
a.bus.Publish(app.TopicAuthLogin, user.Identifier)
|
||||||
@@ -595,7 +598,16 @@ func (a *Authenticator) OauthLoginStep2(ctx context.Context, providerId, nonce,
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
return user, nil
|
return user, idTokenHint, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *Authenticator) OauthProviderLogoutUrl(providerId, idTokenHint, postLogoutRedirectUri string) (string, bool) {
|
||||||
|
oauthProvider, ok := a.oauthAuthenticators[providerId]
|
||||||
|
if !ok {
|
||||||
|
return "", false
|
||||||
|
}
|
||||||
|
|
||||||
|
return oauthProvider.GetLogoutUrl(idTokenHint, postLogoutRedirectUri)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *Authenticator) processUserInfo(
|
func (a *Authenticator) processUserInfo(
|
||||||
|
|||||||
@@ -79,6 +79,10 @@ func (p PlainOauthAuthenticator) GetAllowedUserGroups() []string {
|
|||||||
return p.allowedUserGroups
|
return p.allowedUserGroups
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p PlainOauthAuthenticator) GetLogoutUrl(_, _ string) (string, bool) {
|
||||||
|
return "", false
|
||||||
|
}
|
||||||
|
|
||||||
// RegistrationEnabled returns whether registration is enabled for the OAuth authenticator.
|
// RegistrationEnabled returns whether registration is enabled for the OAuth authenticator.
|
||||||
func (p PlainOauthAuthenticator) RegistrationEnabled() bool {
|
func (p PlainOauthAuthenticator) RegistrationEnabled() bool {
|
||||||
return p.registrationEnabled
|
return p.registrationEnabled
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log/slog"
|
"log/slog"
|
||||||
|
"net/url"
|
||||||
|
|
||||||
"github.com/coreos/go-oidc/v3/oidc"
|
"github.com/coreos/go-oidc/v3/oidc"
|
||||||
"golang.org/x/oauth2"
|
"golang.org/x/oauth2"
|
||||||
@@ -27,6 +28,8 @@ type OidcAuthenticator struct {
|
|||||||
sensitiveInfoLogging bool
|
sensitiveInfoLogging bool
|
||||||
allowedDomains []string
|
allowedDomains []string
|
||||||
allowedUserGroups []string
|
allowedUserGroups []string
|
||||||
|
endSessionEndpoint string
|
||||||
|
logoutIdpSession bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func newOidcAuthenticator(
|
func newOidcAuthenticator(
|
||||||
@@ -63,6 +66,16 @@ func newOidcAuthenticator(
|
|||||||
provider.sensitiveInfoLogging = cfg.LogSensitiveInfo
|
provider.sensitiveInfoLogging = cfg.LogSensitiveInfo
|
||||||
provider.allowedDomains = cfg.AllowedDomains
|
provider.allowedDomains = cfg.AllowedDomains
|
||||||
provider.allowedUserGroups = cfg.AllowedUserGroups
|
provider.allowedUserGroups = cfg.AllowedUserGroups
|
||||||
|
provider.logoutIdpSession = cfg.LogoutIdpSession == nil || *cfg.LogoutIdpSession
|
||||||
|
|
||||||
|
var providerMetadata struct {
|
||||||
|
EndSessionEndpoint string `json:"end_session_endpoint"`
|
||||||
|
}
|
||||||
|
if err = provider.provider.Claims(&providerMetadata); err != nil {
|
||||||
|
slog.Debug("OIDC: failed to parse provider metadata", "provider", cfg.ProviderName, "error", err)
|
||||||
|
} else {
|
||||||
|
provider.endSessionEndpoint = providerMetadata.EndSessionEndpoint
|
||||||
|
}
|
||||||
|
|
||||||
return provider, nil
|
return provider, nil
|
||||||
}
|
}
|
||||||
@@ -80,6 +93,34 @@ func (o OidcAuthenticator) GetAllowedUserGroups() []string {
|
|||||||
return o.allowedUserGroups
|
return o.allowedUserGroups
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (o OidcAuthenticator) GetLogoutUrl(idTokenHint, postLogoutRedirectUri string) (string, bool) {
|
||||||
|
if !o.logoutIdpSession {
|
||||||
|
return "", false
|
||||||
|
}
|
||||||
|
if o.endSessionEndpoint == "" {
|
||||||
|
slog.Debug("OIDC logout URL generation disabled: provider has no end_session_endpoint", "provider", o.name)
|
||||||
|
return "", false
|
||||||
|
}
|
||||||
|
|
||||||
|
logoutUrl, err := url.Parse(o.endSessionEndpoint)
|
||||||
|
if err != nil {
|
||||||
|
slog.Debug("OIDC logout URL generation failed, unable to parse end_session_endpoint url",
|
||||||
|
"provider", o.name, "error", err)
|
||||||
|
return "", false
|
||||||
|
}
|
||||||
|
|
||||||
|
params := logoutUrl.Query()
|
||||||
|
if idTokenHint != "" {
|
||||||
|
params.Set("id_token_hint", idTokenHint)
|
||||||
|
}
|
||||||
|
if postLogoutRedirectUri != "" {
|
||||||
|
params.Set("post_logout_redirect_uri", postLogoutRedirectUri)
|
||||||
|
}
|
||||||
|
logoutUrl.RawQuery = params.Encode()
|
||||||
|
|
||||||
|
return logoutUrl.String(), true
|
||||||
|
}
|
||||||
|
|
||||||
// RegistrationEnabled returns whether registration is enabled for this authenticator.
|
// RegistrationEnabled returns whether registration is enabled for this authenticator.
|
||||||
func (o OidcAuthenticator) RegistrationEnabled() bool {
|
func (o OidcAuthenticator) RegistrationEnabled() bool {
|
||||||
return o.registrationEnabled
|
return o.registrationEnabled
|
||||||
|
|||||||
@@ -278,6 +278,11 @@ type OpenIDConnectProvider struct {
|
|||||||
// If LogSensitiveInfo is set to true, sensitive information retrieved from the OIDC provider will be logged in trace level.
|
// If LogSensitiveInfo is set to true, sensitive information retrieved from the OIDC provider will be logged in trace level.
|
||||||
// This also includes OAuth tokens! Keep this disabled in production!
|
// This also includes OAuth tokens! Keep this disabled in production!
|
||||||
LogSensitiveInfo bool `yaml:"log_sensitive_info"`
|
LogSensitiveInfo bool `yaml:"log_sensitive_info"`
|
||||||
|
|
||||||
|
// LogoutIdpSession controls whether the user's session at the OIDC provider is terminated on logout.
|
||||||
|
// If set to true (default), the user will be redirected to the IdP's end_session_endpoint after local logout.
|
||||||
|
// If set to false, only the local wg-portal session is invalidated.
|
||||||
|
LogoutIdpSession *bool `yaml:"logout_idp_session"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// OAuthProvider contains the configuration for the OAuth provider.
|
// OAuthProvider contains the configuration for the OAuth provider.
|
||||||
|
|||||||
Reference in New Issue
Block a user