Skip to content
This repository was archived by the owner on May 22, 2023. It is now read-only.

Commit 4908b26

Browse files
committed
- Check if IDP-initiated login is allowed and if so assume that the RelayState is a deep-link.
- Guard against an IDP-initiated request that may not have the request ID in the claims. - Attempt to retrieve a state value using the RelayState first before checking if IDP-initiated flow is allowed.
1 parent ebc5f78 commit 4908b26

File tree

1 file changed

+26
-19
lines changed

1 file changed

+26
-19
lines changed

samlsp/middleware.go

Lines changed: 26 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,9 @@ func (m *Middleware) getPossibleRequestIDs(r *http.Request) []string {
184184
continue
185185
}
186186
claims := token.Claims.(jwt.MapClaims)
187-
rv = append(rv, claims["id"].(string))
187+
if id, ok := claims["id"]; ok {
188+
rv = append(rv, id.(string))
189+
}
188190
}
189191

190192
// If IDP initiated requests are allowed, then we can expect an empty response ID.
@@ -204,28 +206,33 @@ func (m *Middleware) Authorize(w http.ResponseWriter, r *http.Request, assertion
204206
redirectURI := "/"
205207
if relayState := r.Form.Get("RelayState"); relayState != "" {
206208
stateValue := m.ClientState.GetState(r, relayState)
207-
if stateValue == "" {
208-
m.ServiceProvider.Logger.Printf("cannot find corresponding state: %s", relayState)
209-
http.Error(w, http.StatusText(http.StatusForbidden), http.StatusForbidden)
210-
return
211-
}
209+
if stateValue != "" {
210+
jwtParser := jwt.Parser{
211+
ValidMethods: []string{jwtSigningMethod.Name},
212+
}
213+
state, err := jwtParser.Parse(stateValue, func(t *jwt.Token) (interface{}, error) {
214+
return secretBlock, nil
215+
})
216+
if err != nil || !state.Valid {
217+
m.ServiceProvider.Logger.Printf("Cannot decode state JWT: %s (%s)", err, stateValue)
218+
http.Error(w, http.StatusText(http.StatusForbidden), http.StatusForbidden)
219+
return
220+
}
221+
claims := state.Claims.(jwt.MapClaims)
222+
redirectURI = claims["uri"].(string)
212223

213-
jwtParser := jwt.Parser{
214-
ValidMethods: []string{jwtSigningMethod.Name},
215-
}
216-
state, err := jwtParser.Parse(stateValue, func(t *jwt.Token) (interface{}, error) {
217-
return secretBlock, nil
218-
})
219-
if err != nil || !state.Valid {
220-
m.ServiceProvider.Logger.Printf("Cannot decode state JWT: %s (%s)", err, stateValue)
224+
// delete the cookie
225+
m.ClientState.DeleteState(w, r, relayState)
226+
} else if m.AllowIDPInitiated {
227+
// If the state value couldn't be retrieved for the RelayState, and IDP-initiated flows are allowed
228+
// then use the RelayState value as the redirect URI itself.
229+
redirectURI = relayState
230+
} else {
231+
// Otherwise, redirect the user with a 403.
232+
m.ServiceProvider.Logger.Printf("cannot find corresponding state: %s", relayState)
221233
http.Error(w, http.StatusText(http.StatusForbidden), http.StatusForbidden)
222234
return
223235
}
224-
claims := state.Claims.(jwt.MapClaims)
225-
redirectURI = claims["uri"].(string)
226-
227-
// delete the cookie
228-
m.ClientState.DeleteState(w, r, relayState)
229236
}
230237

231238
now := saml.TimeNow()

0 commit comments

Comments
 (0)