...
Add a cryptographically secure anti-csrf token to the request context viewScope
, on-entry
to any view-state. Then check the returned token (in the HTTP request) matches that stored in the viewScope
on proceed
a proceed event/
transition. If the token is invalid, prevent execution of the transition and re-render the view, else proceed.
...
- per-view (as on-entry, per request if on-render) synchroniser token - marginally safer than per-session or conversation etc. but more expensive. Although with the IdP only typically having one view a few views per flow, the efficiency/safety tradeoff is probably less of an issue.
- the token only needs to be stored for the lifetime it is required e.g. in the viewscopeof the view state.
- the token is only generated on view states, and is not generated when not needed e.g. when using a previous AuthenticationResult.
...
- A
CsrfToken
API interface . This defines token implementations that return token values and HTTP parameter names.- packaged inside
idp-session-api
. Although this maybe better inside ofjava-support, or idp-ui
?
- packaged inside
- A default implementation of CsrfToken, namely
SimpleCsrfToken
. Encapsulating both token value and HTTP parameter name as a non-empty Strings. Has no business logic.- packaged inside
idp-session-api
. Although this maybe better inside ofjava-support, or idp-ui
?
- packaged inside
- A
CsrfTokenManager
to provide helper methods for generating and validating anti-csrf tokens .- packaged inside
idp-session-impl
. Although this maybe better inside ofjava-support, or idp-ui
? - uses a configurable
SecureRandomIdentifierGenerationStrategy
to generate anti-csrf tokens - even though suitable, is generating a token and not an identifier. - currently fixed to a single implementation.contains predicate logic for token validation, but is not a Predicate type.
- packaged inside
- A
ValidateCsrfToken
action class. Extracts the CsrfToken from therequestContext
viewScope
and the CSRF token String value from the HTTP request. Delegates to theCsrfTokenManager
to compare them, if equal (String comparison) signals a ‘success’ event, if different signals a ‘failure’ event. Note here, as this action is (see later sections) nested within a transaction, any event with ID other than ‘success’, ‘yes’, or ‘true’ will prevent the transaction from executing.- is-a
AbstractProfileAction
, is not anAbstractValidationAction
- it does not produce anAuthenticationResult
.
- is-a
...
The anti-csrf token is generated on-entry
to a view state, and placed inside the SWF viewScope:. This could be added on-render if required.
Code Block |
---|
<on-entry> <evaluate expression="flowRequestContext.getActiveFlow().getApplicationContext().getBean('shibboleth.CsrfTokenManager').generateCsrfToken()" result="viewScope.csrfToken" /> </on-entry> |
...
the anti-csrf token stored in the viewScope is then compared to that returned as a HTTP parameter from the view. This needs to happen (because the token is bound to the viewScope) inside the view-state
before the proceed
transition is executed and the state exited. Hence, a ValidateCsrfToken
action is nested inside the proceed
transition:
...
- system wide enforcement of a synchroniser token based CSRF defence for SWF view-states.
- For internal views and any custom views created as part of IdP flow extensions.
- View-states can be excluded by configuration.
- CSRF defence could be turned easily be controlled (turned on/off as ) by a property in
idp.properties
- not implemented. - can, if configured correctly (e.g. catching invalid token exceptions in the flow), be used to show the default (or other) IdP error page with a custom message. Otherwise the generic uncaught exception message will be shown.
- CSRF tokens are refreshed per view render. Arguably slightly stronger than, for example, per-session tokens, as they could be used along with the session ID in a session fixation type attack.
...
- A
CsrfToken
API interface . This defines token implementations that return token values and HTTP parameter names.- packaged inside
idp-session-api
. Although this maybe better inside ofjava-support, or idp-ui
?
- packaged inside
- A default implementation of CsrfToken, namely
SimpleCsrfToken
. Encapsulating both token value and HTTP parameter name as a non-empty Strings. Has no business logic.- packaged inside
idp-session-api
. Although this maybe better inside ofjava-support, or idp-ui
?
- packaged inside
- A
CsrfTokenManager
to provide helper methods for generating and validating anti-csrf CSRF tokens .- packaged inside
idp-session-impl
. Although this maybe better inside ofjava-support, or idp-ui
? - uses a configurable
SecureRandomIdentifierGenerationStrategy
to generate anti-csrf tokens - even though suitable, maybe an abuse of its definitionis generating a token and not an identifier.. - currently fixed to a single implementation.
- contains predicate logic for token validation, but is not a Predicate type.
- packaged inside
- A
CsrfTokenFlowExecutionListener
which reacts to SWF lifecycle events.- adds CSRF tokens to the viewScope when views are rendering.
- checks the CSRF token in the request matches that stored in the view scope when a ‘proceed’ event occurs.
- Can be configured to ignore or exclude certain view-states by ID.
- An
InvalidCsrfTokenException
, subtype ofFlowExecutionException
, thrown when an invalid CSRF token is found.
...
To correctly transition the IdPEventIds.INVALID_CSRF_TOKEN
eventID event ID to an error page, a transition needs to be placed in the action-state where the validation profile actions action is evaluated (see next section), and a global transition needs to be defined that maps to an end-state.
...
Changes to password authn flow
The anti-csrf CSRF token is taken from the CsrfUIContext
and placed inside the SWF viewScope on-entry to render of the DisplayUsernamePasswordPage view-state (or any view-state as required):
...
Note, as the profile request context is already passed into the view, the CsrfUIContext and then token could be extracted by the view templating engine e.g. as is the case with the RelyingPartyContext in the login view.
...