//
        // 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 != null) 
            { 
                // Did it return with an error?
                if (!String.IsNullOrEmpty(Request.Form["error"]))
                {
                    appState.ErrorMessage = Request.Form["error"];                
                    appState.AppIsAuthorized = false;

                    return View(appState);
                }

                // Authorized without error: Check to see if we have an ID token
                if (String.IsNullOrEmpty(Request.Form["id_token"]))
                {
                    appState.AppIsAuthorized = false;
                }
                else
                {
                    // 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.";
                        appState.AppIsAuthorized = false;

                        return View(appState);
                    }
                    if (!Request.Form["state"].Equals(authstate))
                    {
                        appState.ErrorMessage = "Oops. Something went wrong with the authorization state (Invalid auth state). Please retry.";
                        appState.AppIsAuthorized = false;

                        return View(appState);
                    }

                    // 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 = GetTenantId(Request.Form["id_token"]);
                    appState.TenantId = openIDToken.tid;
                    appState.TenantDomain = openIDToken.domain;
                    appState.LoggedOnUser = openIDToken.upn;

                    appState.AppIsAuthorized = true;
                }
            }

            if(appState.AppIsAuthorized)
            {
                // Get app-only access tokens ....
                try
                {
                    // Get an app-only access token for the AAD Graph Rest APIs
                    var authResult = await GetAppOnlyAccessToken(appConfig.GraphResourceUri, appState.TenantId);

                    // Get list of users in this Tenant from AAD Graph to fill drop down with smtp addresses
                    List<GraphUser> users = GetUsers(appState.TenantId, authResult.AccessToken);

                    appState.MailboxList = this.BuildMailboxDropDownList(string.Empty, users);
                    appState.MailboxSmtpAddress = appState.MailboxList.SelectedValue as String;

                    // For convenience maintain this list as a session
                    Session[AppSessionVariables.MailboxList] = users;

                    // Get app-only access tokens for Exchange Rest APIs
                    authResult = await GetAppOnlyAccessToken(appConfig.ExchangeResourceUri, appState.TenantId);

                    appState.AccessToken = authResult.AccessToken;
                    appState.AccessTokenAquiredWithoutError = true;
                    
                    SetSessionInProgress();
                }
                catch(Exception ex)
                {
                    appState.ErrorMessage = ex.Message;
                }
            }

            return View(appState);
        }
        public ActionResult Auhorize(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.GraphResourceUri) +
#if DEBUG
                    "&login_hint=" + appConfig.DebugOffice365User +
#endif
                    "&prompt=admin_consent" +
                    "&response_mode=form_post";

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

            return View("Index", passedAppState);
        }
        public ActionResult GetContacts(AppState passedAppState)
        {
            if (!IsSessionInProgress())
            {
                return RedirectHome();
            }

            string api = String.Format("{0}api/v1.0/users('{1}')/contacts?$top=50", appConfig.ExchangeResourceUri, passedAppState.MailboxSmtpAddress);

            MakeExchangeRestApiRequest(api, ref passedAppState);

            return View("Index", passedAppState);
        }
        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);
        }
        private void MakeExchangeRestApiRequest(string api, ref AppState passedAppState)
        {
            if (IsValidSmtp(passedAppState.MailboxSmtpAddress))
            {
                passedAppState.Request = api;

                Func<HttpRequestMessage> requestCreator = () =>
                {
                    HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, api);
                    request.Headers.Add("Accept", "application/json; odata.metadata=none");
                    return request;
                };

                string json = HttpRequestHelper.MakeHttpRequest(requestCreator, passedAppState.AccessToken);
                passedAppState.Response = JObject.Parse(json).ToString(/*Newtonsoft.Json.Formatting.Indented*/);
            }
            else
            {
                passedAppState.ErrorMessage = "Invalid SMTP";
            }

            List<GraphUser> users = Session[AppSessionVariables.MailboxList] as List<GraphUser>;
            passedAppState.MailboxList = BuildMailboxDropDownList(passedAppState.MailboxSmtpAddress, users);
        }