Microsoft Entra Verified ID는 요청 서비스 REST API를 포함합니다. 이 API를 사용하면 자격 증명을 발급하고 확인할 수 있습니다. 이 문서에서는 요청 서비스 REST API를 사용하는 방법을 보여 줍니다.
API 액세스 토큰
애플리케이션은 요청 서비스 REST API에 액세스할 수 있도록 필요한 권한이 있는 유효한 액세스 토큰을 포함해야 합니다. Microsoft ID 플랫폼에서 발급한 액세스 토큰에는 요청 서비스 REST API에서 호출자의 유효성을 검사하는 데 사용하는 정보(범위)가 포함됩니다. 액세스 토큰은 호출자가 요청하는 작업을 수행할 수 있는 적절한 권한을 갖도록 합니다.
액세스 토큰을 가져오려면 앱이 Microsoft ID 플랫폼 등록되고 관리자가 요청 서비스 REST API에 대한 액세스 권한을 부여받아야 합니다. verifiable-credentials-app 애플리케이션을 등록하지 않은 경우 앱을 등록하는 방법 및 애플리케이션 비밀 생성을 참조하세요.
액세스 토큰 가져오기
OAuth 2.0 클라이언트 자격 증명 부여 흐름을 사용하여 Microsoft ID 플랫폼을 통해 액세스 토큰을 획득합니다. 이 목적을 위해 신뢰할 수 있는 라이브러리를 사용합니다. 이 자습서에서는 MSAL(Microsoft 인증 라이브러리)을 사용합니다. MSAL은 보안 웹 API를 호출할 수 있는 앱에 인증 및 권한 부여를 추가하는 것을 간소화합니다.
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();
위의 코드에서 다음 매개 변수를 제공합니다.
매개 변수
Condition
설명
인증 기관
Required
애플리케이션이 작동할 디렉터리 테넌트입니다. 예: https://login.microsoftonline.com/{your-tenant} (your-tenant를 테넌트 ID 또는 이름으로 바꿉니다.)
Client ID
Required
앱에 할당되는 애플리케이션 ID입니다. 앱을 등록한 Azure Portal에서 이 정보를 찾을 수 있습니다.
클라이언트 암호
Required
앱에 대해 생성한 클라이언트 암호입니다.
범위
Required
3db474b9-6a0c-4840-96ac-1fceb342124f/.default로 설정해야 합니다. 이 설정은 역할 클레임이 있는 액세스 토큰을 생성합니다VerifiableCredential.Create.All.
콘솔 앱의 ID를 사용하여 액세스 토큰을 가져오는 방법에 대한 자세한 내용은 다음 문서 중 하나를 참조하세요.
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=12345678-0000-0000-00000000000000000
&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();
API 호출
확인 가능한 자격 증명을 발급하거나 확인하려면 다음을 수행합니다.
요청 서비스 REST API에 대한 HTTP POST 요청을 생성합니다. 테넌트 ID는 액세스 토큰에 클레임으로 존재하기 때문에 URL에 더 이상 필요하지 않습니다.
문제점
POST https://verifiedid.did.msidentity.com/v1.0/verifiableCredentials/createIssuanceRequest
확인
POST https://verifiedid.did.msidentity.com/v1.0/verifiableCredentials/createPresentationRequest
요청 페이로드에는 발급 및 프레젠테이션 콜백 엔드포인트가 포함됩니다. 엔드포인트는 웹 애플리케이션의 일부이며 HTTPS 프로토콜을 통해 공개적으로 사용할 수 있어야 합니다. 요청 서비스 API는 엔드포인트를 호출하여 특정 이벤트에 대해 앱에 알립니다. 예를 들어 사용자가 QR 코드를 스캔하거나, 인증자 앱에 대한 딥 링크를 사용하거나, 프레젠테이션 프로세스를 완료할 때 이러한 이벤트가 발생할 수 있습니다.
다음 다이어그램에서는 앱이 Request Service REST API에 대해 호출하고 애플리케이션에 대한 콜백을 설명합니다.
들어오는 HTTP POST 요청을 수신 대기하도록 엔드포인트를 구성합니다. 다음 코드 조각은 발급 콜백 HTTP 요청을 처리하는 방법과 그에 따라 UI를 업데이트하는 방법을 보여 줍니다.
[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
}
}