func()

in cli/azd/pkg/auth/manager.go [202:350]


func (m *Manager) CredentialForCurrentUser(
	ctx context.Context,
	options *CredentialForCurrentUserOptions,
) (azcore.TokenCredential, error) {

	if options == nil {
		options = &CredentialForCurrentUserOptions{}
	}

	if m.UseExternalAuth() {
		log.Printf("delegating auth to external process")
		return newRemoteCredential(
			m.externalAuthCfg.Endpoint,
			m.externalAuthCfg.Key,
			options.TenantID,
			m.externalAuthCfg.Transporter), nil
	}

	userConfig, err := m.userConfigManager.Load()
	if err != nil {
		return nil, fmt.Errorf("fetching current user: %w", err)
	}

	if shouldUseLegacyAuth(userConfig) {
		log.Printf("delegating auth to az since %s is set to true", useAzCliAuthKey)
		cred, err := azidentity.NewAzureCLICredential(&azidentity.AzureCLICredentialOptions{
			TenantID: options.TenantID,
		})
		if err != nil {
			return nil, fmt.Errorf("failed to create credential: %w: %w", err, ErrNoCurrentUser)
		}
		return cred, nil
	}

	authConfig, err := m.readAuthConfig()
	if err != nil {
		return nil, fmt.Errorf("reading auth config: %w", err)
	}

	currentUser, err := readUserProperties(authConfig)
	if errors.Is(err, ErrNoCurrentUser) {
		// User is not logged in, not using az credentials, try CloudShell if possible
		if runcontext.IsRunningInCloudShell() {
			cloudShellCredential, err := m.newCredentialFromCloudShell()
			if err != nil {
				return nil, err
			}
			return cloudShellCredential, nil
		}
		if oneauth.Supported && strings.EqualFold(os.Getenv("IsDevBox"), "True") {
			// Try logging in the active OS account. If that fails for any reason, tell the user to run `azd auth login`.
			if err := m.LoginWithBrokerAccount(); err == nil {
				if config, err := m.readAuthConfig(); err == nil {
					user, err := readUserProperties(config)
					if err == nil && user != nil && user.HomeAccountID != nil && *user.HomeAccountID != "" {
						tenant := options.TenantID
						if tenant == "" {
							tenant = "organizations"
						}
						authority := m.cloud.Configuration.ActiveDirectoryAuthorityHost + tenant
						return oneauth.NewCredential(authority, azdClientID, oneauth.CredentialOptions{
							HomeAccountID: *user.HomeAccountID,
						})
					}
				}
			}
		}
		return nil, ErrNoCurrentUser
	}

	if currentUser.HomeAccountID != nil {
		if currentUser.FromOneAuth {
			tenant := options.TenantID
			if tenant == "" {
				tenant = "organizations"
			}

			authority, err := url.JoinPath(m.cloud.Configuration.ActiveDirectoryAuthorityHost, tenant)
			if err != nil {
				return nil, fmt.Errorf("joining authority url: %w", err)
			}

			return oneauth.NewCredential(authority, azdClientID, oneauth.CredentialOptions{
				HomeAccountID: *currentUser.HomeAccountID,
				NoPrompt:      options.NoPrompt,
			})
		}

		accounts, err := m.publicClient.Accounts(ctx)
		if err != nil {
			return nil, err
		}
		for i, account := range accounts {
			if account.HomeAccountID == *currentUser.HomeAccountID {
				if options.TenantID == "" {
					return newAzdCredential(m.publicClient, &accounts[i], m.cloud), nil
				} else {
					newAuthority := m.cloud.Configuration.ActiveDirectoryAuthorityHost + options.TenantID

					newOptions := make([]public.Option, 0, len(m.publicClientOptions)+1)
					newOptions = append(newOptions, m.publicClientOptions...)

					// It is important that this option comes after the saved public client options since it will
					// override the default authority.
					newOptions = append(newOptions, public.WithAuthority(newAuthority))

					clientWithNewTenant, err := public.New(azdClientID, newOptions...)
					if err != nil {
						return nil, err
					}

					return newAzdCredential(
						&msalPublicClientAdapter{client: &clientWithNewTenant}, &accounts[i], m.cloud), nil
				}
			}
		}
	} else if currentUser.ManagedIdentity {
		clientID := ""
		if currentUser.ClientID != nil {
			clientID = *currentUser.ClientID
		}
		return m.newCredentialFromManagedIdentity(clientID)
	} else if currentUser.TenantID != nil && currentUser.ClientID != nil {
		// by default we used the stored tenant (i.e. the one provided with the tenant id parameter when a user ran
		// `azd auth login`), but we allow an override using the options bag, when
		// TenantID is non-empty and PreferFallbackTenant is not true.
		tenantID := *currentUser.TenantID

		if options.TenantID != "" {
			tenantID = options.TenantID
		}

		ps, err := m.loadSecret(*currentUser.TenantID, *currentUser.ClientID)
		if err != nil {
			return nil, fmt.Errorf("loading secret: %w: %w", err, ErrNoCurrentUser)
		}

		if ps.ClientSecret != nil {
			return m.newCredentialFromClientSecret(tenantID, *currentUser.ClientID, *ps.ClientSecret)
		} else if ps.ClientCertificate != nil {
			return m.newCredentialFromClientCertificate(tenantID, *currentUser.ClientID, *ps.ClientCertificate)
		} else if ps.FederatedAuth != nil && ps.FederatedAuth.TokenProvider != nil {
			return m.newCredentialFromFederatedTokenProvider(
				tenantID, *currentUser.ClientID, *ps.FederatedAuth.TokenProvider, ps.FederatedAuth.ServiceConnectionID)
		}
	}

	return nil, ErrNoCurrentUser
}