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); }