Repository navigation
The oauth2, oauth1 and Apple callbacks now read the handshake token only from the JWT cookie set by the login step. They used TokenService.Get, which takes the JWT query parameter and the X-JWT header before the cookie, so a callback request could carry a handshake that the browser's own login never set and complete a login started elsewhere, leaving the browser signed in to an account it did not choose. Session tokens in the query or header work as before everywhere else (#329).
Two more callback fixes in the same change. The oauth1 callback panicked when the cookie held a session token and GET was in XSRFIgnoreMethods; it now answers 403 like the oauth2 and Apple callbacks. The callback also enforces the 30-minute expiry the login handlers put on the handshake, which the cookie path never checked. A handshake without an expiry is still accepted.
Two behaviour changes. A callback that sends the handshake in ?token= or X-JWT without the cookie now fails. No known integration does this: remark42 and the example finish OAuth through a browser popup that carries the cookie. A user who leaves the provider's consent page open for more than 30 minutes now has to start the login again.
Every oauth2 login through the shared oauth2 handler, which serves the built-in oauth2 providers except Apple and every AddCustomProvider registration, now uses PKCE with the S256 method. Servers without PKCE support ignore it, so there is nothing to configure, and a callback for a handshake issued before the upgrade sends no verifier (#327 by @paskal).
New TelegramHandler.ChatIDAttribute stores the user's raw Telegram chat ID as a string attribute under the given key on a fresh login, so an app can message the user through its bot. Empty keeps the current behaviour, and the user id stays the hashed value (c8b8b0b by @paskal).