Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
Os métodos addKey e removeKey definidos nos recursos application e servicePrincipal permitem que você role chaves expiradas programaticamente.
Como parte da validação de solicitação para esses métodos, uma PoP (prova de posse) de uma chave existente é verificada antes que os métodos possam ser invocados. A prova usa um JSON Web Token (JWT) autoassinado. Esse token deve ser assinado usando a chave privada de um dos certificados válidos existentes do aplicativo. A vida útil recomendada do token é de 10 minutos.
Este artigo inclui exemplos de código C# para demonstrar como:
- Calcule a declaração do cliente usando um certificado válido existente.
- Gere o token PoP usando a chave de asserção do cliente gerada.
- Use o token PoP para carregar um novo certificado para o objeto de aplicativo ou entidade de serviço usando o método addKey .
- Use o token PoP para remover um certificado do aplicativo ou objeto principal de serviço usando o método removeKey .
Importante
Aplicativos sem certificados válidos existentes, seja porque nenhum foi adicionado ou porque os existentes expiraram, não podem usar esta ação de serviço. Em vez disso, use a operação do aplicativo Update para atualizar keyCredentials. Para obter mais informações, consulte Adicionar um certificado a um aplicativo usando o Microsoft Graph.
Pré-requisitos
- Ter um certificado de cliente válido no aplicativo de destino ou na entidade de serviço.
- Você precisa dos detalhes de um certificado existente válido para gerar a chave de asserção do cliente e o token PoP.
- Para fins de teste, você pode usar um certificado autoassinado. Para saber como criar um certificado autoassinado, consulte Criar um certificado público autoassinado para autenticar seu aplicativo.
- Exporte o certificado com sua chave privada no
.pfxformato. Como alternativa, atualize o script para exigir apenas o certificado público sem a chave privada.
- Você precisa dos detalhes de um certificado existente válido para gerar a chave de asserção do cliente e o token PoP.
- A ID do cliente (chamada appId na API) e a ID do objeto (chamada de id na API) do aplicativo ou entidade de serviço para a qual você gera o token PoP.
Código de exemplo
O token contém as seguintes declarações:
-
aud: A audiência precisa ser
00000002-0000-0000-c000-000000000000. - iss: Issuer deve ser a ID do aplicativo ou objeto servicePrincipal que inicia a solicitação.
- nbf: Não antes do tempo.
- exp: O tempo de expiração deve ser o valor de nbf + 10 minutos.
using System;
using System.Security.Cryptography.X509Certificates;
using System.Net;
using System.Net.Http;
using Microsoft.IdentityModel.Tokens;
namespace SampleCertCall
{
class Program
{
static void Main(string[] args)
{
//=============================
// Global variables used to store app registration info. You can use appsettings.json to store this data.
//=============================
string clientId = "Enter_the_Application_Id_Here"; // Client ID or app ID of the target app or service principal
string tenantID = "Enter_the_Tenant_Id_Here"; // Tenant ID value
string scopes = "https://graph.microsoft.com/.default"; // The "https://graph.microsoft.com/.default" is required in the client credentials flow, see the consent documentation (https://learn.microsoft.com/en-us/entra/identity-platform/scopes-oidc#the-default-scope)
string objectId = "Enter_the_Object_Id_Here"; // The object ID is the identifier of the app or service principal you want to work with. Depending on the endpoint you use, it can be either the application objectId (https://graph.microsoft.com/v1.0/applications)) or the service principal objectId (https://graph.microsoft.com/v1.0/ServicePrincipals)).
string api = "Graph_API/ENDPOINT"; // Choose the graph endpoint you need to use, depending on whether you are working with (https://graph.microsoft.com/v1.0/applications) or (https://graph.microsoft.com/v1.0/servicePrincipals)
string aud_POP = "00000002-0000-0000-c000-000000000000"; // audience for client assertion must always be 00000002-0000-0000-c000-000000000000
string aud_ClientAssertion = "https://login.microsoftonline.com/{YOUR_TENANT_ID_HERE}/v2.0"; // audience for PoP must always be in the format https://login.microsoftonline.com/{YOUR_TENANT_ID_HERE}/v2.0
// pfxFilePath -> Use an existing valid cert used/uploaded to the app or service principal to generate access token and PoP token.
string pfxFilePath = "Current_Active_Certificate_Path"; // Replace the file path with the location of your certificate.
string password = "Current_Active_Certificate_Password"; // If applicable, replace the password value with your certificate password.
X509Certificate2 signingCert = null;
try
{
if (!string.IsNullOrEmpty(password))
signingCert = new X509Certificate2(pfxFilePath, password);
else
signingCert = new X509Certificate2(pfxFilePath);
}
catch (System.Security.Cryptography.CryptographicException ex)
{
Console.WriteLine("Check the old or uploaded certificate {CertificateDiskPath}. Add the correct certificate path or password for this sample to work.\n" + ex.Message);
Environment.Exit(-1);
}
// newCerFilePath -> This is the new cert which will be uploaded. The cert can also be stored in Azure Key Vault.
string newCerFilePath = "New_Certificate_Path"; // Replace the file path with the location of your new certificate to be uploaded using the Graph API.
string newCertPassword = "New_Certificate_Password"; // If applicable, replace the password value with your new certificate password.
X509Certificate2 newCert = null;
try
{
if (newCertPassword != "")
newCert = new X509Certificate2(newCerFilePath, newCertPassword);
else
newCert = new X509Certificate2(newCerFilePath);
}
catch (System.Security.Cryptography.CryptographicException ex)
{
Console.WriteLine("Check the new certificate {NewCertificateDiskPath}, you need to add a correct certificate path and/or password for this sample to work\n" + ex.Message);
Environment.Exit(-1);
}
//========================
//Get acessToken via client assertion
//========================
var client_assertion = Helper.GenerateClientAssertion(aud_ClientAssertion, clientId, signingCert);
var token = Helper.GenerateAccessTokenWithClientAssertion(client_assertion, clientId, tenantID);
//========================
//Get PoP Token
//========================
var poP = Helper.GeneratePoPToken(objectId, aud_POP, signingCert);
// Get the new certificate info which will be uploaded via Microsoft Graph API call
var key = Helper.GetCertificateKey(newCert);
var graphClient = Helper.GetGraphClient(scopes, tenantID, clientId, signingCert);
int choice = -1;
while (choice != 0)
{
Console.WriteLine("\n=================================================");
Console.WriteLine("Choose one of the following options:");
Console.WriteLine("=================================================");
Console.WriteLine("0. Exit");
Console.WriteLine("1. Display access token");
Console.WriteLine("2. Display client assertion");
Console.WriteLine("3. Display PoP token");
Console.WriteLine("4. Display certificate Info");
Console.WriteLine("5. Upload certificate using Graph SDK");
Console.WriteLine("6. Upload certificate using Graph API");
Console.WriteLine("7. Delete certificate using Graph SDK");
Console.WriteLine("8. Delete certificate using Graph API");
Console.WriteLine("\nEnter the choose number here:");
choice = Int32.TryParse(Console.ReadLine(), out choice) ? choice : -1;
HttpStatusCode code;
KeyCredential response;
string certID;
Guid val;
// Process user choice
switch (choice)
{
case 0:
// Exit the program
Console.WriteLine("\nGoodbye...\n");
break;
case 1:
// Display access token
Console.WriteLine("\n\"Access Token Value is:\"\n__________________");
Console.WriteLine($"Access Token: {token}");
Console.WriteLine("__________________\n");
break;
case 2:
// Display client assertion
Console.WriteLine("\n\"Client Assertion Token Value is\"\n__________________");
Console.WriteLine($"client_assertion: {client_assertion}");
Console.WriteLine("__________________\n");
break;
case 3:
// Display client assertion
Console.WriteLine("\n\"Proof of Possession Token Value is\"\n__________________");
Console.WriteLine($"PoP token: {poP}");
Console.WriteLine("__________________\n");
break;
case 4:
// Display certificate key
Helper.DisplayCertificateInfo(newCert);
break;
case 5:
// Call the addKey SDK using Graph SDK
if (newCertPassword != "")
{
response = GraphSDK.AddKeyWithPassword_GraphSDKAsync(poP, objectId, key, newCertPassword, graphClient).GetAwaiter().GetResult();
}
else
{
response = GraphSDK.AddKey_GraphSDKAsync(poP, objectId, key, graphClient).GetAwaiter().GetResult();
}
if (response != null)
{
Console.WriteLine("\n______________________");
Console.WriteLine("Uploaded Successfully!");
Console.WriteLine("______________________\n");
}
else
{
Console.WriteLine("\n______________________");
Console.WriteLine("An error occurred.");
Console.WriteLine("______________________\n");
}
break;
case 6:
// Call the addKey API directly without using SDK
if (!password.IsNullOrEmpty())
{
code = GraphAPI.AddKeyWithPassword(poP, objectId, api, token, key, newCertPassword);
}
else
{
code = GraphAPI.AddKey(poP, objectId, api, token, key);
}
if (code == HttpStatusCode.OK)
{
Console.WriteLine("\n______________________");
Console.WriteLine("Uploaded Successfully!");
Console.WriteLine("______________________\n");
}
else
{
Console.WriteLine("\n______________________");
Console.WriteLine("Something went wrong!");
Console.WriteLine("HTTP Status code is " + code);
Console.WriteLine("______________________\n");
}
break;
case 7:
// Call the removeKey API using Graph SDK
Console.WriteLine("\nEnter certificate ID that you want to delete:");
certID = Console.ReadLine();
if (Guid.TryParse(certID, out val))
{
var res = GraphSDK.RemoveKey_GraphSDKAsync(poP, objectId, certID, graphClient).GetAwaiter().GetResult();
if (res)
{
Console.WriteLine("\n______________________");
Console.WriteLine("Cert Deleted Successfully!");
Console.WriteLine("_____________________\n");
}
else
{
Console.WriteLine("\n______________________");
Console.WriteLine("Something Went Wrong!");
Console.WriteLine("ERROR: Unable to delete certificate");
Console.WriteLine("______________________\n");
}
}
else
{
Console.WriteLine("\n______________________");
Console.WriteLine("Error: Invalid certificate ID.");
Console.WriteLine("______________________\n");
}
break;
case 8:
// Call the removeKey API directly without using API
Console.WriteLine("\nEnter certificate ID that you want to delete:");
certID = Console.ReadLine();
try
{
if (Guid.TryParse(certID, out val))
{
code = GraphAPI.RemoveKey(poP, objectId, api, certID, token);
if (code == HttpStatusCode.NoContent)
{
Console.WriteLine("\n______________________");
Console.WriteLine("Cert Deleted Successfully!");
Console.WriteLine("______________________\n");
}
else
{
Console.WriteLine("\n______________________");
Console.WriteLine("Something went wrong!");
Console.WriteLine("HTTP Status code is " + code);
Console.WriteLine("______________________\n");
}
}
else
{
Console.WriteLine("\n------------------------------");
Console.WriteLine("ERROR: Invalid Certificate ID");
Console.WriteLine("______________________________\n");
}
}
catch (HttpRequestException ex)
{
Console.WriteLine(ex.InnerException.Message);
Console.WriteLine("\n______________________");
Console.WriteLine("ERROR: " + ex.Message);
Console.WriteLine("______________________\n");
}
break;
default:
Console.WriteLine("\n______________________");
Console.WriteLine("Invalid choice");
Console.WriteLine("______________________\n");
break;
}
}
}
}
}
Você também pode gerar a prova usando a assinatura no Azure KeyVault. É importante observar que o caractere de preenchimento '=' não deve ser incluído no cabeçalho JWT e no conteúdo ou um erro Authentication_MissingOrMalformed é retornado.
Conteúdo relacionado
Agora que você tem seu token PoP, use-o para:
- Adicione ouremova uma chave do aplicativo.
- Adicione uma chave ou remova uma chave da entidade de serviço.
Saiba mais sobre as declarações do cliente na autenticação do aplicativo da plataforma de identidade da Microsoft, credenciais de certificado.