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"));
            }
        }
Example #3
0
        // 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));
            }
        }
Example #4
0
        //
        // 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"));
            }
        }
Example #5
0
        // 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"));
        }