{"action":"opened","issue":{"url":"https://api.github.com/repos/mohiva/play-silhouette/issues/391","labels_url":"https://api.github.com/repos/mohiva/play-silhouette/issues/391/labels{/name}","comments_url":"https://api.github.com/repos/mohiva/play-silhouette/issues/391/comments","events_url":"https://api.github.com/repos/mohiva/play-silhouette/issues/391/events","html_url":"https://github.com/mohiva/play-silhouette/issues/391","id":94821626,"number":391,"title":"Add support for per-authentication-flow state to SocialProviders (feature request/design proposal)","user":{"login":"asazernik","id":1307640,"avatar_url":"https://avatars.githubusercontent.com/u/1307640?v=3","gravatar_id":"","url":"https://api.github.com/users/asazernik","html_url":"https://github.com/asazernik","followers_url":"https://api.github.com/users/asazernik/followers","following_url":"https://api.github.com/users/asazernik/following{/other_user}","gists_url":"https://api.github.com/users/asazernik/gists{/gist_id}","starred_url":"https://api.github.com/users/asazernik/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/asazernik/subscriptions","organizations_url":"https://api.github.com/users/asazernik/orgs","repos_url":"https://api.github.com/users/asazernik/repos","events_url":"https://api.github.com/users/asazernik/events{/privacy}","received_events_url":"https://api.github.com/users/asazernik/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":0,"created_at":"2015-07-13T21:56:22Z","updated_at":"2015-07-13T21:56:22Z","closed_at":null,"body":"The main application for this is redirection to the same page that a user originally requested but was not authenticated for; in OAuth2 there is a separate redirect_url (aka callbackURL) param, but most providers restrict that to a preset whitelist of URLs in order to combat CSRF attacks; the best practice recommended by e.g. [Google](https://developers.google.com/identity/protocols/OpenIDConnect#sendauthrequest) is to have `state` be a structured field that includes both the CSRF token *and* \"any other information needed to recover the context when the user returns to your application, e.g. the starting URL.\" Sessions and flash scope don't quite work, because they break in the case where a user has more than one tab/window open.\r\n\r\nMy proposal is to make two changes to the SocialProvider trait:\r\n\r\n1. Add a `userState: Map[String, String]` param to `SocialProvider.authenticate[B]()`, which will be inserted into the auth redirect on the initial request (i.e. when `authenticate()` returns a `Left[Result]`) and be re-inserted into the authInfo in a provider-specific way on auth completion.\r\n2. Add a `retrieveUserState(authInfo: A): Map[String, String]` which will allow a caller to retrieve this per-flow state on a successful authentication.\r\n\r\nI have a fairly good grasp on how to implement this for OAuth2Provider - change `authenticate()` to combine both `serializedState` (which I'd probably rename to `csrfState` for clarity) and the new `userState` param to get the `state` auth URL parameter, and change the `StateProvider.validate[B]` method to take an explicit `providerState` parameter instead of reading out the whole `state` callback URL param.\r\n\r\nI would appreciate both comments on this design as it applies to OAuth2 and tips for how to implement this for other providers; once I've gotten some design feedback I'll start putting a PR together."}}