redirect-url not same for login and logout

This commit is contained in:
2025-02-24 03:14:36 -06:00
parent 301b036f3c
commit d587e97dbe
4 changed files with 98 additions and 2 deletions

View File

@ -1,3 +1,62 @@
# member-console # member-console
Member console application for users to create, acccess, and manage their accounts associated with the Wiki Cafe MSC. Member console application for users to create, acccess, and manage their accounts associated with the Wiki Cafe MSC.
## Development notes:
- [ ] Implement backchannel logout
- [ ] Implement CSRF tokens
- [ ] Make sure viper's 'env' key will work correctly in production
---
- All protected pages should include CSRF tokens in forms
- Session timeout should match your security policy
example:
```
<button hx-get="/api/data" hx-headers='{"X-CSRF-Token": "{{.csrfToken}}"}'>
Load Data
</button>
```
---
Session Management:
- Use SameSite=Lax cookies
- Set Secure flag in production
- Rotate session secrets regularly
Error Handling:
- Custom error pages for 401/403 statuses
- Rate limiting on login attempts
Frontend Security:
- Content Security Policy (CSP)
- XSS protections in all templates
- Subresource Integrity (SRI) for CDN assets
Other:
- Back-Channel Logout:
- When a user logs out of the application, the application should notify the identity provider to log the user out of the identity provider as well.
---
- Secure headers?
- Content-Security-Policy
- Strict-Transport-Security
- X-Content-Type-Options
- X-Frame-Options
- X-XSS-Protection
- Referrer-Policy
- Expect-CT
- Feature-Policy
What is this??
```
w.Header().Set("Clear-Site-Data", `"cookies", "storage"`)
w.Header().Set("Strict-Transport-Security", "max-age=63072000; includeSubDomains")
```

View File

@ -99,7 +99,7 @@ var startCmd = &cobra.Command{
// 3. Build logout URL with post_logout_redirect_uri and id_token_hint // 3. Build logout URL with post_logout_redirect_uri and id_token_hint
q := keycloakLogoutURL.Query() q := keycloakLogoutURL.Query()
q.Set("post_logout_redirect_uri", viper.GetString("redirect-url")) q.Set("post_logout_redirect_uri", viper.GetString("post-logout-redirect-uri"))
q.Set("client_id", viper.GetString("client-id")) q.Set("client_id", viper.GetString("client-id"))
// Retrieve ID token from session if available // Retrieve ID token from session if available
@ -137,7 +137,8 @@ func init() {
startCmd.Flags().String("client-id", "", "OIDC Client ID") startCmd.Flags().String("client-id", "", "OIDC Client ID")
startCmd.Flags().String("client-secret", "", "OIDC Client Secret") startCmd.Flags().String("client-secret", "", "OIDC Client Secret")
startCmd.Flags().String("issuer-url", "", "Keycloak Issuer URL") startCmd.Flags().String("issuer-url", "", "Keycloak Issuer URL")
startCmd.Flags().String("redirect-url", "", "OAuth Redirect URL") startCmd.Flags().String("redirect-url", "", "OAuth Redirect URL") // Get rid of this
startCmd.Flags().String("post-logout-redirect-uri", "", "Post-logout redirect URI") // Get rid of this
startCmd.Flags().String("session-secret", "", "Session encryption secret") startCmd.Flags().String("session-secret", "", "Session encryption secret")
// Bind the flags to Viper // Bind the flags to Viper

View File

@ -116,6 +116,7 @@ func CallbackHandler(config *AuthConfig) http.HandlerFunc {
// Authenticate session // Authenticate session
session.Values["authenticated"] = true session.Values["authenticated"] = true
// session.Values["id_token"] = rawIDToken
session.Save(r, w) session.Save(r, w)
http.Redirect(w, r, "/", http.StatusFound) http.Redirect(w, r, "/", http.StatusFound)
} }

View File

@ -0,0 +1,35 @@
package middleware
import (
"net/http"
"github.com/gorilla/sessions"
)
// SecureHeaders is a middleware function that adds secure headers to the HTTP response
func SecureHeaders(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Security-Policy", "default-src 'self'")
w.Header().Set("Referrer-Policy", "strict-origin-when-cross-origin")
next.ServeHTTP(w, r)
})
}
// middleware/csrf.go
func CSRFMiddleware(store sessions.Store) Middleware {
return func(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if r.Method == "POST" {
session, _ := store.Get(r, "auth-session")
csrfToken := session.Values["csrf_token"].(string)
formToken := r.FormValue("_csrf")
if csrfToken != formToken {
http.Error(w, "Invalid CSRF token", http.StatusForbidden)
return
}
}
next.ServeHTTP(w, r)
})
}
}