I'm looking for assistance designing a Windows custom credential provider that includes fingerprint authentication. Specifically:
It needs to authenticate users via their fingerprints, using an external fingerprint reader/software.
It must interface with the Windows biometric fingerprint API to integrate with the operating system.
Unfortunately I don't have experience working with Windows or its API, so I was hoping to find an open source sample project I could adapt. However, I haven't been able to find anything suitable.
Does anyone have experience building Windows credential providers they could advise me on? I'm essentially looking for guidance on:
1-Using the Windows biometric fingerprint API
2-Integrating an external fingerprint reader/software
3-The overall architecture for a custom credential provider
Any pointers in the right direction would be greatly appreciated! If a full working sample/template exists that others have built, that would be ideal.
- i found a similar question --> Windows Credential Provider - Is there a way to communicate or interfere with windows Hello API? , but the answer wasn't really clear/ there was no much guidance and as i already said i'm a beginner.
i asked chatgpt and it provided me with the following code, but i dont think its sufficient :
#include <credentialprovider.h>
#include <windows.h>
class MyCredentialProvider : public ICredentialProvider, public ICredentialProviderCredential
{
public:
// Implement ICredentialProvider methods
HRESULT STDMETHODCALLTYPE SetUsageScenario(
__in CREDENTIAL_PROVIDER_USAGE_SCENARIO cpus,
__in DWORD dwFlags
) override;
HRESULT STDMETHODCALLTYPE SetSerialization(
__in const CREDENTIAL_PROVIDER_CREDENTIAL_SERIALIZATION* pcpcs
) override;
HRESULT STDMETHODCALLTYPE Advise(
__in ICredentialProviderEvents* pcpe,
__in UINT_PTR upAdviseContext
) override;
HRESULT STDMETHODCALLTYPE UnAdvise() override;
HRESULT STDMETHODCALLTYPE GetFieldDescriptorCount(
__out DWORD* pdwCount
) override;
HRESULT STDMETHODCALLTYPE GetFieldDescriptorAt(
__in DWORD dwIndex,
__deref_out CREDENTIAL_PROVIDER_FIELD_DESCRIPTOR** ppcpfd
) override;
HRESULT STDMETHODCALLTYPE GetCredentialCount(
__out DWORD* pdwCount,
__out DWORD* pdwDefault,
__out BOOL* pbAutoLogonWithDefault
) override;
HRESULT STDMETHODCALLTYPE GetCredentialAt(
__in DWORD dwIndex,
__out ICredentialProviderCredential** ppcpc
) override;
// Implement ICredentialProviderCredential methods
HRESULT STDMETHODCALLTYPE Advise(
__in ICredentialProviderCredentialEvents* pcpce
) override;
HRESULT STDMETHODCALLTYPE UnAdvise() override;
HRESULT STDMETHODCALLTYPE SetSelected(
__out BOOL* pbAutoLogon
) override;
HRESULT STDMETHODCALLTYPE SetDeselected() override;
HRESULT STDMETHODCALLTYPE GetFieldState(
__in DWORD dwIndex,
__out CREDENTIAL_PROVIDER_FIELD_STATE* pcpfs,
__out CREDENTIAL_PROVIDER_FIELD_INTERACTIVE_STATE* pcpfis
) override;
HRESULT STDMETHODCALLTYPE GetStringValue(
__in DWORD dwIndex,
__out LPWSTR* ppwsz
) override;
HRESULT STDMETHODCALLTYPE GetBitmapValue(
__in DWORD dwIndex,
__out HBITMAP* phbmp
) override;
HRESULT STDMETHODCALLTYPE GetCheckboxValue(
__in DWORD dwIndex,
__out BOOL* pbChecked,
__deref_out LPWSTR* ppwszLabel
) override;
HRESULT STDMETHODCALLTYPE GetSubmitButtonValue(
__in DWORD dwIndex,
__out DWORD* pdwAdjacentTo
) override;
HRESULT STDMETHODCALLTYPE GetComboBoxValueCount(
__in DWORD dwIndex,
__out DWORD* pcItems,
__out DWORD* pdwSelectedItem
) override;
HRESULT STDMETHODCALLTYPE GetComboBoxValueAt(
__in DWORD dwIndex,
__in DWORD dwItem,
__deref_out LPWSTR* ppwszItem
) override;
HRESULT STDMETHODCALLTYPE SetStringValue(
__in DWORD dwIndex,
__in PCWSTR pwz
) override;
private:
// Add private members and methods as needed
};
// Implement ICredentialProvider methods
HRESULT STDMETHODCALLTYPE MyCredentialProvider::SetUsageScenario(
__in CREDENTIAL_PROVIDER_USAGE_SCENARIO cpus,
__in DWORD dwFlags
)
{
// TODO: Implement SetUsageScenario method
return E_NOTIMPL;
}
HRESULT STDMETHODCALLTYPE MyCredentialProvider::SetSerialization(
__in const CREDENTIAL_PROVIDER_CREDENTIAL_SERIALIZATION* pcpcs
)
{
// TODO: Implement SetSerialization method
return E_NOTIMPL;
}
HRESULT STDMETHODCALLTYPE MyCredentialProvider::Advise(
__in ICredentialProviderEvents* pcpe,
__in UINT_PTR upAdviseContext
)
{
// TODO: Implement Advise method
return E_NOTIMPL;
}
HRESULT STDMETHODCALLTYPE MyCredentialProvider::UnAdvise()
{
// TODO: Implement UnAdvise method
return E_NOTIMPL;
}
HRESULT STDMETHODCALLTYPE MyCredentialProvider::GetFieldDescriptorCount(
__out DWORD* pdwCount
)
{
// TODO: Implement GetFieldDescriptorCount method
return E_NOTIMPL;
}
HRESULT STDMETHODCALLTYPE MyCredentialProvider::GetFieldDescriptorAt(
__in DWORD dwIndex,
__deref_out CREDENTIAL_PROVIDER_FIELD_DESCRIPTOR** ppcpfd
)
{
// TODO: Implement GetFieldDescriptorAt method
return E_NOTIMPL;
}
HRESULT STDMETHODCALLTYPE MyCredentialProvider::GetCredentialCount(
__out DWORD* pdwCount,
__out DWORD* pdwDefault,
__out BOOL* pbAutoLogonWithDefault
)
{
// TODO: Implement GetCredentialCount method
return E_NOTIMPL;
}
HRESULT STDMETHODCALLTYPE MyCredentialProvider::GetCredentialAt(
__in DWORD dwIndex,
__out ICredentialProviderCredential** ppcpc
)
{
// TODO: Implement GetCredentialAt method
return E_NOTIMPL;
}
// Implement ICredentialProviderCredential methods
HRESULT STDMETHODCALLTYPE MyCredentialProvider::Advise(
__in ICredentialProviderCredentialEvents* pcpce
)
{
// TODO: Implement Advise method
return E_NOTIMPL;
}
HRESULT STDMETHODCALLTYPE MyCredentialProvider::UnAdvise()
{
// TODO: Implement UnAdvise method
return E_NOTIMPL;
}
HRESULT STDMETHODCALLTYPE MyCredentialProvider::SetSelected(
__out BOOL* pbAutoLogon
)
{
// TODO: Implement SetSelected method
return E_NOTIMPL;
}
HRESULT STDMETHODCALLTYPE MyCredentialProvider::SetDeselected()
{
// TODO: Implement SetDeselected method
return E_NOTIMPL;
}
HRESULT STDMETHODCALLTYPE MyCredentialProvider::GetFieldState(
__in DWORD dwIndex,
__out CREDENTIAL_PROVIDER_FIELD_STATE* pcpfs,
__out CREDENTIAL_PROVIDER_FIELD_INTERACTIVE_STATE* pcpfis
)
{
// TODO: Implement GetFieldState method
return E_NOTIMPL;
}
HRESULT STDMETHODCALLTYPE MyCredentialProvider::GetStringValue(
__in DWORD dwIndex,
__out LPWSTR* ppwsz
)
{
// TODO: Implement GetStringValue method
return E_NOTIMPL;
}
HRESULT STDMETHODCALLTYPE MyCredentialProvider::GetBitmapValue(
__in DWORD dwIndex,
__out HBITMAP* phbmp
)
{
// TODO: Implement GetBitmapValue method
return E_NOTIMPL;
}
HRESULT STDMETHODCALLTYPE MyCredentialProvider::GetCheckboxValue(
__in DWORD dwIndex,
__out BOOL* pbChecked,
__deref_out LPWSTR* ppwszLabel
)
{
// TODO: Implement GetCheckboxValue method
return E_NOTIMPL;
}
HRESULT STDMETHODCALLTYPE MyCredentialProvider::GetSubmitButtonValue(
__in DWORD dwIndex,
__out DWORD* pdwAdjacentTo
)
{
// TODO: Implement GetSubmitButtonValue method
return E_NOTIMPL;
}
HRESULT STDMETHODCALLTYPE MyCredentialProvider::GetComboBoxValueCount(
__in DWORD dwIndex,
__out DWORD* pcItems,
__out DWORD* pdwSelectedItem
)
{
// TODO: Implement GetComboBoxValueCount method
return E_NOTIMPL;
}
HRESULT STDMETHODCALLTYPE MyCredentialProvider::GetComboBoxValueAt(
__in DWORD dwIndex,
__in DWORD dwItem,
__deref_out LPWSTR* ppwszItem
)
{
// TODO: Implement GetComboBoxValueAt method
return E_NOTIMPL;
}
HRESULT STDMETHODCALLTYPE MyCredentialProvider::SetStringValue(
__in DWORD dwIndex,
__in PCWSTR pwz
)
{
// TODO: Implement SetStringValue method
return E_NOTIMPL;
}