public AuthModule(ITwitterAuthenticatedClient twitterApi, ITwitterUserTracker userTracker)
            : base("/auth")
        {
            this.Get["/signin", true] = async(_, __) =>
            {
                var callbackurl = new UriBuilder(
                    Request.Url.Scheme,
                    Request.Url.HostName,
                    Request.Url.Port ?? 80,
                    "/auth/callback");

                ViewBag.AuthUrl = await twitterApi.GetAuthorizationUri(callbackurl.ToString());

                return(View["SignIn"]);
            };

            this.Get["/callback", true] = async(_, __) =>
            {
                await twitterApi.Authenticate((string)Request.Query.oauth_token, (string)Request.Query.oauth_verifier);

                Guid sessionId = Guid.NewGuid();
                userTracker.Register(sessionId, twitterApi);

                return(this.LoginAndRedirect(sessionId));
            };
        }
        private async Task Authenticate(ITwitterAuthenticatedClient client)
        {
            // shared mutable state - won't be able to run tests in parallel
            HorribleOAuthHacks.Reset();
            var uri = await client.GetAuthorizationUri(string.Concat(OAuthInterceptorUri, "/", HorribleOAuthHacks.OAuthCallBack));

            //requires user interaction to authorize the app - brittle
            Process.Start(uri.ToString());

            //wait until the user has completed the oauth flow - might time out or hang
            await Wait.Until(() => HorribleOAuthHacks.IsOAuthSigninCompleted);

            //authenticate the service
            await client.Authenticate(HorribleOAuthHacks.OAuthToken, HorribleOAuthHacks.OAuthVerifier);
        }
        public void Register(Guid id, ITwitterAuthenticatedClient twitterApi)
        {
            if (id == default(Guid))
            {
                throw new ArgumentOutOfRangeException(nameof(id), "id must be initialized.");
            }

            if (twitterApi == null)
            {
                throw new ArgumentNullException(nameof(twitterApi));
            }

            if (!twitterApi.UserId.HasValue)
            {
                throw new InvalidOperationException("Cannot register an anauthorized Twitter Client");
            }

            this.sessionUserIdMap.TryAdd(id, twitterApi.UserId.Value);
            this.userClientMap.TryAdd(twitterApi.UserId.Value, twitterApi);
        }