in cli/azd/cmd/auth_login.go [441:586]
func (la *loginAction) login(ctx context.Context) error {
if la.flags.federatedTokenProvider == azurePipelinesProvider {
if la.flags.clientID == "" {
log.Printf("setting client id from environment variable %s", azurePipelinesClientIDEnvVarName)
la.flags.clientID = os.Getenv(azurePipelinesClientIDEnvVarName)
}
if la.flags.tenantID == "" {
log.Printf("setting tenant id from environment variable %s", azurePipelinesClientIDEnvVarName)
la.flags.tenantID = os.Getenv(azurePipelinesTenantIDEnvVarName)
}
}
if la.flags.managedIdentity {
if _, err := la.authManager.LoginWithManagedIdentity(
ctx, la.flags.clientID,
); err != nil {
return fmt.Errorf("logging in: %w", err)
}
return nil
}
if !la.flags.managedIdentity && la.flags.clientID != "" {
if la.flags.tenantID == "" {
return errors.New("must set both `client-id` and `tenant-id` for service principal login")
}
if countTrue(
la.flags.clientSecret.ptr != nil,
la.flags.clientCertificate != "",
la.flags.federatedTokenProvider != "",
) != 1 {
return fmt.Errorf(
"must set exactly one of %s for service principal", strings.Join([]string{
cClientSecretFlagName,
cClientCertificateFlagName,
cFederatedCredentialProviderFlagName,
}, ", "))
}
switch {
case la.flags.clientSecret.ptr != nil:
if *la.flags.clientSecret.ptr == "" {
v, err := la.console.Prompt(ctx, input.ConsoleOptions{
Message: "Enter your client secret",
})
if err != nil {
return fmt.Errorf("prompting for client secret: %w", err)
}
la.flags.clientSecret.ptr = &v
}
if _, err := la.authManager.LoginWithServicePrincipalSecret(
ctx, la.flags.tenantID, la.flags.clientID, *la.flags.clientSecret.ptr,
); err != nil {
return fmt.Errorf("logging in: %w", err)
}
case la.flags.clientCertificate != "":
certFile, err := os.Open(la.flags.clientCertificate)
if err != nil {
return fmt.Errorf("reading certificate: %w", err)
}
defer certFile.Close()
cert, err := io.ReadAll(certFile)
if err != nil {
return fmt.Errorf("reading certificate: %w", err)
}
if _, err := la.authManager.LoginWithServicePrincipalCertificate(
ctx, la.flags.tenantID, la.flags.clientID, cert,
); err != nil {
return fmt.Errorf("logging in: %w", err)
}
case la.flags.federatedTokenProvider == "github":
if _, err := la.authManager.LoginWithGitHubFederatedTokenProvider(
ctx, la.flags.tenantID, la.flags.clientID,
); err != nil {
return fmt.Errorf("logging in: %w", err)
}
case la.flags.federatedTokenProvider == azurePipelinesProvider:
serviceConnectionID := os.Getenv(azurePipelinesServiceConnectionIDEnvVarName)
if serviceConnectionID == "" {
return fmt.Errorf("must set %s for azure-pipelines federated token provider",
azurePipelinesServiceConnectionIDEnvVarName)
}
if _, err := la.authManager.LoginWithAzurePipelinesFederatedTokenProvider(
ctx, la.flags.tenantID, la.flags.clientID, serviceConnectionID,
); err != nil {
return fmt.Errorf("logging in: %w", err)
}
}
return nil
}
if la.authManager.UseExternalAuth() {
// Request a token and assume the external auth system will prompt the user to log in.
//
// TODO(ellismg): We may want instead to call some explicit `/login` endpoint on the external auth system instead
// of abusing the token request in this manner. This would allow the other end to provide a more tailored experience.
_, err := la.verifyLoggedIn(ctx)
return err
}
useDevCode, err := parseUseDeviceCode(ctx, la.flags.useDeviceCode, la.commandRunner)
if err != nil {
return err
}
if useDevCode {
_, err = la.authManager.LoginWithDeviceCode(ctx, la.flags.tenantID, la.flags.scopes, func(url string) error {
if !la.flags.global.NoPrompt {
la.console.Message(ctx, "Then press enter and continue to log in from your browser...")
la.console.WaitForEnter()
openWithDefaultBrowser(ctx, la.console, url)
return nil
}
// For no-prompt, Just provide instructions without trying to open the browser
// If manual browsing is enabled, we don't want to open the browser automatically
la.console.Message(ctx, fmt.Sprintf("Then, go to: %s", url))
return nil
})
return err
}
if oneauth.Supported && !la.flags.browser {
err = la.authManager.LoginWithOneAuth(ctx, la.flags.tenantID, la.flags.scopes)
} else {
_, err = la.authManager.LoginInteractive(ctx, la.flags.scopes,
&auth.LoginInteractiveOptions{
TenantID: la.flags.tenantID,
RedirectPort: la.flags.redirectPort,
WithOpenUrl: func(url string) error {
openWithDefaultBrowser(ctx, la.console, url)
return nil
},
})
}
if err != nil {
err = fmt.Errorf("logging in: %w", err)
}
return err
}