Llamar a la API de REST del servicio de solicitudes
Artículo
Verified ID de Microsoft Entra incluye la API REST del servicio de solicitudes. Esta API le permite emitir y comprobar credenciales. En este artículo se muestra cómo empezar a usar la API de REST del servicio de solicitudes.
Token de acceso a la API
La aplicación necesita incluir un token de acceso válido con los permisos necesarios para que pueda acceder a la API de REST del servicio de solicitud. Los tokens de acceso emitidos por la Plataforma de identidad de Microsoft contienen información (ámbitos) que la API de REST del servicio de solicitudes usa para validar al autor de la llamada. Un token de acceso garantiza que el autor de llamada tenga los permisos adecuados para realizar la operación que solicita.
Para obtener un token de acceso, la aplicación debe estar registrada en Plataforma de identidad de Microsoft y tener la autorización de un administrador para acceder a la API de REST de solicitud de servicio. Si no ha registrado la aplicación verifiable-credentials-app, vea cómo registrar la aplicación y luego genere un secreto de aplicación.
Obtención de un token de acceso
Use el flujo de concesión de credenciales de cliente de OAuth 2.0 para adquirir el token de acceso mediante Plataforma de identidad de Microsoft. Use una biblioteca de confianza para este fin. En este tutorial, usamos la biblioteca de autenticación de Microsoft (MSAL). MSAL simplifica la incorporación de autenticación y autorización a una aplicación que puede llamar a una 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();
En el código anterior, proporcione los parámetros siguientes:
Parámetro
Condition
Descripción
Autoridad
Requerido
Inquilino del directorio en el que la aplicación tiene previsto funcionar. Por ejemplo: https://login.microsoftonline.com/{your-tenant}. (Remplace your-tenant por el identificador o nombre de inquilino).
Id. de cliente
Obligatorio
El identificador de la aplicación que está asignado a la aplicación. Puede encontrar esta información en Azure Portal, donde ha registrado la aplicación.
Secreto del cliente
Requerido
Secreto de cliente que ha generado para la aplicación.
Ámbitos
Obligatorio
Se debe establecer en 3db474b9-6a0c-4840-96ac-1fceb342124f/.default. Esto generará un token de acceso con una notificación roles con el valor VerifiableCredential.Create.All.
Para obtener más información sobre cómo obtener un token de acceso mediante la identidad de una aplicación de consola, vea alguno de los artículos siguientes:
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();
Llamada a la API
Emitir o verificar una credencial verificable:
Cree una solicitud HTTP POST para la API de REST del servicio de solicitudes. El ID del inquilino ya no es necesario en la URL porque está presente como reclamo en el token de acceso.
Problema
POST https://verifiedid.did.msidentity.com/v1.0/verifiableCredentials/createIssuanceRequest
Verify
POST https://verifiedid.did.msidentity.com/v1.0/verifiableCredentials/createPresentationRequest
Adjunte el token de acceso como token de portador al encabezado de autorización de una solicitud HTTP.
Authorization: Bearer <token>
Establezca el encabezado Content-Type en Application/json.
Prepare y adjunte la carga de la solicitud de emisión o presentación al cuerpo de la solicitud.
Envíe la solicitud a la API de REST del servicio de solicitudes.
La API del servicio de solicitudes devuelve un código de estado HTTP 201 Created en una llamada correcta. Si la llamada API devuelve un error, consulte la documentación de referencia de errores.
La carga de la solicitud contiene el punto de conexión de devolución de llamada de emisión y de presentación. El punto de conexión forma parte de la aplicación web y debe estar disponible públicamente mediante el protocolo HTTPS. La API del servicio de solicitudes llama al punto de conexión para informar a la aplicación de determinados eventos. Por ejemplo, estos eventos pueden ser que un usuario digitalice el código QR, use el vínculo profundo de la aplicación de autenticación o finalice el proceso de presentación.
En el siguiente diagrama se describen la llamada que realiza su aplicación a la API de REST del servicio de solicitudes y las devoluciones de llamada a la aplicación.
Configure el punto de conexión para escuchar las solicitudes HTTP POST entrantes. En el siguiente fragmento de código se muestra cómo controlar la solicitud HTTP de devolución de llamada de emisión y cómo actualizar la interfaz de usuario en consecuencia:
No aplicable. Elija alguno de los demás lenguajes de programación.
[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 obtener el código completo, consulte el código de emisión y de presentación en el repositorio 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()
})