Exemplo n.º 1
0
        /// <summary>
        /// Creates a new authentication broker based for the specified resource.
        /// <para/>
        /// Returns `<see langword="true"/>` if an authority could be determined; otherwise `<see langword="false"/>`.
        /// </summary>
        /// <param name="targetUri">The resource for which authentication is being requested.</param>
        /// <param name="scope">The scope of the access being requested.</param>
        /// <param name="personalAccessTokenStore">Storage container for personal access token secrets.</param>
        public static async Task <BaseAuthentication> GetAuthentication(
            RuntimeContext context,
            TargetUri targetUri,
            TokenScope scope,
            ICredentialStore personalAccessTokenStore)
        {
            if (context is null)
            {
                throw new ArgumentNullException(nameof(context));
            }
            if (targetUri is null)
            {
                throw new ArgumentNullException(nameof(targetUri));
            }
            if (scope is null)
            {
                throw new ArgumentNullException(nameof(scope));
            }
            if (personalAccessTokenStore is null)
            {
                throw new ArgumentNullException(nameof(personalAccessTokenStore));
            }

            BaseAuthentication authentication = null;

            var result = await DetectAuthority(context, targetUri);

            if (!result.HasValue)
            {
                return(null);
            }

            // Query for the tenant's identity
            Guid tenantId = result.Value;

            // empty identity is MSA, anything else is AAD
            if (tenantId == Guid.Empty)
            {
                context.Trace.WriteLine("MSA authority detected.");
                authentication = new MsaAuthentication(context, scope, personalAccessTokenStore);
            }
            else
            {
                context.Trace.WriteLine($"AAD authority for tenant '{tenantId}' detected.");
                authentication = new AadAuthentication(context, tenantId, scope, personalAccessTokenStore);
                (authentication as AadAuthentication).TenantId = tenantId;
            }

            return(authentication);
        }
        public static async Task <BaseAuthentication> CreateAuthentication(Program program, OperationArguments operationArguments)
        {
            if (operationArguments is null)
            {
                throw new ArgumentNullException(nameof(operationArguments));
            }
            if (operationArguments.TargetUri is null)
            {
                var innerException = new NullReferenceException($"`{operationArguments.TargetUri}` cannot be null.");
                throw new ArgumentException(innerException.Message, nameof(operationArguments), innerException);
            }

            var secretsNamespace         = operationArguments.CustomNamespace ?? Program.SecretsNamespace;
            BaseAuthentication authority = null;

            var basicCredentialCallback = (operationArguments.UseModalUi)
                    ? new AcquireCredentialsDelegate(program.ModalPromptForCredentials)
                    : new AcquireCredentialsDelegate(program.BasicCredentialPrompt);

            var bitbucketPrompts = new Bitbucket.AuthenticationPrompts(program.Context, operationArguments.ParentHwnd);

            var bitbucketCredentialCallback = (operationArguments.UseModalUi)
                    ? bitbucketPrompts.CredentialModalPrompt
                    : new Bitbucket.Authentication.AcquireCredentialsDelegate(program.BitbucketCredentialPrompt);

            var bitbucketOauthCallback = (operationArguments.UseModalUi)
                    ? bitbucketPrompts.AuthenticationOAuthModalPrompt
                    : new Bitbucket.Authentication.AcquireAuthenticationOAuthDelegate(program.BitbucketOAuthPrompt);

            var githubPrompts = new Github.AuthenticationPrompts(program.Context, operationArguments.ParentHwnd);

            var githubCredentialCallback = (operationArguments.UseModalUi)
                    ? new Github.Authentication.AcquireCredentialsDelegate(githubPrompts.CredentialModalPrompt)
                    : new Github.Authentication.AcquireCredentialsDelegate(program.GitHubCredentialPrompt);

            var githubAuthcodeCallback = (operationArguments.UseModalUi)
                    ? new Github.Authentication.AcquireAuthenticationCodeDelegate(githubPrompts.AuthenticationCodeModalPrompt)
                    : new Github.Authentication.AcquireAuthenticationCodeDelegate(program.GitHubAuthCodePrompt);

            NtlmSupport basicNtlmSupport = NtlmSupport.Auto;

            switch (operationArguments.Authority)
            {
            case AuthorityType.Auto:
                program.Trace.WriteLine($"detecting authority type for '{operationArguments.TargetUri}'.");

                // Detect the authority.
                authority = await Vsts.Authentication.GetAuthentication(program.Context,
                                                                        operationArguments.TargetUri,
                                                                        Program.VstsCredentialScope,
                                                                        new SecretStore(program.Context, secretsNamespace, Vsts.Authentication.UriNameConversion))
                            ?? Github.Authentication.GetAuthentication(program.Context,
                                                                       operationArguments.TargetUri,
                                                                       Program.GitHubCredentialScope,
                                                                       new SecretStore(program.Context, secretsNamespace, Secret.UriToName),
                                                                       githubCredentialCallback,
                                                                       githubAuthcodeCallback,
                                                                       null)
                            ?? Bitbucket.Authentication.GetAuthentication(program.Context,
                                                                          operationArguments.TargetUri,
                                                                          new SecretStore(program.Context, secretsNamespace, Secret.UriToIdentityUrl),
                                                                          bitbucketCredentialCallback,
                                                                          bitbucketOauthCallback);

                if (authority != null)
                {
                    // Set the authority type based on the returned value.
                    if (authority is Vsts.MsaAuthentication)
                    {
                        operationArguments.Authority = AuthorityType.MicrosoftAccount;
                        goto case AuthorityType.MicrosoftAccount;
                    }
                    else if (authority is Vsts.AadAuthentication)
                    {
                        operationArguments.Authority = AuthorityType.AzureDirectory;
                        goto case AuthorityType.AzureDirectory;
                    }
                    else if (authority is Github.Authentication)
                    {
                        operationArguments.Authority = AuthorityType.GitHub;
                        goto case AuthorityType.GitHub;
                    }
                    else if (authority is Bitbucket.Authentication)
                    {
                        operationArguments.Authority = AuthorityType.Bitbucket;
                        goto case AuthorityType.Bitbucket;
                    }
                }
                goto default;

            case AuthorityType.AzureDirectory:
                program.Trace.WriteLine($"authority for '{operationArguments.TargetUri}' is Azure Directory.");

                if (authority is null)
                {
                    Guid tenantId = Guid.Empty;

                    // Get the identity of the tenant.
                    var result = await Vsts.Authentication.DetectAuthority(program.Context, operationArguments.TargetUri);

                    if (result.HasValue)
                    {
                        tenantId = result.Value;
                    }

                    // Create the authority object.
                    authority = new Vsts.AadAuthentication(program.Context,
                                                           tenantId,
                                                           operationArguments.VstsTokenScope,
                                                           new SecretStore(program.Context, secretsNamespace, Vsts.AadAuthentication.UriNameConversion));
                }

                // Return the allocated authority or a generic AAD backed VSTS authentication object.
                return(authority);

            case AuthorityType.Basic:
                // Enforce basic authentication only.
                basicNtlmSupport = NtlmSupport.Never;
                goto default;

            case AuthorityType.GitHub:
                program.Trace.WriteLine($"authority for '{operationArguments.TargetUri}' is GitHub.");

                // Return a GitHub authentication object.
                return(authority ?? new Github.Authentication(program.Context,
                                                              operationArguments.TargetUri,
                                                              Program.GitHubCredentialScope,
                                                              new SecretStore(program.Context, secretsNamespace, Secret.UriToName),
                                                              githubCredentialCallback,
                                                              githubAuthcodeCallback,
                                                              null));

            case AuthorityType.Bitbucket:
                program.Trace.WriteLine($"authority for '{operationArguments.TargetUri}'  is Bitbucket.");

                // Return a Bitbucket authentication object.
                return(authority ?? new Bitbucket.Authentication(program.Context,
                                                                 new SecretStore(program.Context, secretsNamespace, Secret.UriToIdentityUrl),
                                                                 bitbucketCredentialCallback,
                                                                 bitbucketOauthCallback));

            case AuthorityType.MicrosoftAccount:
                program.Trace.WriteLine($"authority for '{operationArguments.TargetUri}' is Microsoft Live.");

                // Return the allocated authority or a generic MSA backed VSTS authentication object.
                return(authority ?? new Vsts.MsaAuthentication(program.Context,
                                                               operationArguments.VstsTokenScope,
                                                               new SecretStore(program.Context, secretsNamespace, Vsts.MsaAuthentication.UriNameConversion)));

            case AuthorityType.Ntlm:
                // Enforce NTLM authentication only.
                basicNtlmSupport = NtlmSupport.Always;
                goto default;

            default:
                program.Trace.WriteLine($"authority for '{operationArguments.TargetUri}' is basic with NTLM={basicNtlmSupport}.");

                // Return a generic username + password authentication object.
                return(authority ?? new BasicAuthentication(program.Context,
                                                            new SecretStore(program.Context, secretsNamespace, Secret.UriToIdentityUrl),
                                                            basicNtlmSupport,
                                                            basicCredentialCallback,
                                                            null));
            }
        }