Bu kılavuzda, Doğrulanabilir Sunumlar için OpenID (OpenID4VP) isteği aracılığıyla Digital Credentials Verifier API kullanılarak doğrulanmış e-posta alma işleminin nasıl uygulanacağı açıklanmaktadır.
Bağımlılık ekleme
Uygulamanızın build.gradle dosyasına, Kimlik Bilgisi Yöneticisi için aşağıdaki bağımlılıkları ekleyin:
dependencies {
implementation("androidx.credentials:credentials:1.7.0-alpha02")
implementation("androidx.credentials:credentials-play-services-auth:1.7.0-alpha02")
}
Kimlik Bilgisi Yöneticisi'ni başlatma
CredentialManager nesnesi oluşturmak için uygulamanızı veya etkinlik bağlamınızı kullanın.
// Use your app or activity context to instantiate a client instance of
// CredentialManager.
private val credentialManager = CredentialManager.create(context)
Dijital kimlik bilgisi isteğini oluşturma
Doğrulama e-postası istemek için GetDigitalCredentialOption içeren bir GetCredentialRequest oluşturun. Bu seçenek, Doğrulanabilir Sunumlar için OpenID (OpenID4VP) isteği olarak biçimlendirilmiş bir requestJson dizesi gerektirir.
OpenID4VP isteği JSON'u belirli bir yapıda olmalıdır. Mevcut sağlayıcılar, dış "digital": {"requests": [...] sarmalayıcısı olan bir JSON yapısını destekler.
val nonce = generateSecureRandomNonce()
// This request follows the OpenID4VP spec
val openId4vpRequest = """
{
"requests": [
{
"protocol": "openid4vp-v1-unsigned",
"data": {
"response_type": "vp_token",
"response_mode": "dc_api",
"nonce": "$nonce",
"dcql_query": {
"credentials": [
{
"id": "user_info_query",
"format": "dc+sd-jwt",
"meta": {
"vct_values": ["UserInfoCredential"]
},
"claims": [
{"path": ["email"]},
{"path": ["name"]},
{"path": ["given_name"]},
{"path": ["family_name"]},
{"path": ["picture"]},
{"path": ["hd"]},
{"path": ["email_verified"]}
]
}
]
}
}
}
]
}
"""
val getDigitalCredentialOption = GetDigitalCredentialOption(requestJson = openId4vpRequest)
val request = GetCredentialRequest(listOf(getDigitalCredentialOption))
İstek aşağıdaki önemli bilgileri içerir:
- DCQL sorgusu:
dcql_query, kimlik bilgisi türünü ve istenen talepleri (email_verified) belirtir. Doğrulama düzeyini belirlemek için başka taleplerde bulunabilirsiniz. Olası iddialardan birkaçı şunlardır:email_verified: Yanıtta, e-postanın doğrulanıp doğrulanmadığını gösteren bir Boole değeridir.hd(barındırılan alan adı): Yanıtta bu alan boştur.
- nonce: Her istek için benzersiz, kriptografik olarak güvenli rastgele bir değer oluşturulur. Bu, tekrar saldırılarını önlediği için güvenlik açısından kritik bir öneme sahiptir.
UserInfoCredential: Bu değer, kullanıcı özelliklerini içeren belirli bir dijital kimlik bilgisi türünü ifade eder. E-posta doğrulama kullanım alanını ayırt etmek için bu parametrenin isteğe eklenmesi çok önemlidir.
Ardından, openId4vpRequest JSON'u bir GetDigitalCredentialOption içine sarmalayın, bir GetCredentialRequest oluşturun ve getCredential() yöntemini çağırın.
İsteği kullanıcıya sunma
Kimlik Bilgisi Yöneticisi'nin yerleşik kullanıcı arayüzünü kullanarak isteği kullanıcıya gösterin.
try {
// Requesting Digital Credential from user...
val result = credentialManager.getCredential(activity, request)
when (val credential = result.credential) {
is DigitalCredential -> {
val responseJsonString = credential.credentialJson
// Successfully received digital credential response.
// Next, parse this response and send it to your server.
// ...
}
else -> {
// handle Unexpected State() - Up to the developer
}
}
} catch (e: Exception) {
// handle exceptions - Up to the developer
}
İstemcide yanıtı ayrıştırma
Yanıtı aldıktan sonra istemcide ön ayrıştırma yapabilirsiniz. Bu, kullanıcı arayüzünü hemen güncellemek (ör. kullanıcının adını göstermek) için kullanışlıdır.
Aşağıdaki kod, ham Seçici Açıklama JWT'sini (SD-JWT) ayıklar ve taleplerinin kodunu çözmek için bir yardımcı kullanır.
// 1. Parse the outer JSON wrapper to get the `vp_token`
val responseData = JSONObject(responseJsonString)
val vpToken = responseData.getJSONObject("vp_token")
// 2. Extract the raw SD-JWT string
val credentialId = vpToken.keys().next()
val rawSdJwt = vpToken.getJSONArray(credentialId).getString(0)
// 3. Use your parser to get the verified claims
// Server-side validation/parsing is highly recommended.
// Assumes a local parser like the one in our SdJwtParser.kt sample
val claims = SdJwtParser.parse(rawSdJwt)
Log.d("TAG", "Parsed Claims: ${claims.toString(2)}")
// 4. Create your VerifiedUserInfo object with REAL data
val userInfo = VerifiedUserInfo(
email = claims.getString("email"),
displayName = claims.optString("name", claims.getString("email"))
)
Yanıtı işleme
Credential Manager API, DigitalCredential yanıtı döndürür.
Aşağıda, ham responseJsonString'nin nasıl göründüğüne ve dahili SD-JWT'yi ayrıştırdıktan sonra hak taleplerinin nasıl göründüğüne dair bir örnek verilmiştir. Bu örnekte, doğrulanmış e-postanın yanı sıra ek meta veriler de gösterilmektedir:
/*
// Example of the raw JSON response from credential.credentialJson:
{
"vp_token": {
// This key matches the 'id' you set in your dcql_query
"user_info_query": [
// The SD-JWT string (Issuer JWT ~ Disclosures ~ Key Binding JWT)
"eyJhbGciOiJ...~WyI...IiwgImVtYWlsIiwgInVzZXJAZXhhbXBsZS5jb20iXQ~...~eyJhbGciOiJ..."
]
}
}
// Example of the parsed and verified claims from the SD-JWT on your server:
{
"cnf": {
"jwk": {..}
},
"exp": 1775688222,
"iat": 1775083422,
"iss": "https://verifiablecredentials-pa.googleapis.com",
"vct": "UserInfoCredential",
"email": "jane.doe.246745@gmail.com",
"email_verified": true,
"given_name": "Jane",
"family_name": "Doe",
"name": "Jane Doe",
"picture": "http://example.com/janedoe/me.jpg",
"hd": ""
}
*/
Hesap oluşturma için sunucu tarafı doğrulama
Alınan e-posta, şifreleme yöntemiyle doğrulandığı için e-posta OTP doğrulama adımını atlayabilirsiniz. Bu sayede, kaydolma sürecindeki zorlukları önemli ölçüde azaltabilir ve dönüşümü artırabilirsiniz. Bu işlem en iyi şekilde sunucunuzda gerçekleştirilir. İstemci, ham yanıtı (vp_token içeren) ve orijinal tek seferlik rastgele sayıyı yeni bir sunucu uç noktasına gönderir.
Doğrulama için uygulamanız, hesap oluşturmadan veya kullanıcıyı giriş yaptırmadan önce kriptografik doğrulama için tam responseJsonString değerini sunucunuza göndermelidir.
Dijital kimlik bilgisi, sunucunuz için iki önemli doğrulama düzeyi sağlar:
- Verilerin özgünlüğü: Veren kuruluşun (
iss) URL'sinin veSD-JWTimzasının doğrulanması, bu verilerin güvenilir bir yetkili tarafından verildiğini kanıtlar. - Sunucunun kimliği:
cnfalanının ve anahtar bağlama (kb) imzasının doğrulanması, kimlik bilgisinin ilk verildiği cihaz tarafından paylaşıldığını onaylayarak başka bir cihazda ele geçirilmesini veya kullanılmasını önler.
Sunucudaki doğrulama işlemi şunları gerçekleştirmelidir:
- Vereni doğrulama:
iss(veren) alanınınhttps://verifiablecredentials-pa.googleapis.comile eşleştiğinden emin olun. - İmzayı doğrulama: https://verifiablecredentials-pa.googleapis.com/.well-known/vc-public-jwks adresinde bulunan ortak anahtarları (JWK'ler) kullanarak SD-JWT'nin imzasını kontrol edin.
Tam güvenlik için, tekrar oynatma saldırılarını önlemek amacıyla nonce değerini de doğruladığınızdan emin olun.
Sunucunuz bu adımları birleştirerek hem verilerin gerçekliğini hem de sunucunun kimliğini doğrulayabilir. Böylece, yeni hesap sağlanmadan önce kimlik bilgilerinin ele geçirilmediğinden veya taklit edilmediğinden emin olabilirsiniz.
try {
// Send the raw credential response and the original nonce to your server.
// Your server must validate the response. createAccountWithVerifiedCredentials
// is a custom implementation per each RP for server side verification and account creation.
val serverResponse = createAccountWithVerifiedCredentials(responseJsonString, nonce)
// Server returns the new account info (e.g., email, name)
val claims = JSONObject(serverResponse.json)
val userInfo = VerifiedUserInfo(
email = claims.getString("email"),
displayName = claims.optString("name", claims.getString("email"))
)
// handle response - Up to the developer
} catch (e: Exception) {
// handle exceptions - Up to the developer
}
Geçiş anahtarı oluşturma
Hesabın temel hazırlığı yapıldıktan sonra isteğe bağlı ancak kesinlikle önerilen bir sonraki adım, ilgili hesap için hemen geçiş anahtarı oluşturmaktır. Bu sayede kullanıcılar, güvenli ve şifresiz bir yöntemle oturum açabilir. Bu akış, standart geçiş anahtarı kaydıyla aynıdır.
WebView desteği
Akışın WebView üzerinde çalışması için geliştiricilerin, aktarımı kolaylaştırmak amacıyla bir JavaScript köprüsü (JS Köprüsü) uygulaması gerekir. Bu köprü, WebView nesnesinin yerel uygulamaya sinyal göndermesine olanak tanır. Yerel uygulama, Credential Manager API'ye gerçek çağrıyı yapabilir.