in src/cli/commands/login/login.ts [51:106]
async function setupProjectCredentials(options: SWACLIConfig, credentialChain: TokenCredential) {
let { subscriptionId, tenantId, clientId, clientSecret } = options;
// If the user has not specified a tenantId, we will prompt them to choose one
if (!tenantId) {
const tenants = await listTenants(credentialChain);
if (tenants.length === 0) {
throw new Error(
`No Azure tenants found in your account.\n Please read https://docs.microsoft.com/azure/cost-management-billing/manage/troubleshoot-sign-in-issue`,
);
} else if (tenants.length === 1) {
logger.silly(`Found 1 tenant: ${tenants[0].tenantId}`);
tenantId = tenants[0].tenantId;
} else {
const tenant = await chooseTenant(tenants, options.tenantId);
tenantId = tenant?.tenantId;
// login again with the new tenant
// TODO: can we silently authenticate the user with the new tenant?
credentialChain = await authenticateWithAzureIdentity({ tenantId, clientId, clientSecret }, options.useKeychain, true);
if (await credentialChain.getToken(defaultScope)) {
logger.log(chalk.green(`✔ Successfully logged into Azure tenant: ${tenantId}`));
}
}
}
logger.silly(`Selected tenant: ${tenantId}`);
// If the user has not specified a subscriptionId, we will prompt them to choose one
if (!subscriptionId) {
const subscriptions = await listSubscriptions(credentialChain);
if (subscriptions.length === 0) {
throw new Error(
`No valid subscription found for tenant ${tenantId}.\n Please read https://docs.microsoft.com/azure/cost-management-billing/manage/no-subscriptions-found`,
);
} else if (subscriptions.length === 1) {
logger.silly(`Found 1 subscription: ${subscriptions[0].subscriptionId}`);
subscriptionId = subscriptions[0].subscriptionId;
} else {
const subscription = await chooseSubscription(subscriptions, subscriptionId);
subscriptionId = subscription?.subscriptionId;
}
}
logger.silly(`Selected subscription: ${subscriptionId}`);
logger.silly(`Project credentials:`);
logger.silly({ subscriptionId, tenantId, clientId, clientSecret });
await storeProjectCredentialsInEnvFile(subscriptionId, tenantId, clientId, clientSecret);
return {
credentialChain,
subscriptionId: subscriptionId as string,
};
}