Fix backchannel logout

Use access token to lookup session id. The userinfo endpoint does
not return the session id. Also add some debug logging.

Co-authored-by: Christian Richter <crichter@owncloud.com>
Co-authored-by: Michael Barz <mbarz@owncloud.com>
This commit is contained in:
Ralf Haferkamp
2023-04-20 18:04:52 +02:00
co-authored by Christian Richter Michael Barz
parent a08438c54e
commit 70a80125c3
4 changed files with 32 additions and 14 deletions
+17 -3
View File
@@ -220,7 +220,9 @@ type jse struct {
// handle backchannel logout requests as per https://openid.net/specs/openid-connect-backchannel-1_0.html#BCRequest
func (h *StaticRouteHandler) backchannelLogout(w http.ResponseWriter, r *http.Request) {
// parse the application/x-www-form-urlencoded POST request
logger := h.logger.SubloggerWithRequestID(r.Context())
if err := r.ParseForm(); err != nil {
logger.Warn().Err(err).Msg("ParseForm failed")
render.Status(r, http.StatusBadRequest)
render.JSON(w, r, jse{Error: "invalid_request", ErrorDescription: err.Error()})
return
@@ -228,6 +230,7 @@ func (h *StaticRouteHandler) backchannelLogout(w http.ResponseWriter, r *http.Re
logoutToken, err := h.oidcClient.VerifyLogoutToken(r.Context(), r.PostFormValue("logout_token"))
if err != nil {
logger.Warn().Err(err).Msg("VerifyLogoutToken failed")
render.Status(r, http.StatusBadRequest)
render.JSON(w, r, jse{Error: "invalid_request", ErrorDescription: err.Error()})
return
@@ -240,19 +243,30 @@ func (h *StaticRouteHandler) backchannelLogout(w http.ResponseWriter, r *http.Re
return
}
if err != nil {
logger.Error().Err(err).Msg("Error reading userinfo cache")
render.Status(r, http.StatusBadRequest)
render.JSON(w, r, jse{Error: "invalid_request", ErrorDescription: err.Error()})
return
}
for _, record := range records {
err = h.userInfoCache.Delete(string(record.Value))
if !errors.Is(err, microstore.ErrNotFound) {
if err != nil && !errors.Is(err, microstore.ErrNotFound) {
// Spec requires us to return a 400 BadRequest when the session could not be destroyed
h.logger.Err(err).Msg("could not delete user info from cache")
logger.Err(err).Msg("could not delete user info from cache")
render.Status(r, http.StatusBadRequest)
render.JSON(w, r, jse{Error: "invalid_request", ErrorDescription: err.Error()})
return
}
logger.Debug().Msg("Deleted userinfo from cache")
}
// we can ignore errors when cleaning up the lookup table
_ = h.userInfoCache.Delete(logoutToken.SessionId)
err = h.userInfoCache.Delete(logoutToken.SessionId)
if err != nil {
logger.Debug().Err(err).Msg("Failed to cleanup sessionid lookup entry")
}
render.Status(r, http.StatusOK)
render.JSON(w, r, nil)
+2 -3
View File
@@ -11,7 +11,6 @@ import (
"github.com/owncloud/ocis/v2/ocis-pkg/log"
"github.com/owncloud/ocis/v2/ocis-pkg/oidc"
"github.com/golang-jwt/jwt/v4"
"github.com/pkg/errors"
"github.com/shamaton/msgpack/v2"
store "go-micro.dev/v4/store"
@@ -104,7 +103,7 @@ func (m *OIDCAuthenticator) getClaims(token string, req *http.Request) (map[stri
m.Logger.Error().Err(err).Msg("failed to write to userinfo cache")
}
if sid, ok := claims["sid"]; ok {
if sid := aClaims.SessionID; sid != "" {
// reuse user cache for session id lookup
err = m.userInfoCache.Write(&store.Record{
Key: fmt.Sprintf("%s", sid),
@@ -125,7 +124,7 @@ func (m *OIDCAuthenticator) getClaims(token string, req *http.Request) (map[stri
// extractExpiration tries to extract the expriration time from the access token
// If the access token does not have an exp claim it will fallback to the configured
// default expiration
func (m OIDCAuthenticator) extractExpiration(aClaims jwt.RegisteredClaims) time.Time {
func (m OIDCAuthenticator) extractExpiration(aClaims oidc.RegClaimsWithSID) time.Time {
defaultExpiration := time.Now().Add(m.DefaultTokenCacheTTL)
if aClaims.ExpiresAt != nil {
m.Logger.Debug().Str("exp", aClaims.ExpiresAt.String()).Msg("Expiration Time from access_token")