Aplica-se a:
Locatários da força de trabalho
Locatários externos (saiba mais)
Saiba como configurar o código para seu aplicativo daemon que chama APIs da Web.
Bibliotecas da Microsoft que suportam aplicativos daemon
As seguintes bibliotecas da Microsoft suportam aplicações daemon:
1Os Termos de Licença Universal para Serviços Online aplicam-se às bibliotecas em Pré-visualização Pública.
Os aplicativos Daemon usam permissões de aplicativo em vez de permissões delegadas. Portanto, o tipo de conta suportada não pode ser uma conta em nenhum diretório organizacional ou qualquer conta pessoal da Microsoft (por exemplo, Skype, Xbox, Outlook.com). Não há nenhum administrador de locatário para conceder consentimento a um aplicativo daemon para uma conta pessoal da Microsoft. Você precisa escolher contas na minha organização ou contas em qualquer organização.
A autoridade especificada na configuração do aplicativo deve incluir o ID do locatário ypur ou um nome de domínio associado à sua organização.
Mesmo que se deseje fornecer uma ferramenta multi-inquilino, deve-se usar um ID de inquilino ou nome de domínio, e nãocommon
ou organizations
neste fluxo, porque o serviço não pode inferir de forma confiável qual inquilino deve ser usado.
Nas Bibliotecas de Autenticação da Microsoft (MSAL), as credenciais do cliente (segredo ou certificado) são passadas como um parâmetro da construção confidencial do aplicativo cliente.
Importante
Mesmo que seu aplicativo seja um aplicativo de console executado como um serviço, se for um aplicativo daemon, ele precisará ser um aplicativo cliente confidencial.
Arquivo de configuração
O arquivo de configuração define:
- A instância de nuvem e o ID do locatário, que juntos compõem a autoridade.
- A ID do cliente que você obteve do registro do aplicativo.
- Um segredo do cliente ou um certificado.
Aqui está um exemplo de definição da configuração em um arquivo appsettings.json. Este exemplo é retirado do exemplo de código do daemon do console .NET no GitHub.
{
"AzureAd": {
"Instance": "https://login.microsoftonline.com/",
"TenantId": "[Enter here the tenantID or domain name for your Azure AD tenant]",
"ClientId": "[Enter here the ClientId for your application]",
"ClientCredentials": [
{
"SourceType": "ClientSecret",
"ClientSecret": "[Enter here a client secret for your application]"
}
]
}
}
Você fornece um certificado em vez do segredo do cliente ou das credenciais de federação de identidade de carga de trabalho.
private final static String CLIENT_ID = "";
private final static String AUTHORITY = "https://login.microsoftonline.com/<tenant>/";
private final static String CLIENT_SECRET = "";
private final static Set<String> SCOPE = Collections.singleton("https://graph.microsoft.com/.default");
Os parâmetros de configuração para o exemplo de daemon Node.js estão localizados em um arquivo .env :
# Credentials
TENANT_ID=Enter_the_Tenant_Info_Here
CLIENT_ID=Enter_the_Application_Id_Here
// You provide either a ClientSecret or a CertificateConfiguration, or a ClientAssertion. These settings are exclusive
CLIENT_SECRET=Enter_the_Client_Secret_Here
CERTIFICATE_THUMBPRINT=Enter_the_certificate_thumbprint_Here
CERTIFICATE_PRIVATE_KEY=Enter_the_certificate_private_key_Here
CLIENT_ASSERTION=Enter_the_Assertion_String_Here
# Endpoints
// the Azure AD endpoint is the authority endpoint for token issuance
AAD_ENDPOINT=Enter_the_Cloud_Instance_Id_Here // https://login.microsoftonline.com/
// the graph endpoint is the application ID URI of Microsoft Graph
GRAPH_ENDPOINT=Enter_the_Graph_Endpoint_Here // https://graph.microsoft.com/
Quando se cria um cliente confidencial com segredos de cliente, o arquivo de configuração parameters.json no exemplo de daemon Python é o seguinte:
{
"authority": "https://login.microsoftonline.com/<your_tenant_id>",
"client_id": "your_client_id",
"scope": [ "https://graph.microsoft.com/.default" ],
"secret": "The secret generated by Azure AD during your confidential app registration",
"endpoint": "https://graph.microsoft.com/v1.0/users"
}
Quando você cria um cliente confidencial com certificados, o arquivo de configuração parameters.json no exemplo de daemon Python é o seguinte:
{
"authority": "https://login.microsoftonline.com/<your_tenant_id>",
"client_id": "your_client_id",
"scope": [ "https://graph.microsoft.com/.default" ],
"thumbprint": "790E... The thumbprint generated by Azure AD when you upload your public cert",
"private_key_file": "server.pem",
"endpoint": "https://graph.microsoft.com/v1.0/users"
}
Aqui está um exemplo de definição da configuração em um arquivo appsettings.json. Este exemplo é retirado do exemplo de código do daemon do console .NET no GitHub.
{
"Instance": "https://login.microsoftonline.com/{0}",
"Tenant": "[Enter here the tenantID or domain name for your Azure AD tenant]",
"ClientId": "[Enter here the ClientId for your application]",
"ClientSecret": "[Enter here a client secret for your application]",
"CertificateName": "[Or instead of client secret: Enter here the name of a certificate (from the user cert store) as registered with your application]"
}
Você fornece um ClientSecret
ou um CertificateName
. Essas configurações são exclusivas.
Instanciar o aplicativo MSAL
Para instanciar o aplicativo MSAL, adicione, faça referência ou importe o pacote MSAL (dependendo do idioma).
A construção é diferente, dependendo se você está usando segredos de cliente ou certificados (ou, como um cenário avançado, asserções assinadas).
Referenciar o pacote
Faça referência ao pacote MSAL no código do aplicativo.
Adicione o pacote NuGet Microsoft.Identity.Web.TokenAcquisition à sua aplicação.
Como alternativa, se você quiser chamar o Microsoft Graph, adicione o pacote Microsoft.Identity.Web.GraphServiceClient .
O seu projeto pode ser o seguinte. O arquivo appsettings.json precisa ser copiado para o diretório de saída.
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net7.0</TargetFramework>
<RootNamespace>daemon_console</RootNamespace>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Identity.Web.GraphServiceClient" Version="2.12.2" />
</ItemGroup>
<ItemGroup>
<None Update="appsettings.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
</Project>
No arquivo Program.cs, adicione uma using
diretiva em seu código para fazer referência a Microsoft.Identity.Web.
using Microsoft.Identity.Abstractions;
using Microsoft.Identity.Web;
import com.microsoft.aad.msal4j.ClientCredentialFactory;
import com.microsoft.aad.msal4j.ClientCredentialParameters;
import com.microsoft.aad.msal4j.ConfidentialClientApplication;
import com.microsoft.aad.msal4j.IAuthenticationResult;
import com.microsoft.aad.msal4j.IClientCredential;
import com.microsoft.aad.msal4j.MsalException;
import com.microsoft.aad.msal4j.SilentParameters;
Instale os pacotes executando npm install
na pasta onde package.json
o arquivo reside. Em seguida, importe o msal-node
pacote:
const msal = require('@azure/msal-node');
import msal
import json
import sys
import logging
Adicione o pacote NuGet Microsoft.Identity.Client ao seu aplicativo e, em seguida, adicione uma using
diretiva em seu código para fazer referência a ele.
Em MSAL.NET, o aplicativo cliente confidencial é representado pela IConfidentialClientApplication
interface.
using Microsoft.Identity.Client;
IConfidentialClientApplication app;
Instanciar o aplicativo cliente confidencial com um segredo do cliente
Aqui está o código para instanciar o aplicativo cliente confidencial com um segredo do cliente:
class Program
{
static async Task Main(string[] _)
{
// Get the Token acquirer factory instance. By default it reads an appsettings.json
// file if it exists in the same folder as the app (make sure that the
// "Copy to Output Directory" property of the appsettings.json file is "Copy if newer").
TokenAcquirerFactory tokenAcquirerFactory = TokenAcquirerFactory.GetDefaultInstance();
// Configure the application options to be read from the configuration
// and add the services you need (Graph, token cache)
IServiceCollection services = tokenAcquirerFactory.Services;
services.AddMicrosoftGraph();
// By default, you get an in-memory token cache.
// For more token cache serialization options, see https://aka.ms/msal-net-token-cache-serialization
// Resolve the dependency injection.
var serviceProvider = tokenAcquirerFactory.Build();
// ...
}
}
A configuração é lida a partir do appsettings.json:
IClientCredential credential = ClientCredentialFactory.createFromSecret(CLIENT_SECRET);
ConfidentialClientApplication cca =
ConfidentialClientApplication
.builder(CLIENT_ID, credential)
.authority(AUTHORITY)
.build();
const msalConfig = {
auth: {
clientId: process.env.CLIENT_ID,
authority: process.env.AAD_ENDPOINT + process.env.TENANT_ID,
clientSecret: process.env.CLIENT_SECRET,
}
};
const apiConfig = {
uri: process.env.GRAPH_ENDPOINT + 'v1.0/users',
};
const tokenRequest = {
scopes: [process.env.GRAPH_ENDPOINT + '.default'],
};
const cca = new msal.ConfidentialClientApplication(msalConfig);
# Pass the parameters.json file as an argument to this Python script. E.g.: python your_py_file.py parameters.json
config = json.load(open(sys.argv[1]))
# Create a preferably long-lived app instance that maintains a token cache.
app = msal.ConfidentialClientApplication(
config["client_id"], authority=config["authority"],
client_credential=config["secret"],
# token_cache=... # Default cache is in memory only.
# You can learn how to use SerializableTokenCache from
# https://msal-python.rtfd.io/en/latest/#msal.SerializableTokenCache
)
app = ConfidentialClientApplicationBuilder.Create(config.ClientId)
.WithClientSecret(config.ClientSecret)
.WithAuthority(new Uri(config.Authority))
.Build();
O Authority
é uma concatenação da instância de nuvem e do ID do locatário, por exemplo https://login.microsoftonline.com/contoso.onmicrosoft.com
ou https://login.microsoftonline.com/aaaabbbb-0000-cccc-1111-dddd2222eeee
. No arquivo appsettings.json mostrado na seção Arquivo de configuração, a instância e o locatário são representados pelos valores Instance
e Tenant
, respectivamente.
No exemplo de código, o trecho anterior foi retirado, Authority
é uma propriedade na classe AuthenticationConfig e é definido como tal:
/// <summary>
/// URL of the authority
/// </summary>
public string Authority
{
get
{
return String.Format(CultureInfo.InvariantCulture, Instance, Tenant);
}
}
Instanciar o aplicativo cliente confidencial com um certificado de cliente
Aqui está o código para criar um aplicativo com um certificado:
O código em si é exatamente o mesmo. O certificado é descrito na configuração.
Há muitas maneiras de obter o certificado. Para mais pormenores, ver https://aka.ms/ms-id-web-certificates.
Veja como você faria para obter seu certificado do KeyVault. A identidade da Microsoft delega à DefaultAzureCredential da Identidade do Azure e, quando disponível, usa a identidade gerida para aceder ao certificado do Key Vault. Você pode depurar seu aplicativo localmente, pois ele usa suas credenciais de desenvolvedor.
"ClientCredentials": [
{
"SourceType": "KeyVault",
"KeyVaultUrl": "https://yourKeyVaultUrl.vault.azure.net",
"KeyVaultCertificateName": "NameOfYourCertificate"
}
No MSAL Java, há dois construtores para instanciar o aplicativo cliente confidencial com certificados:
InputStream pkcs12Certificate = ... ; /* Containing PCKS12-formatted certificate*/
string certificatePassword = ... ; /* Contains the password to access the certificate */
IClientCredential credential = ClientCredentialFactory.createFromCertificate(pkcs12Certificate, certificatePassword);
ConfidentialClientApplication cca =
ConfidentialClientApplication
.builder(CLIENT_ID, credential)
.authority(AUTHORITY)
.build();
ou
PrivateKey key = getPrivateKey(); /* RSA private key to sign the assertion */
X509Certificate publicCertificate = getPublicCertificate(); /* x509 public certificate used as a thumbprint */
IClientCredential credential = ClientCredentialFactory.createFromCertificate(key, publicCertificate);
ConfidentialClientApplication cca =
ConfidentialClientApplication
.builder(CLIENT_ID, credential)
.authority(AUTHORITY)
.build();
const config = {
auth: {
clientId: process.env.CLIENT_ID,
authority: process.env.AAD_ENDPOINT + process.env.TENANT_ID,
clientCertificate: {
thumbprint: process.env.CERTIFICATE_THUMBPRINT, // a 40-digit hexadecimal string
privateKey: process.env.CERTIFICATE_PRIVATE_KEY,
}
}
};
// Create an MSAL application object
const cca = new msal.ConfidentialClientApplication(config);
Para obter detalhes, consulte Usar as credenciais de certificado com o MSAL Node.
# Pass the parameters.json file as an argument to this Python script. E.g.: python your_py_file.py parameters.json
config = json.load(open(sys.argv[1]))
# Create a preferably long-lived app instance that maintains a token cache.
app = msal.ConfidentialClientApplication(
config["client_id"], authority=config["authority"],
client_credential={"thumbprint": config["thumbprint"], "private_key": open(config['private_key_file']).read()},
# token_cache=... # Default cache is in memory only.
# You can learn how to use SerializableTokenCache from
# https://msal-python.rtfd.io/en/latest/#msal.SerializableTokenCache
)
X509Certificate2 certificate = ReadCertificate(config.CertificateName);
app = ConfidentialClientApplicationBuilder.Create(config.ClientId)
.WithCertificate(certificate)
.WithAuthority(new Uri(config.Authority))
.Build();
Cenário avançado: Instanciar o aplicativo cliente confidencial com asserções de cliente
Além de usar um segredo ou certificado de cliente, os aplicativos cliente confidenciais também podem provar sua identidade usando asserções de cliente. Consulte CredentialDescription para obter detalhes.
IClientCredential credential = ClientCredentialFactory.createFromClientAssertion(assertion);
ConfidentialClientApplication cca =
ConfidentialClientApplication
.builder(CLIENT_ID, credential)
.authority(AUTHORITY)
.build();
const clientConfig = {
auth: {
clientId: process.env.CLIENT_ID,
authority: process.env.AAD_ENDPOINT + process.env.TENANT_ID,
clientAssertion: process.env.CLIENT_ASSERTION
}
};
const cca = new msal.ConfidentialClientApplication(clientConfig);
Para obter detalhes, consulte Inicializar o objeto ConfidentialClientApplication.
No MSAL Python, você pode fornecer declarações de cliente usando aquelas que serão assinadas pela chave privada de ConfidentialClientApplication
.
# Pass the parameters.json file as an argument to this Python script. E.g.: python your_py_file.py parameters.json
config = json.load(open(sys.argv[1]))
# Create a preferably long-lived app instance that maintains a token cache.
app = msal.ConfidentialClientApplication(
config["client_id"], authority=config["authority"],
client_credential={"thumbprint": config["thumbprint"], "private_key": open(config['private_key_file']).read()},
client_claims = {"client_ip": "x.x.x.x"}
# token_cache=... # Default cache is in memory only.
# You can learn how to use SerializableTokenCache from
# https://msal-python.rtfd.io/en/latest/#msal.SerializableTokenCache
)
Para obter detalhes, consulte a documentação de referência do MSAL Python para ConfidentialClientApplication.
Em vez de um segredo de cliente ou um certificado, o aplicativo cliente confidencial também pode provar sua identidade usando asserções de cliente.
MSAL.NET tem dois métodos para fornecer asserções assinadas para o aplicativo cliente confidencial:
.WithClientAssertion()
.WithClientClaims()
Ao usar WithClientAssertion
, forneça um JWT assinado. Este cenário avançado é detalhado em Asserções de cliente.
string signedClientAssertion = ComputeAssertion();
app = ConfidentialClientApplicationBuilder.Create(config.ClientId)
.WithClientAssertion(signedClientAssertion)
.Build();
Quando se utiliza WithClientClaims
, MSAL.NET produz uma asserção assinada que contém as declarações esperadas pelo Microsoft Entra ID, além de declarações de cliente adicionais que deseja enviar.
Este código mostra como fazer isso:
string ipAddress = "192.168.1.2";
var claims = new Dictionary<string, string> { { "client_ip", ipAddress } };
X509Certificate2 certificate = ReadCertificate(config.CertificateName);
app = ConfidentialClientApplicationBuilder.Create(config.ClientId)
.WithAuthority(new Uri(config.Authority))
.WithClientClaims(certificate, claims)
.Build();
Novamente, para obter detalhes, consulte Asserções de cliente.
Próximos passos