1. Başlamadan önce
WebAuthn olarak da bilinen Web Authentication API, kullanıcıların kimliğini doğrulamak için kaynak kapsamlı ve ortak anahtar kimlik bilgileri oluşturup kullanmanızı sağlar.
API; BDE, NFC ve USB ile dolaşan ve güvenlik anahtarları olarak da bilinen U2F veya FIDO2 kimlik doğrulayıcılarının yanı sıra kullanıcıların parmak izlerini veya ekran kilitlerini kullanarak kimlik doğrulaması yapabilmelerini sağlayan platform kimlik doğrulayıcı kullanımını destekler.
Bu codelab'de, parmak izi sensörü kullanan basit bir yeniden kimlik doğrulama işlevine sahip web sitesi oluşturacaksınız. Yeniden kimlik doğrulama, bir web sitesinde zaten oturum açmış kullanıcıların, web sitesinin önemli bölümlerine girmeye veya belirli bir süre sonra web sitesini yeniden ziyaret etmeye çalıştıklarında tekrar kimlik doğrulaması yapmalarını gerektirdiği için hesap verilerini korur.
Ön koşullar
- WebAuthn'un nasıl çalıştığıyla ilgili temel bilgiler
- JavaScript ile temel programlama becerileri
Yapacaklarınız
- Parmak izi sensörü kullanan basit bir yeniden kimlik doğrulama işlevine sahip web sitesi oluşturma
Gerekenler
- Aşağıdaki cihazlardan biri:
- Android cihaz (tercihen biyometrik sensörle)
- iOS 14 veya sonraki sürümlerde Touch ID ya da Face ID'ye sahip bir iPhone veya iPad
- macOS Big Sur veya üzeri bir modelde Touch ID'ye sahip bir MacBook Pro veya Air
- Windows Hello kurulumuyla birlikte Windows 10 19H1 veya sonraki sürümler
- Aşağıdaki tarayıcılardan biri:
- Google Chrome 67 veya sonraki sürümler
- Microsoft Edge 85 veya sonraki sürümler
- Safari 14 veya üzeri
2. Hazırlanın
Bu codelab'de aksan adlı bir hizmet kullanıyorsunuz. Burada, istemci ve sunucu tarafı kodunu JavaScript ile düzenleyebilir ve anında dağıtabilirsiniz.
https://glitch.com/edit/#!/webauthn-codelab-start adresine gidin.
İşleyiş şekli
Web sitesinin ilk durumunu görmek için şu adımları izleyin:
- Canlı web sitesini görmek için Göster > Yeni Pencerede'yi tıklayın.
- İstediğiniz bir kullanıcı adını girip İleri'yi tıklayın.
- Bir şifre girin ve Oturum aç'ı tıklayın.
Şifre yok sayılır, ancak hâlâ kimliğinizin doğrulaması yapılmış. Ana sayfaya ulaşırsınız.
- Yeniden kimlik doğrulaması yapmayı deneyin'i tıklayın ve ikinci, üçüncü ve dördüncü adımları tekrarlayın.
- Oturumu kapat'ı tıklayın.
Oturum açmayı her denediğinizde şifreyi girmeniz gerektiğini unutmayın. Bu işlem, web sitesinin önemli bir bölümüne erişebilmesi için önce yeniden kimlik doğrulaması yapması gereken bir kullanıcının emülasyonunu yapar.
Kodu yeniden düzenleyin
- WebAuthn / FIDO2 API Codelab'e gidin.
- Projenizi adına çatallayıp Remix Projesi'ni tıklayın ve yeni bir URL'de kendi sürümünüzle devam edin.
3. Parmak izinle kimlik bilgisi kaydetme
Cihazda yerleşik olarak bulunan ve kullanıcının kimliğini doğrulayan kimlik doğrulayıcı UVPA tarafından oluşturulan bir kimlik bilgisini kaydetmeniz gerekir. Bu genellikle kullanıcının cihazına bağlı olarak bir parmak izi sensörü olarak görülür.
Bu özelliği /home
sayfasına eklersiniz:
registerCredential()
işlevi oluşturma
Yeni bir kimlik bilgisi kaydeden bir registerCredential()
işlevi oluşturun.
public/client.js
export const registerCredential = async () => {
};
Sunucu uç noktasından giriş sorgulamasını ve diğer seçenekleri edinme
Kullanıcıdan yeni bir kimlik bilgisi kaydettirmesini istemeden önce, sunucudan, kimlik doğrulaması dahil olmak üzere WebAuthn'da iletilecek parametreleri döndürmesini isteyin. Neyse ki bu tür parametrelerle yanıt veren bir sunucu uç noktanız zaten var.
registerCredential()
koduna aşağıdaki kodu ekleyin.
public/client.js
const opts = {
attestation: 'none',
authenticatorSelection: {
authenticatorAttachment: 'platform',
userVerification: 'required',
requireResidentKey: false
}
};
const options = await _fetch('/auth/registerRequest', opts);
Sunucu ile istemci arasındaki protokol WebAuthn spesifikasyonunun bir parçası değildir. Ancak bu codelab, WebAuthn spesifikasyonuyla uyumlu olacak şekilde tasarlanmıştır ve sunucuya ilettiğiniz JSON nesnesi, sizin için sezgisel olması açısından PublicKeyCredentialCreationOptions
ile çok benzerdir. Aşağıdaki tabloda, sunucuya iletebileceğiniz önemli parametreler ve bunların ne işe yaradığı açıklanmaktadır:
Parametreler | Açıklamalar | ||
| Onay aktarımı tercihi: | ||
| Kimlik doğrulayıcının yinelenenler oluşturmasını önlemek için | ||
|
| Mevcut kimlik doğrulayıcıları filtreleyin. Cihaza bağlı bir kimlik doğrulayıcı kullanmak istiyorsanız " | |
| Kimlik doğrulayıcı yerel kullanıcı doğrulamasının " | ||
| Oluşturulan kimlik bilgilerinin gelecekteki hesap seçici kullanıcı deneyimi için kullanılabilmesi gerekiyorsa |
Bu seçenekler hakkında daha fazla bilgi edinmek için 5.4 Kimlik Bilgisi Oluşturma seçenekleri (sözlük PublicKeyCredentialCreationOptions
).
Aşağıda, sunucudan aldığınız örnek seçenekler verilmiştir.
{
"rp": {
"name": "WebAuthn Codelab",
"id": "webauthn-codelab.glitch.me"
},
"user": {
"displayName": "User Name",
"id": "...",
"name": "test"
},
"challenge": "...",
"pubKeyCredParams": [
{
"type": "public-key",
"alg": -7
}, {
"type": "public-key",
"alg": -257
}
],
"timeout": 1800000,
"attestation": "none",
"excludeCredentials": [
{
"id": "...",
"type": "public-key",
"transports": [
"internal"
]
}
],
"authenticatorSelection": {
"authenticatorAttachment": "platform",
"userVerification": "required"
}
}
Kimlik bilgisi oluşturma
- Bu seçenekler HTTP protokolünden geçecek şekilde kodlandığından, bazı parametreleri özellikle
user.id
,challenge
veexcludeCredentials
dizisine dahil edilenid
örneklerine geri dönüştürün:
public/client.js
options.user.id = base64url.decode(options.user.id);
options.challenge = base64url.decode(options.challenge);
if (options.excludeCredentials) {
for (let cred of options.excludeCredentials) {
cred.id = base64url.decode(cred.id);
}
}
- Yeni bir kimlik bilgisi oluşturmak için
navigator.credentials.create()
yöntemini çağırın.
Bu çağrıda, tarayıcı kimlik doğrulayıcıyla etkileşimde bulunur ve kullanıcının kimliğini UVPA ile doğrulamaya çalışır.
public/client.js
const cred = await navigator.credentials.create({
publicKey: options,
});
Kullanıcı, kimliğini doğruladıktan sonra sunucuya gönderebileceğiniz ve kimlik doğrulayıcıyı kaydedebileceğiniz bir kimlik bilgisi nesnesi alırsınız.
Kimlik bilgisini sunucu uç noktasına kaydedin
Almanız gereken örnek bir kimlik bilgisi nesnesi.
{
"id": "...",
"rawId": "...",
"type": "public-key",
"response": {
"clientDataJSON": "...",
"attestationObject": "..."
}
}
- Tıpkı bir kimlik bilgisini kaydetmek için bir seçenek nesnesi aldığınızda, kimlik bilgisinin ikili parametreleri kodlayarak bir dize olarak sunucuya teslim edilebilmesini sağlayın:
public/client.js
const credential = {};
credential.id = cred.id;
credential.rawId = base64url.encode(cred.rawId);
credential.type = cred.type;
if (cred.response) {
const clientDataJSON =
base64url.encode(cred.response.clientDataJSON);
const attestationObject =
base64url.encode(cred.response.attestationObject);
credential.response = {
clientDataJSON,
attestationObject,
};
}
- Kullanıcı geri geldiğinde kimlik doğrulaması için kullanabileceğiniz kimlik bilgisi kimliğini yerel olarak depolayın:
public/client.js
localStorage.setItem(`credId`, credential.id);
- Nesneyi sunucuya gönderin ve
HTTP code 200
değerini döndürürse yeni kimlik bilgisini başarıyla kaydedilmiş olarak kabul edin.
public/client.js
return await _fetch('/auth/registerResponse' , credential);
Artık registerCredential()
işlevine sahipsiniz.
Bu bölümün nihai kodu
public/client.js
...
export const registerCredential = async () => {
const opts = {
attestation: 'none',
authenticatorSelection: {
authenticatorAttachment: 'platform',
userVerification: 'required',
requireResidentKey: false
}
};
const options = await _fetch('/auth/registerRequest', opts);
options.user.id = base64url.decode(options.user.id);
options.challenge = base64url.decode(options.challenge);
if (options.excludeCredentials) {
for (let cred of options.excludeCredentials) {
cred.id = base64url.decode(cred.id);
}
}
const cred = await navigator.credentials.create({
publicKey: options
});
const credential = {};
credential.id = cred.id;
credential.rawId = base64url.encode(cred.rawId);
credential.type = cred.type;
if (cred.response) {
const clientDataJSON =
base64url.encode(cred.response.clientDataJSON);
const attestationObject =
base64url.encode(cred.response.attestationObject);
credential.response = {
clientDataJSON,
attestationObject
};
}
localStorage.setItem(`credId`, credential.id);
return await _fetch('/auth/registerResponse' , credential);
};
...
4. Kimlik bilgilerini kaydetmek, almak ve kaldırmak için kullanıcı arayüzünü oluşturun
Kayıtlı kimlik bilgilerinin ve düğmelerin yer aldığı bir listeye sahip olmak çok güzel.
Kullanıcı arayüzü yer tutucusu oluşturma
Kimlik bilgilerini listelemek için kullanıcı arayüzü, yeni kimlik bilgilerini kaydetmek için bir düğme ekleyin. Özelliğin kullanılabilir olup olmadığına bağlı olarak, hidden
sınıfını uyarı mesajından veya yeni bir kimlik bilgisini kaydetmek için kullanılan düğmeden kaldırırsınız. ul#list
, kayıtlı kimlik bilgilerinin listesini eklemek için yer tutucudur.
views/home.html
<p id="uvpa_unavailable" class="hidden">
This device does not support User Verifying Platform Authenticator. You can't register a credential.
</p>
<h3 class="mdc-typography mdc-typography--headline6">
Your registered credentials:
</h3>
<section>
<div id="list"></div>
</section>
<mwc-button id="register" class="hidden" icon="fingerprint" raised>Add a credential</mwc-button>
Özellik algılama ve UVPA kullanılabilirliği
UVPA kullanılabilirliğini kontrol etmek için aşağıdaki adımları izleyin:
- WebAuthn'un kullanılabilir olup olmadığını öğrenmek için
window.PublicKeyCredential
dosyasını inceleyin. - UVPA olup olmadığını kontrol etmek için
PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable()
numaralı telefonu arayın . Sertifikalar uygunsa yeni bir kimlik bilgisi kaydetmek için düğmeyi gösterirsiniz. Bunların ikisi de yoksa uyarı mesajını görürsünüz.
views/home.html
const register = document.querySelector('#register');
if (window.PublicKeyCredential) {
PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable()
.then(uvpaa => {
if (uvpaa) {
register.classList.remove('hidden');
} else {
document
.querySelector('#uvpa_unavailable')
.classList.remove('hidden');
}
});
} else {
document
.querySelector('#uvpa_unavailable')
.classList.remove('hidden');
}
Kimlik bilgilerinin listesini alma ve görüntüleme
- Kayıtlı kimlik bilgilerini almak ve bunları bir listede görüntülemek için bir
getCredentials()
işlevi oluşturun. Neyse ki/auth/getKeys
sunucusunda, oturum açmış olan kullanıcı için kayıtlı kimlik bilgilerini getirebileceğiniz yararlı bir uç nokta zaten var.
Döndürülen JSON, id
ve publicKey
gibi kimlik bilgisi bilgilerini içerir. Bunları kullanıcılara göstermek için HTML oluşturabilirsiniz.
views/home.html
const getCredentials = async () => {
const res = await _fetch('/auth/getKeys');
const list = document.querySelector('#list');
const creds = html`${res.credentials.length > 0 ? res.credentials.map(cred => html`
<div class="mdc-card credential">
<span class="mdc-typography mdc-typography--body2">${cred.credId}</span>
<pre class="public-key">${cred.publicKey}</pre>
<div class="mdc-card__actions">
<mwc-button id="${cred.credId}" @click="${removeCredential}" raised>Remove</mwc-button>
</div>
</div>`) : html`
<p>No credentials found.</p>
`}`;
render(creds, list);
};
- Kullanıcı
/home
sayfasına ulaşır gelmez kullanılabilir kimlik bilgilerini göstermek içingetCredentials()
arayın.
views/home.html
getCredentials();
Kimlik bilgisini kaldır
Kimlik bilgisi listesine her kimlik bilgisini kaldırmak için bir düğme eklediniz. /auth/removeKey
sorgusunu, kaldırmak için credId
sorgu parametresiyle birlikte bir istek gönderebilirsiniz.
public/client.js
export const unregisterCredential = async (credId) => {
localStorage.removeItem('credId');
return _fetch(`/auth/removeKey?credId=${encodeURIComponent(credId)}`);
};
- Mevcut
import
ifadesineunregisterCredential
ekleyin.
views/home.html
import { _fetch, unregisterCredential } from '/client.js';
- Kullanıcı Kaldır'ı tıkladığında çağırılacak bir işlev ekleyin.
views/home.html
const removeCredential = async e => {
try {
await unregisterCredential(e.target.id);
getCredentials();
} catch (e) {
alert(e);
}
};
Kimlik bilgisi kaydetme
Kullanıcı, Kimlik bilgisi ekle'yi tıkladığında yeni bir kimlik bilgisi kaydetmek için registerCredential()
çağrısı yapabilirsiniz.
- Mevcut
import
ifadesineregisterCredential
ekleyin.
views/home.html
import { _fetch, registerCredential, unregisterCredential } from '/client.js';
navigator.credentials.create()
seçeneğiyle birlikteregisterCredential()
çağırın.
Kayıt sonrasında getCredentials()
numaralı telefonu arayarak kimlik bilgisi listesini yenilemeyi unutmayın.
views/home.html
register.addEventListener('click', e => {
registerCredential().then(user => {
getCredentials();
}).catch(e => alert(e));
});
Artık yeni bir kimlik bilgisi kaydedebilir ve kimlik bilgilerini görüntüleyebilirsiniz. Canlı web sitenizde deneyebilirsiniz.
Bu bölümün nihai kodu
views/home.html
...
<p id="uvpa_unavailable" class="hidden">
This device does not support User Verifying Platform Authenticator. You can't register a credential.
</p>
<h3 class="mdc-typography mdc-typography--headline6">
Your registered credentials:
</h3>
<section>
<div id="list"></div>
<mwc-fab id="register" class="hidden" icon="add"></mwc-fab>
</section>
<mwc-button raised><a href="/reauth">Try reauth</a></mwc-button>
<mwc-button><a href="/auth/signout">Sign out</a></mwc-button>
</main>
<script type="module">
import { _fetch, registerCredential, unregisterCredential } from '/client.js';
import { html, render } from 'https://unpkg.com/lit-html@1.0.0/lit-html.js?module';
const register = document.querySelector('#register');
if (window.PublicKeyCredential) {
PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable()
.then(uvpaa => {
if (uvpaa) {
register.classList.remove('hidden');
} else {
document
.querySelector('#uvpa_unavailable')
.classList.remove('hidden');
}
});
} else {
document
.querySelector('#uvpa_unavailable')
.classList.remove('hidden');
}
const getCredentials = async () => {
const res = await _fetch('/auth/getKeys');
const list = document.querySelector('#list');
const creds = html`${res.credentials.length > 0 ? res.credentials.map(cred => html`
<div class="mdc-card credential">
<span class="mdc-typography mdc-typography--body2">${cred.credId}</span>
<pre class="public-key">${cred.publicKey}</pre>
<div class="mdc-card__actions">
<mwc-button id="${cred.credId}" @click="${removeCredential}" raised>Remove</mwc-button>
</div>
</div>`) : html`
<p>No credentials found.</p>
`}`;
render(creds, list);
};
getCredentials();
const removeCredential = async e => {
try {
await unregisterCredential(e.target.id);
getCredentials();
} catch (e) {
alert(e);
}
};
register.addEventListener('click', e => {
registerCredential({
attestation: 'none',
authenticatorSelection: {
authenticatorAttachment: 'platform',
userVerification: 'required',
requireResidentKey: false
}
})
.then(user => {
getCredentials();
})
.catch(e => alert(e));
});
</script>
...
public/client.js
...
export const unregisterCredential = async (credId) => {
localStorage.removeItem('credId');
return _fetch(`/auth/removeKey?credId=${encodeURIComponent(credId)}`);
};
...
5. Parmak iziyle kullanıcının kimliğini doğrulama
Artık kimlik bilgilerinizi kaydettirdiniz ve kullanıcının kimliğini doğrulama yöntemi olarak kullanmaya hazırsınız. Şimdi web sitesine yeniden kimlik doğrulama işlevi ekliyorsunuz. Kullanıcı deneyimi şöyledir:
/reauth
sayfasına gelen kullanıcılar, biyometrik kimlik doğrulamanın mümkün olduğu durumlarda bir Kimlik doğrulama düğmesi görür. Parmak iziyle (UVPA) kimlik doğrulama, Kimlik doğrulaması yap seçeneğine dokunduktan, kimlik doğrulamasının başarıyla tamamlanmasından sonra /home
sayfasına geldiğinde başlar. Biyometrik kimlik doğrulama kullanılamazsa veya biyometrik kimlik doğrulama başarısız olursa kullanıcı arayüzü, mevcut şifre formunu kullanmaya başlar.
authenticate()
işlevi oluşturma
Parmak iziyle kullanıcının kimliğini doğrulayan authenticate()
adında bir işlev oluşturun. JavaScript kodunu buraya eklersiniz:
public/client.js
export const authenticate = async () => {
};
Sunucu uç noktasından giriş sorgulamasını ve diğer seçenekleri edinme
- Kimlik doğrulamasından önce, kullanıcının depolanmış bir kimlik bilgisi olup olmadığını inceleyin ve varsa sorgu parametresi olarak ayarlayın.
Diğer seçeneklerle birlikte kimlik bilgisi kimliğini sağladığınızda sunucu, alakalı allowCredentials
sağlayabilir. Bu da kullanıcı doğrulamasının güvenilir olmasını sağlar.
public/client.js
const opts = {};
let url = '/auth/signinRequest';
const credId = localStorage.getItem(`credId`);
if (credId) {
url += `?credId=${encodeURIComponent(credId)}`;
}
- Kullanıcıdan kimlik doğrulamasını istemeden önce sunucudan bir giriş sorgulaması ve diğer parametreleri göndermesini isteyin. Sunucuya POST isteği göndermek için bağımsız değişken olarak
opts
ile_fetch()
çağrısı yapın.
public/client.js
const options = await _fetch(url, opts);
Almanız gereken örnek seçenekler şunlardır (PublicKeyCredentialRequestOptions
ile uyumludur).
{
"challenge": "...",
"timeout": 1800000,
"rpId": "webauthn-codelab.glitch.me",
"userVerification": "required",
"allowCredentials": [
{
"id": "...",
"type": "public-key",
"transports": [
"internal"
]
}
]
}
Buradaki en önemli seçenek allowCredentials
. Sunucudan seçenekler aldığınızda allowCredentials
, sorgu parametresinde kimliği olan bir kimlik bilgisinin sunucu tarafında bulunup bulunmadığına bağlı olarak bir dizideki tek bir nesne veya boş bir dizi olmalıdır.
- Kullanıcı arayüzü, şifre istemeye devam etmesi için
allowCredentials
boş bir dizi olduğundanull
ile ilgili sözü çözün.
if (options.allowCredentials.length === 0) {
console.info('No registered credentials found.');
return Promise.resolve(null);
}
Kullanıcıyı yerel olarak doğrulayın ve kimlik bilgisi alın
- Bu seçenekler HTTP protokolünden geçmek için kodlanmış olarak yayınlandığından, bazı parametreleri, özellikle
challenge
veallowCredentials
dizisine dahil edilenid
örneklerini geri dönüştürün:
public/client.js
options.challenge = base64url.decode(options.challenge);
for (let cred of options.allowCredentials) {
cred.id = base64url.decode(cred.id);
}
- Kullanıcı kimliğini UVPA ile doğrulamak için
navigator.credentials.get()
yöntemini çağırın.
public/client.js
const cred = await navigator.credentials.get({
publicKey: options
});
Kullanıcı, kimliğini doğruladıktan sonra sunucuya gönderebileceğiniz ve kullanıcının kimliğini doğrulayabileceğiniz bir kimlik bilgisi nesnesi alırsınız.
Kimlik bilgilerini doğrulayın
Aşağıda, almış olmanız gereken örnek bir PublicKeyCredential
nesnesi (response
, AuthenticatorAssertionResponse
) verilmiştir:
{
"id": "...",
"type": "public-key",
"rawId": "...",
"response": {
"clientDataJSON": "...",
"authenticatorData": "...",
"signature": "...",
"userHandle": ""
}
}
- Kimlik bilgisinin ikili parametreleri kodlayarak bir dize olarak sunucuya teslim edilebilmesini sağlayın:
public/client.js
const credential = {};
credential.id = cred.id;
credential.type = cred.type;
credential.rawId = base64url.encode(cred.rawId);
if (cred.response) {
const clientDataJSON =
base64url.encode(cred.response.clientDataJSON);
const authenticatorData =
base64url.encode(cred.response.authenticatorData);
const signature =
base64url.encode(cred.response.signature);
const userHandle =
base64url.encode(cred.response.userHandle);
credential.response = {
clientDataJSON,
authenticatorData,
signature,
userHandle,
};
}
- Nesneyi sunucuya gönderin ve
HTTP code 200
değerini döndürürse, kullanıcının başarıyla oturum açtığını göz önünde bulundurun:
public/client.js
return await _fetch(`/auth/signinResponse`, credential);
Artık authentication()
işlevine sahipsiniz.
Bu bölümün nihai kodu
public/client.js
...
export const authenticate = async () => {
const opts = {};
let url = '/auth/signinRequest';
const credId = localStorage.getItem(`credId`);
if (credId) {
url += `?credId=${encodeURIComponent(credId)}`;
}
const options = await _fetch(url, opts);
if (options.allowCredentials.length === 0) {
console.info('No registered credentials found.');
return Promise.resolve(null);
}
options.challenge = base64url.decode(options.challenge);
for (let cred of options.allowCredentials) {
cred.id = base64url.decode(cred.id);
}
const cred = await navigator.credentials.get({
publicKey: options
});
const credential = {};
credential.id = cred.id;
credential.type = cred.type;
credential.rawId = base64url.encode(cred.rawId);
if (cred.response) {
const clientDataJSON =
base64url.encode(cred.response.clientDataJSON);
const authenticatorData =
base64url.encode(cred.response.authenticatorData);
const signature =
base64url.encode(cred.response.signature);
const userHandle =
base64url.encode(cred.response.userHandle);
credential.response = {
clientDataJSON,
authenticatorData,
signature,
userHandle,
};
}
return await _fetch(`/auth/signinResponse`, credential);
};
...
6. Yeniden kimlik doğrulama deneyimini etkinleştir
Derleme kullanıcı arayüzü
Kullanıcı geri döndüğünde, mümkün olduğunca kolay ve güvenli bir şekilde yeniden kimlik doğrulaması yapmasını istersiniz. Biyometrik kimlik doğrulama bu noktada devreye girer. Bununla birlikte, biyometrik kimlik doğrulamasının kullanılamayacağı durumlar vardır:
- UVPA kullanılamıyor.
- Kullanıcı henüz cihazında kimlik bilgisi kaydetmedi.
- Depolama alanı temizlenir ve cihaz artık kimlik bilgisi kimliğini hatırlamaz.
- Kullanıcı, parmağının ıslak olması veya maske takma gibi nedenlerle kimliğini doğrulayamıyor.
Bu nedenle, yedek olarak diğer oturum açma seçeneklerini sağlamanız her zaman için önemlidir. Bu codelab'de, form tabanlı şifre çözümünü kullanıyorsunuz.
- Şifre formuna ek olarak biyometrik kimlik doğrulamasını çağıran bir kimlik doğrulama düğmesi göstermek için kullanıcı arayüzü ekleyin.
Kullanıcının durumuna bağlı olarak bunlardan birini seçip göstermek için hidden
sınıfını kullanın.
views/reauth.html
<div id="uvpa_available" class="hidden">
<h2>
Verify your identity
</h2>
<div>
<mwc-button id="reauth" raised>Authenticate</mwc-button>
</div>
<div>
<mwc-button id="cancel">Sign-in with password</mwc-button>
</div>
</div>
- Forma
class="hidden"
öğesini ekleyin:
views/reauth.html
<form id="form" method="POST" action="/auth/password" class="hidden">
Özellik algılama ve UVPA kullanılabilirliği
Aşağıdaki koşullardan biri karşılanırsa kullanıcıların şifreyle oturum açması gerekir:
- WebAuthn kullanılamıyor.
- UVPA kullanılamaz.
- Bu UVPA için kimlik bilgisi bulunamıyor.
Kimlik doğrulama düğmesini seçerek gösterin veya gizleyin:
views/reauth.html
if (window.PublicKeyCredential) {
PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable()
.then(uvpaa => {
if (uvpaa && localStorage.getItem(`credId`)) {
document
.querySelector('#uvpa_available')
.classList.remove('hidden');
} else {
form.classList.remove('hidden');
}
});
} else {
form.classList.remove('hidden');
}
Şifre formuna yedek
Kullanıcı şifreyle oturum açmayı da seçebilmelidir.
Kullanıcı Şifreyle oturum aç'ı tıkladığında şifre formunu göster ve kimlik doğrulama düğmesini gizle:
views/reauth.html
const cancel = document.querySelector('#cancel');
cancel.addEventListener('click', e => {
form.classList.remove('hidden');
document
.querySelector('#uvpa_available')
.classList.add('hidden');
});
Biyometrik kimlik doğrulamasını çağırın
Son olarak, biyometrik kimlik doğrulamayı etkinleştirin.
authenticate
ifadesini mevcutimport
ifadesine ekle:
views/reauth.html
import { _fetch, authenticate } from '/client.js';
- Kullanıcı, biyometrik kimlik doğrulamasını başlatmak için Kimlik doğrulaması'na dokunduğunda
authenticate()
çağırın.
Biyometrik kimlik doğrulama hatasının şifre formuna döndüğünden emin olun.
views/reauth.html
const button = document.querySelector('#reauth');
button.addEventListener('click', e => {
authenticate().then(user => {
if (user) {
location.href = '/home';
} else {
throw 'User not found.';
}
}).catch(e => {
console.error(e.message || e);
alert('Authentication failed. Use password to sign-in.');
form.classList.remove('hidden');
document.querySelector('#uvpa_available').classList.add('hidden');
});
});
Bu bölümün nihai kodu
views/reauth.html
...
<main class="content">
<div id="uvpa_available" class="hidden">
<h2>
Verify your identity
</h2>
<div>
<mwc-button id="reauth" raised>Authenticate</mwc-button>
</div>
<div>
<mwc-button id="cancel">Sign-in with password</mwc-button>
</div>
</div>
<form id="form" method="POST" action="/auth/password" class="hidden">
<h2>
Enter a password
</h2>
<input type="hidden" name="username" value="{{username}}" />
<div class="mdc-text-field mdc-text-field--filled">
<span class="mdc-text-field__ripple"></span>
<label class="mdc-floating-label" id="password-label">password</label>
<input type="password" class="mdc-text-field__input" aria-labelledby="password-label" name="password" />
<span class="mdc-line-ripple"></span>
</div>
<input type="submit" class="mdc-button mdc-button--raised" value="Sign-In" />
<p class="instructions">password will be ignored in this demo.</p>
</form>
</main>
<script src="https://unpkg.com/material-components-web@7.0.0/dist/material-components-web.min.js"></script>
<script type="module">
new mdc.textField.MDCTextField(document.querySelector('.mdc-text-field'));
import { _fetch, authenticate } from '/client.js';
const form = document.querySelector('#form');
form.addEventListener('submit', e => {
e.preventDefault();
const form = new FormData(e.target);
const cred = {};
form.forEach((v, k) => cred[k] = v);
_fetch(e.target.action, cred)
.then(user => {
location.href = '/home';
})
.catch(e => alert(e));
});
if (window.PublicKeyCredential) {
PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable()
.then(uvpaa => {
if (uvpaa && localStorage.getItem(`credId`)) {
document
.querySelector('#uvpa_available')
.classList.remove('hidden');
} else {
form.classList.remove('hidden');
}
});
} else {
form.classList.remove('hidden');
}
const cancel = document.querySelector('#cancel');
cancel.addEventListener('click', e => {
form.classList.remove('hidden');
document
.querySelector('#uvpa_available')
.classList.add('hidden');
});
const button = document.querySelector('#reauth');
button.addEventListener('click', e => {
authenticate().then(user => {
if (user) {
location.href = '/home';
} else {
throw 'User not found.';
}
}).catch(e => {
console.error(e.message || e);
alert('Authentication failed. Use password to sign-in.');
form.classList.remove('hidden');
document.querySelector('#uvpa_available').classList.add('hidden');
});
});
</script>
...
7. Tebrikler!
Bu codelab'i tamamladınız!
Daha fazla bilgi
- Web Kimlik Doğrulaması: Ortak Anahtar Kimlik Bilgileri Seviye 1'e erişim için API
- WebAuthn API'ye giriş
- FIDO WebAuthn Atölyesi
- WebAuthn Kılavuzu: DUOSEC
- İlk Android FIDO2 API'niz
Yardımlarınız için FIDO Alliance'tan Yuriy Ackermann'a teşekkür ederiz.