A ID Verificada do Microsoft Entra inclui a API REST do Serviço de Solicitação. Essa API permite emitir e verificar credenciais. Este artigo mostra como começar a usar a API REST de Serviço de Solicitação.
Token de acesso da API
Seu aplicativo precisa incluir um token de acesso válido com as permissões necessárias para poder acessar a API REST de Serviço da Solicitação. Os tokens de acesso emitidos pela plataforma de identidade da Microsoft contêm informações (escopos) que a API REST de Serviço de Solicitação usa para validar o chamador. Um token de acesso garante que o chamador tenha as permissões apropriadas para executar a operação que está solicitando.
Para obter um token de acesso, seu aplicativo deve ser registrado com a plataforma de identidade da Microsoft e ser autorizado por um administrador para acessar a API REST de Serviço de Solicitação. Se você ainda não registrou o aplicativo verifiable-credentials-app, confiracomo registrar o aplicativo, em seguida gere o segredo do aplicativo.
Obter um token de acesso
Use o fluxo de concessão de credenciais do cliente OAuth 2.0 para adquirir o token de acesso usando a plataforma de identidade da Microsoft. Use uma biblioteca confiável para essa finalidade. Neste tutorial, usamos a Biblioteca de Autenticação da Microsoft (MSAL). A MSAL simplifica a adição de autenticação e autorização a um aplicativo que pode chamar uma API Web segura.
POST /{tenant}/oauth2/v2.0/token HTTP/1.1 //Line breaks for clarity
Host: login.microsoftonline.com
Content-Type: application/x-www-form-urlencoded
client_id=00001111-aaaa-2222-bbbb-3333cccc4444
&scope=3db474b9-6a0c-4840-96ac-1fceb342124f/.default
&client_secret=sampleCredentia1s
&grant_type=client_credentials
// Initialize MSAL library by using the following code
ConfidentialClientApplicationBuilder.Create(AppSettings.ClientId)
.WithClientSecret(AppSettings.ClientSecret)
.WithAuthority(new Uri(AppSettings.Authority))
.Build();
// Acquire an access token
result = await app.AcquireTokenForClient(AppSettings.Scopes)
.ExecuteAsync();
// Initialize MSAL library by using the following code
const msalConfig = {
auth: {
clientId: config.azClientId,
authority: `https://login.microsoftonline.com/${config.azTenantId}`,
clientSecret: config.azClientSecret,
},
system: {
loggerOptions: {
loggerCallback(loglevel, message, containsPii) {
console.log(message);
},
piiLoggingEnabled: false,
logLevel: msal.LogLevel.Verbose,
}
}
};
const cca = new msal.ConfidentialClientApplication(msalConfig);
const msalClientCredentialRequest = {
scopes: ["3db474b9-6a0c-4840-96ac-1fceb342124f/.default"],
skipCache: false,
};
module.exports.msalCca = cca;
module.exports.msalClientCredentialRequest = msalClientCredentialRequest;
// Acquire an access token
const result = await mainApp.msalCca.acquireTokenByClientCredential(mainApp.msalClientCredentialRequest);
if ( result ) {
accessToken = result.accessToken;
}
# Initialize MSAL library by using the following code
msalCca = msal.ConfidentialClientApplication( config["azClientId"],
authority="https://login.microsoftonline.com/" + config["azTenantId"],
client_credential=config["azClientSecret"],
)
# Acquire an access token
accessToken = ""
result = msalCca.acquire_token_for_client( scopes="3db474b9-6a0c-4840-96ac-1fceb342124f/.default" )
if "access_token" in result:
accessToken = result['access_token']
// Initialize MSAL library by using the following code
ConfidentialClientApplication app = ConfidentialClientApplication.builder(
clientId,
ClientCredentialFactory.createFromSecret(clientSecret))
.authority(authority)
.build();
// Acquire an access token
ClientCredentialParameters clientCredentialParam = ClientCredentialParameters.builder(
Collections.singleton(scope))
.build();
CompletableFuture<IAuthenticationResult> future = app.acquireToken(clientCredentialParam);
IAuthenticationResult result = future.get();
return result.accessToken();
No código anterior, forneça os seguintes parâmetros:
Parâmetro
Condição
Descrição
Authority
Obrigatório
O locatário do diretório no qual o aplicativo planeja operar. Por exemplo: https://login.microsoftonline.com/{your-tenant}. (Substitua your-tenant pela ID de Locatário ou nome.)
ID do Cliente
Obrigatório
A ID do aplicativo atribuído ao aplicativo. É possível encontrar essas informações no portal do Azure, onde você registrou seu aplicativo.
Segredo do cliente
Obrigatório
O segredo do cliente gerado para seu aplicativo.
Escopos
Obrigatório
Deve ser definido como 3db474b9-6a0c-4840-96ac-1fceb342124f/.default. Essa configuração produz um token de acesso com uma declaração de funções de VerifiableCredential.Create.All.
Para obter mais informações sobre como obter um token de acesso usando a identidade de um aplicativo de console, consulte um dos seguintes artigos:
POST /{tenant}/oauth2/v2.0/token HTTP/1.1 //Line breaks for clarity
Host: login.microsoftonline.com
Content-Type: application/x-www-form-urlencoded
client_id=00001111-aaaa-2222-bbbb-3333cccc4444
&scope=3db474b9-6a0c-4840-96ac-1fceb342124f/.default
&client_assertion_type=urn%3Aietf%3Aparams%3Aoauth%3Aclient-assertion-type%3Ajwt-bearer
&client_assertion=eyJhbGciOiJSUzI1NiIsIng1dCI6Imd4OHRHeXN5amNScUtqRlBuZDdSRnd2d1pJMCJ9.eyJ{a lot of characters here}M8U3bSUKKJDEg
&grant_type=client_credentials
// Initialize MSAL library by using the following code
X509Certificate2 certificate = AppSettings.ReadCertificate(AppSettings.CertificateName);
app = ConfidentialClientApplicationBuilder.Create(AppSettings.ClientId)
.WithCertificate(certificate)
.WithAuthority(new Uri(AppSettings.Authority))
.Build();
// Acquire an access token
result = await app.AcquireTokenForClient(AppSettings.Scopes)
.ExecuteAsync();
// Initialize MSAL library by using the following code
const msalConfig = {
auth: {
clientId: config.azClientId,
authority: `https://login.microsoftonline.com/${config.azTenantId}`,
clientCertificate: {
thumbprint: "CERT_THUMBPRINT", // a 40-digit hexadecimal string
privateKey: "CERT_PRIVATE_KEY"
}
},
system: {
loggerOptions: {
loggerCallback(loglevel, message, containsPii) {
console.log(message);
},
piiLoggingEnabled: false,
logLevel: msal.LogLevel.Verbose,
}
}
};
const cca = new msal.ConfidentialClientApplication(msalConfig);
const msalClientCredentialRequest = {
scopes: ["3db474b9-6a0c-4840-96ac-1fceb342124f/.default"],
skipCache: false,
};
module.exports.msalCca = cca;
module.exports.msalClientCredentialRequest = msalClientCredentialRequest;
// Acquire an access token
const result = await mainApp.msalCca.acquireTokenByClientCredential(mainApp.msalClientCredentialRequest);
if ( result ) {
accessToken = result.accessToken;
}
# Initialize MSAL library by using the following code
with open(config["azCertificatePrivateKeyLocation"], "rb") as file:
private_key = file.read()
with open(config["azCertificateLocation"]) as file:
public_certificate = file.read()
cert = load_pem_x509_certificate(data=bytes(public_certificate, 'UTF-8'), backend=default_backend())
thumbprint = (cert.fingerprint(hashes.SHA1()).hex())
msalCca = msal.ConfidentialClientApplication( config["azClientId"],
authority="https://login.microsoftonline.com/" + config["azTenantId"],
client_credential={
"private_key": private_key,
"thumbprint": thumbprint,
"public_certificate": public_certificate
}
)
# Acquire an access token
accessToken = ""
result = msalCca.acquire_token_for_client( scopes="3db474b9-6a0c-4840-96ac-1fceb342124f/.default" )
if "access_token" in result:
accessToken = result['access_token']
// Initialize MSAL library by using the following code
PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(Files.readAllBytes(Paths.get(certKeyLocation)));
PrivateKey key = KeyFactory.getInstance("RSA").generatePrivate(spec);
java.io.InputStream certStream = (java.io.InputStream)new ByteArrayInputStream(Files.readAllBytes(Paths.get(certLocation)));
X509Certificate cert = (X509Certificate) CertificateFactory.getInstance("X.509").generateCertificate(certStream);
ConfidentialClientApplication app = ConfidentialClientApplication.builder(
clientId,
ClientCredentialFactory.createFromCertificate(key, cert))
.authority(authority)
.build();
// Acquire an access token
ClientCredentialParameters clientCredentialParam = ClientCredentialParameters.builder(
Collections.singleton(scope))
.build();
CompletableFuture<IAuthenticationResult> future = app.acquireToken(clientCredentialParam);
IAuthenticationResult result = future.get();
return result.accessToken();
Chamar a API
Para emitir ou verificar uma credencial verificável:
Construa uma solicitação HTTP POST para a API REST de Serviço de Solicitação. A ID de locatário não é mais necessária na URL porque está presente como uma declaração no token de acesso.
Problema
POST https://verifiedid.did.msidentity.com/v1.0/verifiableCredentials/createIssuanceRequest
Verificar
POST https://verifiedid.did.msidentity.com/v1.0/verifiableCredentials/createPresentationRequest
Anexe o token de acesso como um token de portador ao cabeçalho de autorização em uma solicitação HTTP.
Authorization: Bearer <token>
Defina o cabeçalho Content-Type como Application/json.
Prepare e anexe o conteúdo de solicitação emissão ou presentação ao corpo da solicitação.
Envie a solicitação para a API REST de Serviço de Solicitação.
A API de Serviço de Solicitação retorna um Código de Status HTTP 201 Created em uma chamada bem-sucedida. Se a chamada à API retornar um erro, verifique a documentação de referência de erro.
O conteúdo da solicitação contém os pontos de extremidade do retorno de chamada emissão e apresentação. O ponto de extremidade faz parte do aplicativo Web e deve estar disponível publicamente por meio do protocolo HTTPS. A API de Serviço de Solicitação chama o ponto de extremidade para informar determinados eventos ao aplicativo. Por exemplo, tais eventos podem ocorrer quando um usuário verifica o código QR, usa o link profundo para o aplicativo autenticador ou termina o processo de apresentação.
O diagrama a seguir descreve a chamada que seu aplicativo faz para a API REST de Serviço de Solicitação e os retornos de chamada para seu aplicativo.
Configure seu ponto de extremidade para atender as solicitações HTTP POST de entrada. O trecho de código a seguir demonstra como tratar a solicitação HTTP de retorno de chamada de emissão e atualizar a interface do usuário em conformidade:
Não aplicável. Escolha uma das outras linguagens de programação.
[HttpPost]
public async Task<ActionResult> IssuanceCallback()
{
try
{
string content = new System.IO.StreamReader(this.Request.Body).ReadToEndAsync().Result;
_log.LogTrace("callback!: " + content);
JObject issuanceResponse = JObject.Parse(content);
// More code here
if (issuanceResponse["code"].ToString() == "request_retrieved")
{
var cacheData = new
{
status = "request_retrieved",
message = "QR Code is scanned. Waiting for issuance...",
};
_cache.Set(state, JsonConvert.SerializeObject(cacheData));
// More code here
}
}
Para ver o código completo, consulte o código de emissão e apresentação no repositório GitHub.
mainApp.app.post('/api/issuer/issuance-request-callback', parser, async (req, res) => {
var body = '';
req.on('data', function (data) {
body += data;
});
req.on('end', function () {
requestTrace( req );
console.log( body );
var issuanceResponse = JSON.parse(body.toString());
var message = null;
if ( issuanceResponse.code == "request_retrieved" ) {
message = "QR Code is scanned. Waiting for issuance to complete...";
}
if ( issuanceResponse.code == "issuance_successful" ) {
message = "Credential successfully issued";
}
if ( issuanceResponse.code == "issuance_error" ) {
message = issuanceResponse.error.message;
}
// More code here
res.send()
});
res.send()
})