public async Task <ActionResult> GetRefreshTokenAndTest() { string userObjectID = ClaimsPrincipal.Current.FindFirst("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier").Value; IEnumerable <OAuthTokenSet> query = from OAuthTokenSet in model.OAuthTokens where OAuthTokenSet.userId == userObjectID select OAuthTokenSet; OAuthTokenSet usertoken = query.First(); model.OAuthTokens.Remove(usertoken); var result = await model.SaveChangesAsync(); string dest = "https://login.microsoftonline.com/b3aa98fb-8679-40e4-a942-6047017aa1a4/oauth2/token"; HttpWebRequest req = (HttpWebRequest)WebRequest.Create(dest); req.Method = "POST"; req.ContentType = "application/x-www-form-urlencoded"; string postData = String.Format("grant_type=refresh_token&refresh_token={0}&client_id={1}&client_secret={2}&resource={3}", usertoken.refreshToken, Startup.clientId, Startup.appKey, Startup.graphResourceId); System.Text.ASCIIEncoding encoding = new System.Text.ASCIIEncoding(); byte[] bytes = encoding.GetBytes(postData); req.ContentLength = bytes.Length; Stream nStream = req.GetRequestStream(); nStream.Write(bytes, 0, bytes.Length); nStream.Close(); HttpWebResponse resp = (HttpWebResponse)req.GetResponse(); System.Runtime.Serialization.Json.DataContractJsonSerializer json = new System.Runtime.Serialization.Json.DataContractJsonSerializer(typeof(OAuthTokenResponse)); OAuthTokenResponse recvtoken = json.ReadObject(resp.GetResponseStream()) as OAuthTokenResponse; OAuthTokenSet token = new OAuthTokenSet(); token.accessToken = recvtoken.access_token; token.tokenType = recvtoken.token_type; token.refreshToken = recvtoken.refresh_token; token.userId = userObjectID; token.resourceName = Startup.graphResourceId; token.accessTokenExpiry = DateTime.Now.AddSeconds(Convert.ToDouble(recvtoken.expires_in)).ToUniversalTime().ToString(DateTimeFormatInfo.CurrentInfo.UniversalSortableDateTimePattern); Random rnd = new Random(); token.Id = rnd.Next(); model.OAuthTokens.Add(token); result = await model.SaveChangesAsync(); string requestUrl = String.Format( CultureInfo.InvariantCulture, Startup.graphUserUrl, HttpUtility.UrlEncode(Startup.tenant)); HttpClient client = new HttpClient(); HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, requestUrl); request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token.accessToken); HttpResponseMessage response = await client.SendAsync(request); if (response.IsSuccessStatusCode) { ViewBag.RefreshTokenUsedOK = "true"; } string responseString = await response.Content.ReadAsStringAsync(); UserProfile profile = JsonConvert.DeserializeObject <UserProfile>(responseString); // Copy over only the fields recevied from GraphAPI profile.AccessToken = token.accessToken; profile.AccessTokenExpiry = token.accessTokenExpiry; profile.RefreshToken = token.refreshToken; return(View("Index", profile)); }
// // GET: /UserProfile/ public async Task <ActionResult> Index(string authError) { UserProfile profile = new UserProfile(); string userObjectID = ClaimsPrincipal.Current.FindFirst("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier").Value; // Always setup the OAuth /authorize URI to use Uri redirectUri = new Uri(Request.Url.GetLeftPart(UriPartial.Authority).ToString() + "/OAuth"); string state = GenerateState(userObjectID, Request.Url.ToString()); string msoauthUri = string.Format("{0}/oauth2/authorize?resource={1}&client_id={2}&response_type=code&redirect_uri={3}&state={4}", Startup.Authority, Url.Encode(Startup.graphResourceId), Startup.clientId, Url.Encode(redirectUri.ToString()), state); ViewBag.AuthorizationUrl = msoauthUri; // Check local OAuthDataStore to see if we have previously cached OAuth bearer tokens for this user. IEnumerable <OAuthTokenSet> query = from OAuthTokenSet in model.OAuthTokens where OAuthTokenSet.userId == userObjectID && OAuthTokenSet.state == state select OAuthTokenSet; if (query.GetEnumerator().MoveNext() == false) { authError = "AuthorizationRequired"; } else { OAuthTokenSet usertokens = query.First(); profile.AccessToken = usertokens.accessToken; profile.RefreshToken = usertokens.refreshToken; profile.AccessTokenExpiry = usertokens.accessTokenExpiry; authError = null; } // Leaving this chunk of code alone, it generates the URL that the user will be redirected to when they // opt to sign in again. Per OAuth2 flow, this redirect will send the user to MS OAuth endpoint where they // will enter their creds. The resulting Authorization code is then used to get tokens. The OAuthController // will redirect users back to this controller, where we should be able to continue because the user completed // OAuth ok. if (authError != null) { profile = new UserProfile(); profile.DisplayName = " "; profile.GivenName = " "; profile.Surname = " "; ViewBag.ErrorMessage = authError; return(View(profile)); } OAuthTokenSet token = query.First(); try { // // Call the Graph API and retrieve the user's profile. // string requestUrl = String.Format( CultureInfo.InvariantCulture, Startup.graphUserUrl, HttpUtility.UrlEncode(Startup.tenant)); HttpClient client = new HttpClient(); HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, requestUrl); request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token.accessToken); HttpResponseMessage response = await client.SendAsync(request); // // Return the user's profile in the view. // if (response.IsSuccessStatusCode) { string responseString = await response.Content.ReadAsStringAsync(); UserProfile tmp = JsonConvert.DeserializeObject <UserProfile>(responseString); // Copy over only the fields recevied from GraphAPI profile.DisplayName = tmp.DisplayName; profile.GivenName = tmp.GivenName; profile.Surname = tmp.Surname; return(View(profile)); } else if (response.StatusCode == HttpStatusCode.Unauthorized) { // // If the call failed, then drop the current access token and show the user an error indicating they might need to sign-in again. model.OAuthTokens.RemoveRange(model.OAuthTokens); model.SaveChanges(); profile = new UserProfile(); profile.DisplayName = " "; profile.GivenName = " "; profile.Surname = " "; ViewBag.ErrorMessage = "AuthorizationRequired"; return(View(profile)); } else { ViewBag.ErrorMessage = "Error Calling Graph API."; return(View("Error")); } } catch { ViewBag.ErrorMessage = "Error Calling Graph API."; return(View("Error")); } }
// GET: AppServiceCertificate public async Task <ActionResult> Index(string authError) { AppServiceCertificates appServiceCertificates = new AppServiceCertificates(); OAuthTokenSet usertoken = new OAuthTokenSet(); Models.AzureRMWebCertificates.AzureRMWebCertificatesList azureRMWebCertificatesList = new Models.AzureRMWebCertificates.AzureRMWebCertificatesList(); Models.AzureRMWebSites.ResourceManagerWebSites resourceManagerWebSites = new Models.AzureRMWebSites.ResourceManagerWebSites(); // Always setup the OAuth /authorize URI to use Uri redirectUri = new Uri(Request.Url.GetLeftPart(UriPartial.Authority).ToString() + "/OAuth"); string userObjectID = ClaimsPrincipal.Current.FindFirst("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier").Value; string state = GenerateState(userObjectID, Request.Url.ToString()); string msoauthUri = string.Format("{0}/oauth2/authorize?resource={1}&client_id={2}&response_type=code&redirect_uri={3}&state={4}", Startup.Authority, Url.Encode(Startup.resourceGroupsId), Startup.clientId, Url.Encode(redirectUri.ToString()), state); ViewBag.AuthorizationUrl = msoauthUri; // If we are loaded and we have no credentials, we will create a UserToken object to store the state that we include // in the link we construct to the Authorization endpoint. Once the user completes authorization, the OAuthController // will look up the user token that we created and fill it in with the tokens it obtains. if (authError != null) { usertoken.state = state; usertoken.userId = userObjectID; usertoken.resourceName = Startup.resourceGroupsId; model.OAuthTokens.Add(usertoken); await model.SaveChangesAsync(); return(View(appServiceCertificates)); } else { // Check local OAuthDataStore to see if we have previously cached OAuth bearer tokens for this user. IEnumerable <OAuthTokenSet> query = from OAuthTokenSet in model.OAuthTokens where OAuthTokenSet.userId == userObjectID && OAuthTokenSet.resourceName == Startup.resourceGroupsId select OAuthTokenSet; if (query.GetEnumerator().MoveNext() == false) { usertoken.state = state; usertoken.userId = userObjectID; usertoken.resourceName = Startup.resourceGroupsId; model.OAuthTokens.Add(usertoken); await model.SaveChangesAsync(); authError = "AuthorizationRequired"; } else { usertoken = query.First(); appServiceCertificates.AccessToken = usertoken.accessToken; appServiceCertificates.RefreshToken = usertoken.refreshToken; appServiceCertificates.AccessTokenExpiry = usertoken.accessTokenExpiry; authError = null; string requestUrl = String.Format( CultureInfo.InvariantCulture, Startup.resourceGroupsUrl, HttpUtility.UrlEncode(Startup.subscriptionId)); HttpClient client = new HttpClient(); HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, requestUrl); request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", usertoken.accessToken); HttpResponseMessage response = await client.SendAsync(request); string responseString = await response.Content.ReadAsStringAsync(); ResourceGroups resourceGroups = JsonConvert.DeserializeObject <ResourceGroups>(responseString); foreach (Value v in resourceGroups.value) { requestUrl = String.Format( CultureInfo.InvariantCulture, Startup.resourceManagerWebSitesUrl, HttpUtility.UrlEncode(Startup.subscriptionId), HttpUtility.UrlEncode(v.name)); client = new HttpClient(); request = new HttpRequestMessage(HttpMethod.Get, requestUrl); request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", usertoken.accessToken); response = await client.SendAsync(request); responseString = await response.Content.ReadAsStringAsync(); Models.AzureRMWebSites.ResourceManagerWebSiteInfo resourceManagerWebSiteInfo = JsonConvert.DeserializeObject <Models.AzureRMWebSites.ResourceManagerWebSiteInfo>(responseString); resourceManagerWebSites.webSites.Add(resourceManagerWebSiteInfo); AppServiceCertificate appServiceCertificate = new AppServiceCertificate(); foreach (Models.AzureRMWebSites.Value wsv in resourceManagerWebSiteInfo.value) { foreach (Models.AzureRMWebSites.Hostnamesslstate sslstate in wsv.properties.hostNameSslStates) { if (sslstate.sslState == 1) { appServiceCertificate.SiteName = sslstate.name; } } } requestUrl = String.Format( CultureInfo.InvariantCulture, Startup.resourceManagerWebCertificatesUrl, HttpUtility.UrlEncode(Startup.subscriptionId), HttpUtility.UrlEncode(v.name)); client = new HttpClient(); request = new HttpRequestMessage(HttpMethod.Get, requestUrl); request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", usertoken.accessToken); response = await client.SendAsync(request); responseString = await response.Content.ReadAsStringAsync(); Models.AzureRMWebCertificates.AzureRMWebCertificates azureRMWebCertificates = JsonConvert.DeserializeObject <Models.AzureRMWebCertificates.AzureRMWebCertificates>(responseString); foreach (Models.AzureRMWebCertificates.Value wsc in azureRMWebCertificates.value) { appServiceCertificate.KeyVaultSecretName = wsc.properties.keyVaultSecretName; appServiceCertificate.CertificateName = wsc.properties.subjectName; appServiceCertificate.KeyVaultId = wsc.properties.keyVaultId; appServiceCertificate.CertificateIssuer = wsc.properties.issuer; appServiceCertificate.CertificateExpiration = wsc.properties.expirationDate; appServiceCertificate.CertificateThumbprint = wsc.properties.thumbprint; appServiceCertificate.CertificateHostnames = wsc.properties.hostNames; } appServiceCertificates.appServiceCertificates.Add(appServiceCertificate); } } return(View(appServiceCertificates)); } }
// // This method will be invoked as a call-back from an authentication service (e.g., https://login.microsoftonline.com/). // It is not intended to be called directly, only as a redirect from the authorization request in UserProfileController. // On completion, the method will cache the refresh token and access tokens, and redirect to the URL // specified in the state parameter. // public async Task <ActionResult> Index(string code, string error, string error_description, string resource, string state) { string userObjectID = ClaimsPrincipal.Current.FindFirst("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier").Value; // NOTE: In production, OAuth must be done over a secure HTTPS connection. if (Request.Url.Scheme != "https" && !Request.Url.IsLoopback) { return(View("Error")); } // Ensure there is a state value on the response. If there is none, stop OAuth processing and display an error. if (state == null) { ViewBag.ErrorMessage = "Error Generating State."; return(View("Error")); } // Handle errors from the OAuth response, if any. If there are errors, stop OAuth processing and display an error. if (error != null) { return(View("Error")); } string redirectUri = ValidateState(state, userObjectID); if (redirectUri == null) { ViewBag.ErrorMessage = "Error Validating State."; return(View("Error")); } // Redeem the authorization code from the response for an access token and refresh token. // When this code completes, the user is redirected back to /UserProfile so the UserProfileController.Index // method can then fetch the tokens and use them in subsequent calls. try { // Replace this with code to get the access tokens manually string dest = "https://login.microsoftonline.com/b3aa98fb-8679-40e4-a942-6047017aa1a4/oauth2/token"; HttpWebRequest req = (HttpWebRequest)WebRequest.Create(dest); req.Method = "POST"; req.ContentType = "application/x-www-form-urlencoded"; string postData = String.Format("grant_type=authorization_code&client_id={0}&code={1}&redirect_uri={2}&client_secret={3}&resource={4}", Startup.clientId, code, new Uri(Request.Url.GetLeftPart(UriPartial.Path)), Startup.appKey, resource); System.Text.ASCIIEncoding encoding = new System.Text.ASCIIEncoding(); byte[] bytes = encoding.GetBytes(postData); req.ContentLength = bytes.Length; Stream nStream = req.GetRequestStream(); nStream.Write(bytes, 0, bytes.Length); nStream.Close(); HttpWebResponse resp = (HttpWebResponse)req.GetResponse(); System.Runtime.Serialization.Json.DataContractJsonSerializer json = new System.Runtime.Serialization.Json.DataContractJsonSerializer(typeof(OAuthTokenResponse)); OAuthTokenResponse recvtoken = json.ReadObject(resp.GetResponseStream()) as OAuthTokenResponse; OAuthDataStore model = new OAuthDataStore(); string encodedState = Url.Encode(state); IEnumerable <OAuthTokenSet> query = from OAuthTokenSet in model.OAuthTokens where OAuthTokenSet.state == encodedState select OAuthTokenSet; OAuthTokenSet token = query.First(); token.accessToken = recvtoken.access_token; token.tokenType = recvtoken.token_type; token.refreshToken = recvtoken.refresh_token; token.userId = userObjectID; token.state = state; token.accessTokenExpiry = DateTime.Now.AddSeconds(Convert.ToDouble(recvtoken.expires_in)).ToUniversalTime().ToString(DateTimeFormatInfo.CurrentInfo.UniversalSortableDateTimePattern); try { model.SaveChanges(); } catch (Exception e) { throw; } return(Redirect(redirectUri)); } catch (Exception e) { return(Redirect("/UserProfile/Index?authError=token")); } }
// POST: /AppServiceCertificate/ReplaceCertificate public async Task <ActionResult> ReplaceCertificate(AppServiceCertificate ascModel, string authError) { OAuthTokenSet usertoken = new OAuthTokenSet(); HttpClient client = null; // If we have a replacement cert passed to us, persist that to the database. if (Request.HttpMethod == HttpMethod.Post.Method) { ascStore.appServiceCertificates.Add(ascModel); ascStore.SaveChanges(); } string responseString = null; string userObjectID = ClaimsPrincipal.Current.FindFirst("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier").Value; Uri redirectUri = new Uri(Request.Url.GetLeftPart(UriPartial.Authority).ToString() + "/OAuth"); string state = GenerateState(userObjectID, Request.Url.ToString()); string msoauthUri = string.Format("{0}/oauth2/authorize?resource={1}&client_id={2}&response_type=code&redirect_uri={3}&state={4}", Startup.Authority, Url.Encode(Startup.keyVaultResourceUrl), Startup.clientId, Url.Encode(redirectUri.ToString()), state); ViewBag.AuthorizationUrl = msoauthUri; IEnumerable <OAuthTokenSet> query = from OAuthTokenSet in model.OAuthTokens where OAuthTokenSet.userId == userObjectID && OAuthTokenSet.resourceName == Startup.keyVaultResourceUrl select OAuthTokenSet; if (query.GetEnumerator().MoveNext() == false) { usertoken.state = state; usertoken.userId = userObjectID; usertoken.resourceName = Startup.keyVaultResourceUrl; model.OAuthTokens.Add(usertoken); await model.SaveChangesAsync(); authError = "AuthorizationRequired"; ViewBag.Error = "AuthorizationRequiredKV"; return(View(ascModel)); } else { usertoken = query.First(); authError = null; // If we were redirected here back from the OAuth /authorization endpoint // we need to redisplay the form instead of just processing the request. if (Request.HttpMethod == HttpMethod.Get.Method) { IEnumerable <AppServiceCertificate> cquery = from AppServiceCertificate in ascStore.appServiceCertificates where AppServiceCertificate.Replace == true select AppServiceCertificate; return(View(cquery.First())); } } string kvname = ascModel.ReplacementName.Replace('.', '-'); string requestUrl = String.Format( CultureInfo.InvariantCulture, Startup.keyVaultCreateCertificateUrl, Startup.keyVaultName, kvname); KeyVaultRequest keyVaultRequest = new KeyVaultRequest(); keyVaultRequest.policy = new Models.KeyVault.Policy(); keyVaultRequest.policy.x509_props = new X509_Props(); keyVaultRequest.policy.x509_props.subject = String.Format("CN={0}", ascModel.ReplacementName); string postData = JsonConvert.SerializeObject(keyVaultRequest); System.Text.ASCIIEncoding encoding = new System.Text.ASCIIEncoding(); byte[] bytes = encoding.GetBytes(postData); client = new HttpClient(); HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, requestUrl); request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", usertoken.accessToken); request.Content = new ByteArrayContent(bytes); request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/json"); HttpResponseMessage resp = await client.SendAsync(request); if (resp.StatusCode != HttpStatusCode.Accepted) { ViewBag.Error = "unauthorized"; AppServiceCertificates ascs = new AppServiceCertificates(); ascs.appServiceCertificates.Add(ascModel); return(RedirectToAction("Index", "AppServiceCertificate")); } else { } responseString = await resp.Content.ReadAsStringAsync(); dynamic result = JsonConvert.DeserializeObject <dynamic>(responseString); // Working with dynamic type here so I don't have to import all the object model definitions // for each type returned by the KeyVault REST API. KeyVaultRequestResponse kvResponse = new KeyVaultRequestResponse(); foreach (var item in result) { if (item.Name == "csr") { kvResponse.csr = item.Value; } if (item.Name == "id") { kvResponse.id = item.Value; } if (item.Name == "request_id") { kvResponse.requestID = item.Value; } } // Submit CSR to Condor service string zoneinfo = "fee52da0-0b58-11e8-af01-13126b5652e8"; WebApp.Models.Condor.CertificateSigningRequest req = new Models.Condor.CertificateSigningRequest(); req.certificateSigningRequest = kvResponse.getCSRWithHeaders(); req.zoneId = zoneinfo; JsonSerializerSettings serializerSettings = new JsonSerializerSettings(); serializerSettings.NullValueHandling = NullValueHandling.Ignore; postData = JsonConvert.SerializeObject(req, serializerSettings); encoding = new System.Text.ASCIIEncoding(); bytes = encoding.GetBytes(postData); client = new HttpClient(); request = new HttpRequestMessage(HttpMethod.Post, String.Format("{0}/v1/certificaterequests", condorURL)); request.Headers.Add("tppl-api-key", condorAPIKey); request.Content = new ByteArrayContent(bytes); request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/json"); resp = await client.SendAsync(request); // Now poll Condor API to wait for cert to be issued, then install in KeyVault by merging // with previously created request. responseString = await resp.Content.ReadAsStringAsync(); JsonConverter converter = new CondorCertReqConverter(); WebApp.Models.Condor.CertificateSigningRequest certreqresp = JsonConvert.DeserializeObject <Models.Condor.CertificateSigningRequest>(responseString, converter); bool wait = true; while (wait) { client = new HttpClient(); request = new HttpRequestMessage(HttpMethod.Get, String.Format("{0}/v1/certificaterequests/{1}", condorURL, certreqresp.id)); request.Headers.Add("tppl-api-key", condorAPIKey); resp = await client.SendAsync(request); responseString = await resp.Content.ReadAsStringAsync(); certreqresp = JsonConvert.DeserializeObject <Models.Condor.CertificateSigningRequest>(responseString, converter); if (certreqresp.status == "ISSUED") { wait = false; } System.Threading.Thread.Sleep(5000); } string status = certreqresp.status; return(RedirectToAction("Index", "AppServiceCertificate")); }