public ActionResult StartOver(AppState passedAppState)
      {
         if (!IsSessionInProgress())
         {
            return RedirectHome();
         }

         AppState appState = new AppState();

         Session.Clear();

         UriBuilder signOutRequest = new UriBuilder(appConfig.SignoutUri.Replace("common", passedAppState.TenantId));

         signOutRequest.Query = "post_logout_redirect_uri=" + HttpUtility.UrlEncode(appConfig.RedirectUri);

         RedirectResult result = Redirect(signOutRequest.Uri.ToString());
         result.ExecuteResult(this.ControllerContext);

         return View("Index", appState);
      }
      public ActionResult Authorize(AppState passedAppState)
      {
         passedAppState.AppIsAuthorized = false;

         // hit the common endpoint for authorization, 
         // after authorization we will use the tenant specific endpoint for getting app-only tokens
         UriBuilder authorizeRequest = new UriBuilder(appConfig.AuthorizationUri);

         // Maintain state for authorize request to prvenet cross forgery attacks
         var authstate = Guid.NewGuid().ToString();
         Session[AppSessionVariables.AuthState] = authstate;

         authorizeRequest.Query =
                 "state=" + authstate +
                 "&response_type=code+id_token" +
                 "&scope=openid" +
                 "&nonce=" + Guid.NewGuid().ToString() +
                 "&client_id=" + appConfig.ClientId +
                 "&redirect_uri=" + HttpUtility.UrlEncode(appConfig.RedirectUri) +
                 "&resource=" + HttpUtility.UrlEncode(appConfig.SharePointResourceUri) +
#if DEBUG1
                    "&login_hint=" + "*****@*****.**" +
#endif
//                    "&prompt=consent" +
                 "&response_mode=form_post";

         RedirectResult result = Redirect(authorizeRequest.Uri.ToString());
         result.ExecuteResult(this.ControllerContext);

         return View("Index", passedAppState);
      }
      //
      // GET: /Home/
      public async Task<ActionResult> Index()
      {
         // Force SSL
         if (!Request.IsSecureConnection)
         {
            string httplength = "http";
            string nonsecureurl = Request.Url.AbsoluteUri.Substring(httplength.Length);
            string secureurl = String.Format("https{0}", nonsecureurl);
            RedirectResult result = Redirect(secureurl);
            result.ExecuteResult(this.ControllerContext);
         }

         // This is where state of the app is maintained and data passed between view and controller
         AppState appState = new AppState();

         // Authorization back from AAD in a form post as requested in the authorize request
         if (!Request.Form.HasKeys())
         {
            return View(appState);
         }

         // Cool we have a form post

         // Did it return with an error?
         if (!String.IsNullOrEmpty(Request.Form["error"]))
         {
            appState.ErrorMessage = Request.Form["error"];
            return View(appState);
         }

         // Was it correlated with authorize request
         var authstate = Session[AppSessionVariables.AuthState] as String;
         Session[AppSessionVariables.AuthState] = null;
         if (String.IsNullOrEmpty(authstate))
         {
            appState.ErrorMessage = "Oops. Something went wrong with the authorization state (No auth state). Please retry.";
            return View(appState);
         }
         if (!Request.Form["state"].Equals(authstate))
         {
            appState.ErrorMessage = "Oops. Something went wrong with the authorization state (Invalid auth state). Please retry.";
            return View(appState);
         }

         // Authorized without error: Check to see if we have an ID token and code
         if (String.IsNullOrEmpty(Request.Form["id_token"]) || String.IsNullOrEmpty(Request.Form["code"]))
         {
            return View(appState);
         }

         try
         {
            // Get the TenantId out of the ID Token to address tenant specific token endpoint.
            // No validation of ID Token as the only info we need is the tenantID
            // If for any case your app wants to use the ID Token to authenticate 
            // it must be validated.
            JwtToken openIDToken = DecodeIDToken(Request.Form["id_token"]);
            appState.TenantId = openIDToken.tid;
            appState.TenantDomain = openIDToken.domain;
            appState.LoggedOnUser = openIDToken.upn;

            // Get an app-only access token for the AAD Graph Rest APIs
            var token = await GetAccessTokenByAuthorisationCode(Request.Form["code"], appState.TenantId);
            appState.AccessToken = token.access_token;
            appState.AccessTokenAquiredWithoutError = true;
            appState.AppIsAuthorized = true;

            SetSessionInProgress();

            /* Make a SharePoint REST (GET) call using the AAD access token */
            var siteUrl = "https://platinumdogsconsulting.sharepoint.com/sites/publishing";
            var requestUrl = siteUrl + "/_api/Web/Lists";
            var client = new HttpClient();
            var request = new HttpRequestMessage(HttpMethod.Get, requestUrl);
            request.Headers.Accept.Add(MediaTypeWithQualityHeaderValue.Parse("application/json;odata=verbose"));
            request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token.access_token);
            var response = await client.SendAsync(request);
            if (response.IsSuccessStatusCode)
            {
               var responseString = await response.Content.ReadAsStringAsync();
               Debug.WriteLine(string.Format("\n***REST (GET) API  Response:\n{0}\n", responseString));

               var spLists = JsonConvert.DeserializeObject<SpListJsonCollection>(responseString);
               appState.RestWebLists = spLists.d.results;
            }
            else
            {
               Debug.WriteLine(string.Format("***REST (GET) API RESPONSE ERROR: {0}, {1}", response.StatusCode, response.ReasonPhrase));
            }

            /* Make a SharePoint REST (POST) call using the AAD access token */
            var formDigest = await GetFormDigest(siteUrl, token.access_token);

            var announcementTitle = string.Format("Welcome from SimpleWebAppCodeFlow - {0}", DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss"));
            requestUrl = siteUrl + "/_api/Web/Lists/GetByTitle('Announcements')/Items";
            request = new HttpRequestMessage(HttpMethod.Post, requestUrl);
            request.Headers.Accept.Add(MediaTypeWithQualityHeaderValue.Parse("application/json;odata=verbose"));
            request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token.access_token);
            request.Headers.Add("X-RequestDigest", formDigest);

            var requestContent = new StringContent("{ '__metadata': { 'type': 'SP.Data.AnnouncementsListItem' }, 'Title': '" + announcementTitle + "'}");
            requestContent.Headers.ContentType = MediaTypeHeaderValue.Parse("application/json;odata=verbose");
            request.Content = requestContent;
            response = await client.SendAsync(request);
            if (response.IsSuccessStatusCode)
            {
               var responseString = await response.Content.ReadAsStringAsync();
               Debug.WriteLine(string.Format("\n***REST (POST) API Response:\n{0}\n", responseString));
            }
            else
            {
               Debug.WriteLine(string.Format("***REST (POST) API RESPONSE ERROR: {0}, {1}", response.StatusCode, response.ReasonPhrase));
            }

            /* Make a SharePoint CSOM call using the AAD access token */
            var ctx = new ClientContext(siteUrl);
            ctx.ExecutingWebRequest += (sender, e) =>
                  {
                     e.WebRequestExecutor.RequestHeaders["Authorization"] = "Bearer " + token.access_token;
                  };

            var web = ctx.Web;
            ctx.Load(web, w => w.Title, w => w.Url);
            ctx.ExecuteQuery();
            appState.CsomWebTitle = web.Title;
            appState.CsomWebUrl = web.Url;
         }
         catch (Exception ex)
         {
            appState.ErrorMessage = ex.Message;
         }

         return View(appState);
      }