The XSRF-prevention token for the current user/session. To prevent cross-site request forgery, we set an '_xsrf' cookie and include the same '_xsrf' value as an argument with all POST requests. If the two do not match, we reject the form submission as a potential for
(self)
| 1535 | |
| 1536 | @property |
| 1537 | def xsrf_token(self) -> bytes: |
| 1538 | """The XSRF-prevention token for the current user/session. |
| 1539 | |
| 1540 | To prevent cross-site request forgery, we set an '_xsrf' cookie |
| 1541 | and include the same '_xsrf' value as an argument with all POST |
| 1542 | requests. If the two do not match, we reject the form submission |
| 1543 | as a potential forgery. |
| 1544 | |
| 1545 | See http://en.wikipedia.org/wiki/Cross-site_request_forgery |
| 1546 | |
| 1547 | This property is of type `bytes`, but it contains only ASCII |
| 1548 | characters. If a character string is required, there is no |
| 1549 | need to base64-encode it; just decode the byte string as |
| 1550 | UTF-8. |
| 1551 | |
| 1552 | .. versionchanged:: 3.2.2 |
| 1553 | The xsrf token will now be have a random mask applied in every |
| 1554 | request, which makes it safe to include the token in pages |
| 1555 | that are compressed. See http://breachattack.com for more |
| 1556 | information on the issue fixed by this change. Old (version 1) |
| 1557 | cookies will be converted to version 2 when this method is called |
| 1558 | unless the ``xsrf_cookie_version`` `Application` setting is |
| 1559 | set to 1. |
| 1560 | |
| 1561 | .. versionchanged:: 4.3 |
| 1562 | The ``xsrf_cookie_kwargs`` `Application` setting may be |
| 1563 | used to supply additional cookie options (which will be |
| 1564 | passed directly to `set_cookie`). For example, |
| 1565 | ``xsrf_cookie_kwargs=dict(httponly=True, secure=True)`` |
| 1566 | will set the ``secure`` and ``httponly`` flags on the |
| 1567 | ``_xsrf`` cookie. |
| 1568 | """ |
| 1569 | if not hasattr(self, "_xsrf_token"): |
| 1570 | version, token, timestamp = self._get_raw_xsrf_token() |
| 1571 | output_version = self.settings.get("xsrf_cookie_version", 2) |
| 1572 | cookie_kwargs = self.settings.get("xsrf_cookie_kwargs", {}) |
| 1573 | if output_version == 1: |
| 1574 | self._xsrf_token = binascii.b2a_hex(token) |
| 1575 | elif output_version == 2: |
| 1576 | mask = os.urandom(4) |
| 1577 | self._xsrf_token = b"|".join( |
| 1578 | [ |
| 1579 | b"2", |
| 1580 | binascii.b2a_hex(mask), |
| 1581 | binascii.b2a_hex(_websocket_mask(mask, token)), |
| 1582 | utf8(str(int(timestamp))), |
| 1583 | ] |
| 1584 | ) |
| 1585 | else: |
| 1586 | raise ValueError("unknown xsrf cookie version %d", output_version) |
| 1587 | if version is None: |
| 1588 | if self.current_user and "expires_days" not in cookie_kwargs: |
| 1589 | cookie_kwargs["expires_days"] = 30 |
| 1590 | cookie_name = self.settings.get("xsrf_cookie_name", "_xsrf") |
| 1591 | self.set_cookie(cookie_name, self._xsrf_token, **cookie_kwargs) |
| 1592 | return self._xsrf_token |
| 1593 | |
| 1594 | def _get_raw_xsrf_token(self) -> Tuple[Optional[int], bytes, float]: |
nothing calls this directly
no test coverage detected