/// <summary> /// The route handler for the request which connects the PhotoHunt /// user to Google+. /// </summary> /// <param name="context">The request/response context.</param> public override void ProcessRequest(HttpContext context) { User user = GetUser(context); ConnectHelper connectHelper = new ConnectHelper(); if (user == null) { if (context.Request.Cookies[Properties.Resources.MOBILE_SESSION_COOKIEID] != null) { context.Request.Cookies.Remove(Properties.Resources.MOBILE_SESSION_COOKIEID); } // Get the authorization code from the request POST body. StreamReader sr = new StreamReader( context.Request.InputStream); string input = sr.ReadToEnd(); TokenData td = (TokenData)(new TokenData().FromJson(input)); // Manually perform the OAuth2 flow for now. // TODO(class) Use the library for code exchange once // "postmessage" no longer throws exceptions in URI. if (td.code != null) { var authObject = ManualCodeExchanger.ExchangeCode(td.code); // Create an authorization state from the returned token. _authState = CreateState( authObject.access_token, authObject.refresh_token, DateTime.UtcNow, DateTime.UtcNow.AddSeconds(authObject.expires_in)); } else { // Create an authorization state from the returned token. _authState = CreateState( td.access_token, td.refresh_token, DateTime.UtcNow, DateTime.UtcNow.AddSeconds(td.expires_in)); } PhotoHunt.utils.ConnectHelper.VerifyToken(_authState); user = connectHelper.SaveTokenForUser(_authState); context.Session[Properties.Resources.CURRENT_USER_SESSION_KEY] = user.ToJson(); } SendResponse(context, new JsonUser(user)); }
/// <summary> /// Processes the request based on the path. /// </summary> /// <param name="context">Contains the request and response.</param> public void ProcessRequest(HttpContext context) { // Redirect base path to signin. if (context.Request.Path.Equals("/")) { context.Response.RedirectPermanent("signin.ashx"); } // This is reached when the root document is passed. Return HTML // using index.html as a template. if (context.Request.Path.Equals("/signin.ashx")) { String state = (String)context.Session["state"]; // Store a random string in the session for verifying // the responses in our OAuth2 flow. if (state == null) { Random random = new Random((int)DateTime.Now.Ticks); StringBuilder builder = new StringBuilder(); for (int i = 0; i < 13; i++) { builder.Append(Convert.ToChar( Convert.ToInt32(Math.Floor( 26 * random.NextDouble() + 65)))); } state = builder.ToString(); context.Session["state"] = state; } // Render the templated HTML. String templatedHTML = File.ReadAllText( context.Server.MapPath("index.html")); templatedHTML = Regex.Replace(templatedHTML, "[{]{2}\\s*APPLICATION_NAME\\s*[}]{2}", APP_NAME); templatedHTML = Regex.Replace(templatedHTML, "[{]{2}\\s*CLIENT_ID\\s*[}]{2}", CLIENT_ID); templatedHTML = Regex.Replace(templatedHTML, "[{]{2}\\s*STATE\\s*[}]{2}", state); context.Response.ContentType = "text/html"; context.Response.Write(templatedHTML); return; } if (context.Session["authState"] == null) { // The connect action exchanges a code from the sign-in button, // verifies it, and creates OAuth2 credentials. if (context.Request.Path.Contains("/connect")) { // Get the code from the request POST body. StreamReader sr = new StreamReader( context.Request.InputStream); string code = sr.ReadToEnd(); string state = context.Request["state"]; // Test that the request state matches the session state. if (!state.Equals(context.Session["state"])) { context.Response.StatusCode = 401; return; } // Manually perform the OAuth2 flow for now. var authObject = ManualCodeExchanger.ExchangeCode(code); // Create an authorization state from the returned token. context.Session["authState"] = CreateState( authObject.access_token, authObject.refresh_token, DateTime.UtcNow, DateTime.UtcNow.AddSeconds(authObject.expires_in)); string id_token = authObject.id_token; string[] segments = id_token.Split('.'); string base64EncoodedJsonBody = segments[1]; int mod4 = base64EncoodedJsonBody.Length % 4; if (mod4 > 0) { base64EncoodedJsonBody += new string( '=', 4 - mod4 ); } byte[] encodedBodyAsBytes = System.Convert.FromBase64String(base64EncoodedJsonBody); string json_body = System.Text.Encoding.UTF8.GetString(encodedBodyAsBytes); IDTokenJsonBodyObject bodyObject = JsonConvert.DeserializeObject <IDTokenJsonBodyObject>(json_body); string gplus_id = bodyObject.sub; } else { // No cached state and we are not connecting. context.Response.StatusCode = 400; return; } } else { // Register the authenticator and construct the Plus service // for performing API calls on behalf of the user. _authState = (IAuthorizationState)context.Session["authState"]; AuthorizationServerDescription description = GoogleAuthenticationServer.Description; var provider = new WebServerClient(description); provider.ClientIdentifier = CLIENT_ID; provider.ClientSecret = CLIENT_SECRET; var authenticator = new OAuth2Authenticator <WebServerClient>( provider, GetAuthorization) { NoCaching = true }; ps = new PlusService(new BaseClientService.Initializer() { Authenticator = authenticator }); } // Perform an authenticated API request to retrieve the list of // people that the user has made visible to the app. if (context.Request.Path.Contains("/people")) { // Get the PeopleFeed for the currently authenticated user. PeopleFeed pf = ps.People.List("me", PeopleResource.CollectionEnum.Visible).Fetch(); // This JSON, representing the people feed, will later be // parsed by the JavaScript client. string jsonContent = Newtonsoft.Json.JsonConvert.SerializeObject(pf); context.Response.ContentType = "application/json"; context.Response.Write(jsonContent); return; } // Disconnect the user from the application by revoking the tokens // and removing all locally stored data associated with the user. if (context.Request.Path.Contains("/disconnect")) { // Perform a get request to the token endpoint to revoke the // refresh token. _authState = (IAuthorizationState)context.Session["authState"]; string token = (_authState.RefreshToken != null) ? _authState.RefreshToken : _authState.AccessToken; WebRequest request = WebRequest.Create( "https://accounts.google.com/o/oauth2/revoke?token=" + token); WebResponse response = request.GetResponse(); // Remove the cached credentials. context.Session["authState"] = null; // You could reset the state in the session but you must also // reset the state on the client. // context.Session["state"] = null; context.Response.Write( response.GetResponseStream().ToString().ToCharArray()); return; } }