Example #1
0
        private void StartConsentFlow(string loginEndPoint, AzureADApp azureApp, string redirectUri, string token, HttpClient httpClient, PSObject record, CmdletMessageWriter messageWriter, List <PermissionScope> scopes)
        {
            Host.UI.WriteLine(ConsoleColor.Yellow, Host.UI.RawUI.BackgroundColor, $"Starting consent flow.");

            var resource = scopes.FirstOrDefault(s => s.resourceAppId == PermissionScopes.ResourceAppId_Graph) != null ? $"https://{AzureAuthHelper.GetGraphEndPoint(AzureEnvironment)}/.default" : "https://microsoft.sharepoint-df.com/.default";

            var consentUrl = $"{loginEndPoint}/{Tenant}/v2.0/adminconsent?client_id={azureApp.AppId}&scope={resource}&redirect_uri={redirectUri}";


            if (OperatingSystem.IsWindows() && !NoPopup)
            {
                var waitTime = 60;
                // CmdletMessageWriter.WriteFormattedWarning(this, $"Waiting {waitTime} seconds to launch the consent flow in a popup window.\n\nThis wait is required to make sure that Azure AD is able to initialize all required artifacts. You can always navigate to the consent page manually:\n\n{consentUrl}");

                var progressRecord = new ProgressRecord(1, "Please wait...", $"Waiting {waitTime} seconds to launch the consent flow in a popup window. This wait is required to make sure that Azure AD is able to initialize all required artifacts.");

                for (var i = 0; i < waitTime; i++)
                {
                    progressRecord.PercentComplete = Convert.ToInt32((Convert.ToDouble(i) / Convert.ToDouble(waitTime)) * 100);
                    WriteProgress(progressRecord);
                    // if (Convert.ToDouble(i) % Convert.ToDouble(10) > 0)
                    // {
                    //     Host.UI.Write(ConsoleColor.Yellow, Host.UI.RawUI.BackgroundColor, "-");
                    // }
                    // else
                    // {
                    //     Host.UI.Write(ConsoleColor.Yellow, Host.UI.RawUI.BackgroundColor, $"[{i}]");
                    // }
                    System.Threading.Thread.Sleep(1000);

                    // Check if CTRL+C has been pressed and if so, abort the wait
                    if (Stopping)
                    {
                        Host.UI.WriteLine("Wait cancelled. You can provide consent manually by navigating to");
                        Host.UI.WriteLine(consentUrl);
                        break;
                    }
                }
                progressRecord.RecordType = ProgressRecordType.Completed;
                WriteProgress(progressRecord);

                if (!Stopping)
                {
                    // Host.UI.WriteLine(ConsoleColor.Yellow, Host.UI.RawUI.BackgroundColor, $"[{waitTime}]");

                    // Host.UI.WriteLine();

                    if (ParameterSpecified(nameof(Interactive)))
                    {
                        using (var authManager = AuthenticationManager.CreateWithInteractiveLogin(azureApp.AppId, (url, port) =>
                        {
                            BrowserHelper.OpenBrowserForInteractiveLogin(url, port, true, cancellationTokenSource);
                        }, Tenant, "You successfully provided consent", "You failed to provide consent.", AzureEnvironment))
                        {
                            authManager.GetAccessToken(resource, Microsoft.Identity.Client.Prompt.Consent);
                        }
                    }
                    else
                    {
                        BrowserHelper.GetWebBrowserPopup(consentUrl, "Please provide consent", new[] { ("https://pnp.github.io/powershell/consent.html", BrowserHelper.UrlMatchType.StartsWith) }, cancellationTokenSource: cancellationTokenSource, cancelOnClose: false);
Example #2
0
        private void StartConsentFlow(string loginEndPoint, AzureApp azureApp, string redirectUri, string token, HttpClient httpClient, PSObject record)
        {
            var consentUrl = $"{loginEndPoint}/{Tenant}/v2.0/adminconsent?client_id={azureApp.AppId}&scope=https://microsoft.sharepoint-df.com/.default&redirect_uri={redirectUri}";


            if (OperatingSystem.IsWindows() && !NoPopup)
            {
                var waitTime = 60;
                CmdletMessageWriter.WriteFormattedWarning(this, $"Waiting {waitTime} seconds to launch consent flow in a popup window.\n\nThis wait is required to make sure that Azure AD is able to initialize all required artifacts. You can always navigate to the consent page manually:\n\n{consentUrl}");

                for (var i = 0; i < waitTime; i++)
                {
                    if (Convert.ToDouble(i) % Convert.ToDouble(10) > 0)
                    {
                        Host.UI.Write(ConsoleColor.Yellow, Host.UI.RawUI.BackgroundColor, "-");
                    }
                    else
                    {
                        Host.UI.Write(ConsoleColor.Yellow, Host.UI.RawUI.BackgroundColor, $"[{i}]");
                    }
                    System.Threading.Thread.Sleep(1000);

                    // Check if CTRL+C has been pressed and if so, abort the wait
                    if (Stopping)
                    {
                        break;
                    }
                }

                if (!Stopping)
                {
                    Host.UI.WriteLine(ConsoleColor.Yellow, Host.UI.RawUI.BackgroundColor, $"[{waitTime}]");

                    Host.UI.WriteLine();

                    BrowserHelper.GetWebBrowserPopup(consentUrl, "Please provide consent", new[] { (redirectUri, BrowserHelper.UrlMatchType.StartsWith) });
Example #3
0
        protected override void ProcessRecord()
        {
            if (ParameterSpecified(nameof(Store)) && !OperatingSystem.IsWindows())
            {
                throw new PSArgumentException("The Store parameter is only supported on Microsoft Windows");
            }

            if (!string.IsNullOrWhiteSpace(OutPath))
            {
                if (!Path.IsPathRooted(OutPath))
                {
                    OutPath = Path.Combine(SessionState.Path.CurrentFileSystemLocation.Path, OutPath);
                }
            }
            else
            {
                OutPath = SessionState.Path.CurrentFileSystemLocation.Path;
            }

            var redirectUri = "https://pnp.github.io/powershell/consent.html";

            var messageWriter = new CmdletMessageWriter(this);

            cancellationTokenSource = new CancellationTokenSource();
            CancellationToken cancellationToken = cancellationTokenSource.Token;

            WriteVerbose(ParameterSetName);

            var loginEndPoint = string.Empty;
            var record        = new PSObject();

            using (var authenticationManager = new AuthenticationManager())
            {
                loginEndPoint = authenticationManager.GetAzureADLoginEndPoint(AzureEnvironment);
            }

            string token = GetAuthToken(messageWriter, loginEndPoint);

            if (!string.IsNullOrEmpty(token))
            {
                var cert = GetCertificate(record);


                using (var httpClient = new HttpClient())
                {
                    if (!AppExists(ApplicationName, httpClient, token))
                    {
                        var azureApp = CreateApp(loginEndPoint, httpClient, token, cert, redirectUri);

                        record.Properties.Add(new PSVariableProperty(new PSVariable("AzureAppId/ClientId", azureApp.AppId)));
                        record.Properties.Add(new PSVariableProperty(new PSVariable("Certificate Thumbprint", cert.GetCertHashString())));

                        StartConsentFlow(loginEndPoint, azureApp, redirectUri, token, httpClient, record);
                    }
                    else
                    {
                        throw new PSInvalidOperationException($"The application with name {ApplicationName} already exists.");
                    }
                }
            }
        }
Example #4
0
        private X509Certificate2 GetCertificate(PSObject record)
        {
            var cert = new X509Certificate2();

            if (ParameterSetName == ParameterSet_EXISTINGCERT)
            {
                if (!System.IO.Path.IsPathRooted(CertificatePath))
                {
                    CertificatePath = Path.Combine(SessionState.Path.CurrentFileSystemLocation.Path, CertificatePath);
                }
                // Ensure a file exists at the provided CertificatePath
                if (!File.Exists(CertificatePath))
                {
                    throw new PSArgumentException(string.Format(Resources.CertificateNotFoundAtPath, CertificatePath), nameof(CertificatePath));
                }

                try
                {
                    cert = new X509Certificate2(CertificatePath, CertificatePassword, X509KeyStorageFlags.Exportable | X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet);
                }
                catch (CryptographicException e) when(e.Message.Contains("The specified password is not correct"))
                {
                    throw new PSArgumentNullException(nameof(CertificatePassword), string.Format(Resources.PrivateKeyCertificateImportFailedPasswordIncorrect, nameof(CertificatePassword)));
                }

                // Ensure the certificate at the provided CertificatePath holds a private key
                if (!cert.HasPrivateKey)
                {
                    throw new PSArgumentException(string.Format(Resources.CertificateAtPathHasNoPrivateKey, CertificatePath), nameof(CertificatePath));
                }
            }
            else
            {
#if NETFRAMEWORK
                var x500Values = new List <string>();
                if (!MyInvocation.BoundParameters.ContainsKey("CommonName"))
                {
                    CommonName = ApplicationName;
                }
                if (!string.IsNullOrWhiteSpace(CommonName))
                {
                    x500Values.Add($"CN={CommonName}");
                }
                if (!string.IsNullOrWhiteSpace(Country))
                {
                    x500Values.Add($"C={Country}");
                }
                if (!string.IsNullOrWhiteSpace(State))
                {
                    x500Values.Add($"S={State}");
                }
                if (!string.IsNullOrWhiteSpace(Locality))
                {
                    x500Values.Add($"L={Locality}");
                }
                if (!string.IsNullOrWhiteSpace(Organization))
                {
                    x500Values.Add($"O={Organization}");
                }
                if (!string.IsNullOrWhiteSpace(OrganizationUnit))
                {
                    x500Values.Add($"OU={OrganizationUnit}");
                }

                string x500 = string.Join("; ", x500Values);

                if (ValidYears < 1 || ValidYears > 30)
                {
                    ValidYears = 10;
                }
                DateTime validFrom = DateTime.Today;
                DateTime validTo   = validFrom.AddYears(ValidYears);

                byte[] certificateBytes = CertificateHelper.CreateSelfSignCertificatePfx(x500, validFrom, validTo, CertificatePassword);
                cert = new X509Certificate2(certificateBytes, CertificatePassword, X509KeyStorageFlags.Exportable | X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet);
#else
                if (!MyInvocation.BoundParameters.ContainsKey("CommonName"))
                {
                    CommonName = ApplicationName;
                }
                DateTime validFrom = DateTime.Today;
                DateTime validTo   = validFrom.AddYears(ValidYears);
                cert = CertificateHelper.CreateSelfSignedCertificate(CommonName, Country, State, Locality, Organization, OrganizationUnit, CertificatePassword, CommonName, validFrom, validTo);
#endif
            }
            var pfxPath = string.Empty;
            var cerPath = string.Empty;


            if (Directory.Exists(OutPath))
            {
                pfxPath = Path.Combine(OutPath, $"{ApplicationName}.pfx");
                cerPath = Path.Combine(OutPath, $"{ApplicationName}.cer");
                byte[] certPfxData = cert.Export(X509ContentType.Pfx, CertificatePassword);
                File.WriteAllBytes(pfxPath, certPfxData);
                record.Properties.Add(new PSVariableProperty(new PSVariable("Pfx file", pfxPath)));

                byte[] certCerData = cert.Export(X509ContentType.Cert);
                File.WriteAllBytes(cerPath, certCerData);
                record.Properties.Add(new PSVariableProperty(new PSVariable("Cer file", cerPath)));
            }
            if (ParameterSpecified(nameof(Store)))
            {
                if (OperatingSystem.IsWindows())
                {
                    using (var store = new X509Store("My", Store))
                    {
                        store.Open(OpenFlags.ReadWrite);
                        store.Add(cert);
                        store.Close();
                    }
                    Host.UI.WriteLine(ConsoleColor.Yellow, Host.UI.RawUI.BackgroundColor, "Certificate added to store");
                }
            }
            return(cert);
        }
        protected override void ProcessRecord()
        {
            if (ParameterSpecified(nameof(Store)) && !OperatingSystem.IsWindows())
            {
                throw new PSArgumentException("The Store parameter is only supported on Microsoft Windows");
            }

            if (!string.IsNullOrWhiteSpace(OutPath))
            {
                if (!Path.IsPathRooted(OutPath))
                {
                    OutPath = Path.Combine(SessionState.Path.CurrentFileSystemLocation.Path, OutPath);
                }
            }
            else
            {
                OutPath = SessionState.Path.CurrentFileSystemLocation.Path;
            }

            var redirectUri = "http://localhost";

            if (ParameterSpecified(nameof(DeviceLogin)))
            {
                redirectUri = "https://pnp.github.io/powershell/consent.html";
            }

            var messageWriter = new CmdletMessageWriter(this);

            cancellationTokenSource = new CancellationTokenSource();
            CancellationToken cancellationToken = cancellationTokenSource.Token;

            var loginEndPoint = string.Empty;

            using (var authenticationManager = new AuthenticationManager())
            {
                loginEndPoint = authenticationManager.GetAzureADLoginEndPoint(AzureEnvironment);
            }

            var permissionScopes = new PermissionScopes();
            var scopes           = new List <PermissionScope>();

            if (this.Scopes != null)
            {
                foreach (var scopeIdentifier in this.Scopes)
                {
                    scopes.Add(permissionScopes.GetScope(scopeIdentifier));
                }
            }
            else
            {
                scopes.Add(permissionScopes.GetScope("SPO.Sites.FullControl.All"));
                scopes.Add(permissionScopes.GetScope("MSGraph.Group.ReadWrite.All"));
                scopes.Add(permissionScopes.GetScope("SPO.User.Read.All"));
                scopes.Add(permissionScopes.GetScope("MSGraph.User.Read.All"));
            }

            var record = new PSObject();

            string token = GetAuthToken(messageWriter);

            if (!string.IsNullOrEmpty(token))
            {
                var cert = GetCertificate(record);

                using (var httpClient = new HttpClient())
                {
                    if (!AppExists(ApplicationName, httpClient, token))
                    {
                        var azureApp = CreateApp(loginEndPoint, httpClient, token, cert, redirectUri, scopes);

                        record.Properties.Add(new PSVariableProperty(new PSVariable("AzureAppId/ClientId", azureApp.AppId)));
                        record.Properties.Add(new PSVariableProperty(new PSVariable("Certificate Thumbprint", cert.GetCertHashString())));
                        byte[] certPfxData  = cert.Export(X509ContentType.Pfx, CertificatePassword);
                        var    base64String = Convert.ToBase64String(certPfxData);
                        record.Properties.Add(new PSVariableProperty(new PSVariable("Base64Encoded", base64String)));
                        StartConsentFlow(loginEndPoint, azureApp, redirectUri, token, httpClient, record, messageWriter, scopes);
                    }
                    else
                    {
                        throw new PSInvalidOperationException($"The application with name {ApplicationName} already exists.");
                    }
                }
            }
        }