phaetto / windows-credentials-provider Goto Github PK
View Code? Open in Web Editor NEWAn example implementation of a windows credential provider that is tightly connected with logon system
License: The Unlicense
An example implementation of a windows credential provider that is tightly connected with logon system
License: The Unlicense
Hi phaetto,
Is it possible to implement password change scenario in c#, because I couldn't find any doc or sample on implementing the same in c#.
In c++, Kerb_changepassword_request can be used by packing the credentials in getserialization function, but in c#, I couldn't find any method for packing the credentials.
Hi,
I recently got interested in CredentialProvider and run across your genius .NET implementation for it. The interface did work in terms of being registered by Windows as a credential provider. However I encountered some issues in your demo
public List<_CREDENTIAL_PROVIDER_FIELD_DESCRIPTOR> CredentialProviderFieldDescriptorList = new List<_CREDENTIAL_PROVIDER_FIELD_DESCRIPTOR> {
new _CREDENTIAL_PROVIDER_FIELD_DESCRIPTOR
{
cpft = _CREDENTIAL_PROVIDER_FIELD_TYPE.CPFT_SMALL_TEXT,
dwFieldID = 0,
pszLabel = "Rebootify Awesomeness",
},
new _CREDENTIAL_PROVIDER_FIELD_DESCRIPTOR
{
cpft = _CREDENTIAL_PROVIDER_FIELD_TYPE.CPFT_SUBMIT_BUTTON,
dwFieldID = 1,
pszLabel = "Login",
}
};
but the button did not appear in CredUI prompt.
I tried to add an edit text but it wasn't shown either. Is it CredUI's limitation to only render the first text as a title and ignore everything else?
_CREDENTIAL_PROVIDER_USAGE_SCENARIO.CPUS_LOGON
usage scenario and setup a dummy user account (including an username and a password) for a quick test. Then these infos was provided in TestWindowsCredentialProviderTile.GetSerialization()
but LSA (LogonUI issued a bad username or password) refused to accept the credentials for that dummy user account. And also no button was rendered as in CredUI.Any help on this would be greatly appreciated.
Dear Phaetto,
Our goal is to login a user once we receive the user data via an NFC card.
If i see your code its possible to write the data to the registry and then use it.
But i cant find a way to use it without first going to the user icon.
Is there a way to trigger login once we received the user data ?
Best Regards,
Hans
Hi there,
I have rebuilt this project in VS2015. I have also merged the registry. When I log out and in again, Windows 10 still shows the standard logon screen without any options. How do I get the custom login screen to show?
Thank in advance
dear,
when I build project completed, copy the WindowsCredentialProviderTest.dll to path "c:/windows/system32/” and click register-credentials-provider.reg file to regist,but it doesn't show in login screen。
other: windows 64bit Professional
Hey,
I have implemented the windows credential provider and it shows up during windows login.
But when I input the correct username and password, it shows me an error message which says "The user name or password is incorrect".
I have verified the username and password multiple times.
I haven't changed the authentication code in GetSerialization which does the authentication either. The account I'm trying to log into is a local account and not a domain account (machine isn't connect to any AD)
I have also tried hashing a password using NTLM manually and replacing it in password field which didn't work either.
Can you tell me why I'm getting this error message and why the login isn't happening?
Any help is appreciated, thank you.
Hi,
We are working on a custom implementation of a credential provider and have tried your version. this one works for us so we tried to create a clean assembly using this as a template,
When i implement the GetFieldDescriptotAt
method it results in a access violation error (which seems to be a memory pointer issue). I have copied the exact code from your project but it does not work. Also tried another marshal.
(BTW: I noticed that the default implementation of the interface lacks the [Out]
directive).
public int GetFieldDescriptorAt(uint dwIndex, [Out] IntPtr ppcpfd)
{
Debug.Write("GetFieldDescriptorAt");
try
{
Diagnostics.LogMethodEntry();
_logger.Debug($"GetFieldDescriptorAt: dwIndex [{dwIndex}].");
var credential = CredentialsManager.GetCredential(0) as ICredentialDescriptor;
var descriptor = credential.GetDescriptor((int)dwIndex);
_logger.Debug($"Returning descriptor of type [{descriptor.cpft}] with label [{descriptor.pszLabel}]");
int size = Marshal.SizeOf(descriptor);
IntPtr tempPtr = Marshal.AllocCoTaskMem(size);
//IntPtr tempPtr = Marshal.AllocHGlobal(size);
Marshal.StructureToPtr(descriptor, tempPtr, false);
Marshal.StructureToPtr(tempPtr, ppcpfd, false);
return HRESULT.S_OK;
}
catch (Exception ex)
{
_logger.Error(ex, $"{ex.Message}");
return HRESULT.E_UNEXPECTED;
}
catch
{
_logger.Error($"Uncaught exception");
throw;
}
finally
{
Diagnostics.LogMethodExit();
}
}
No error occures in this method but the GetBitmap raises an issue as seen in the WinDbg log
onecoreuap\ds\security\fido\credprov\dll\fidoprovider.cpp(62)\fidocredprov.dll!00007FFD731975AD: (caller: 00007FFD6E7AAC48) ReturnHr(2) tid(1010) 80070057 The parameter is incorrect.
onecoreuap\shell\auth\credprov2fahelper\dll\credprov2fahelper.cpp(80)\CredProv2faHelper.dll!00007FFD7A1C554A: (caller: 00007FFD6E7B3ACF) ReturnHr(1) tid(1010) 800704EC This program is blocked by group policy. For more information, contact your system administrator.
Msg:[Device unlock policy not configured]
AdviseGetCredentialCountGetCredentialAtGetFieldDescriptorCountGetFieldDescriptorAtGetDescriptorGetFieldDescriptorAtGetDescriptor(d98.1010): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
credprovhost!_GetBitmapData+0x44:
I have no clue why this is occuring. I'm actually testing both your provider and mine from the same solution with the same test client (CredUI) so i'm would at least expect both providers to act the same.
Any thoughts on this.
Regards,
Martijn
I am using your code and working on a Windows 10 Cred Provider, and I am having trouble with the CPUS_UNLOCK_WORKSTATION scenario. My CP simply serializes a Username and Password and logs the user in. This works in the CPUS_LOGON scenario, but I get a bad username and password in the CPUS_UNLOCK_WORKSTATION scenario.
According to MS docs (https://docs.microsoft.com/en-us/windows/desktop/api/credentialprovider/ne-credentialprovider-credential_provider_usage_scenario), "Credential providers that implement this scenario should be prepared to serialize credentials to the local authority for authentication. These credential providers also need to enumerate the currently logged-in user as the default tile."
How exactly do I do that? I think that the CredentialProviderBase:SetUserArray
is the place to do it, but I don't know how.
Any insight you can give would be appreciated. Thank you.
**EDIT: ** I also posted this issue in https://github.com/SteveSyfuhs/CredProvider.NET because truthfully I am using code from both repos.
hey, recently i tried testing this code on window server 12 with some changes. Like i added CPFT_EDIT_TEXT to get username and CPFT_PASSWORD_TEXT to get the password. This works fine on windows 11, 16 and 19 but on windows 2012 the CPFT_EDIT_TEXT isn't shown at all. any idea what am i missing here? Below is a snapshot from my WindowsCredentialProviderTile file
public List<_CREDENTIAL_PROVIDER_FIELD_DESCRIPTOR> CredentialProviderFieldDescriptorList = new List<_CREDENTIAL_PROVIDER_FIELD_DESCRIPTOR> {
new _CREDENTIAL_PROVIDER_FIELD_DESCRIPTOR
{
cpft = _CREDENTIAL_PROVIDER_FIELD_TYPE.CPFT_SMALL_TEXT,
dwFieldID = 1,
pszLabel = "Hello World",
},
new _CREDENTIAL_PROVIDER_FIELD_DESCRIPTOR
{
cpft = _CREDENTIAL_PROVIDER_FIELD_TYPE.CPFT_EDIT_TEXT,
dwFieldID = 2,
pszLabel = "Username",
},
new _CREDENTIAL_PROVIDER_FIELD_DESCRIPTOR
{
cpft = _CREDENTIAL_PROVIDER_FIELD_TYPE.CPFT_PASSWORD_TEXT,
dwFieldID = 3,
pszLabel = "Password",
},
new _CREDENTIAL_PROVIDER_FIELD_DESCRIPTOR
{
cpft = _CREDENTIAL_PROVIDER_FIELD_TYPE.CPFT_SUBMIT_BUTTON,
dwFieldID = 4,
pszLabel = "Login",
}
};
Hi,
Great to find a good extended example for Credential Providers. The info only is not always easy to find.
We are working on developing a custom credential provider. To test it we register the component for COM interop and add the regkey so it is show in CredUI.
Problem is that when we want to test the actual login the component is kept in use (by WinLogin probably) and builds for do not succeed as the file is in use. Is there way to free the component without unregistering and rebooting.
C:\testcp\c#_cp_new\TestCredentialProvider\TestCredentialProvider\midl>midl "C:\Program Files (x86)\Windows Kits\10\Include\10.0.22621.0\um\credentialprovider.idl"
Microsoft (R) 32b/64b MIDL Compiler Version 8.01.0628
Copyright (c) Microsoft Corporation. All rights reserved.
Processing C:\Program Files (x86)\Windows Kits\10\Include\10.0.22621.0\um\credentialprovider.idl
credentialprovider.idl
Processing C:\Program Files (x86)\Windows Kits\10\include\10.0.22621.0\shared\wtypes.idl
wtypes.idl
Processing C:\Program Files (x86)\Windows Kits\10\include\10.0.22621.0\shared\wtypesbase.idl
wtypesbase.idl
Processing C:\Program Files (x86)\Windows Kits\10\include\10.0.22621.0\shared\basetsd.h
basetsd.h
Processing C:\Program Files (x86)\Windows Kits\10\include\10.0.22621.0\shared\guiddef.h
guiddef.h
Processing C:\Program Files (x86)\Windows Kits\10\include\10.0.22621.0\um\shobjidl_core.idl
shobjidl_core.idl
Processing C:\Program Files (x86)\Windows Kits\10\include\10.0.22621.0\um\objidl.idl
objidl.idl
Processing C:\Program Files (x86)\Windows Kits\10\include\10.0.22621.0\um\unknwn.idl
unknwn.idl
Processing C:\Program Files (x86)\Windows Kits\10\include\10.0.22621.0\um\shtypes.idl
shtypes.idl
Processing C:\Program Files (x86)\Windows Kits\10\include\10.0.22621.0\um\servprov.idl
servprov.idl
Processing C:\Program Files (x86)\Windows Kits\10\include\10.0.22621.0\um\comcat.idl
comcat.idl
Processing C:\Program Files (x86)\Windows Kits\10\include\10.0.22621.0\um\propsys.idl
propsys.idl
Processing C:\Program Files (x86)\Windows Kits\10\include\10.0.22621.0\um\oleidl.idl
oleidl.idl
Processing C:\Program Files (x86)\Windows Kits\10\include\10.0.22621.0\um\ocidl.idl
ocidl.idl
Processing C:\Program Files (x86)\Windows Kits\10\include\10.0.22621.0\um\oaidl.idl
oaidl.idl
Processing C:\Program Files (x86)\Windows Kits\10\include\10.0.22621.0\um\urlmon.idl
urlmon.idl
Processing C:\Program Files (x86)\Windows Kits\10\include\10.0.22621.0\um\msxml.idl
msxml.idl
Processing C:\Program Files (x86)\Windows Kits\10\include\10.0.22621.0\um\StructuredQueryCondition.idl
StructuredQueryCondition.idl
Processing C:\Program Files (x86)\Windows Kits\10\include\10.0.22621.0\um\propidl.idl
propidl.idl
Processing C:\Program Files (x86)\Windows Kits\10\include\10.0.22621.0\um\ObjectArray.idl
ObjectArray.idl
Processing C:\Program Files (x86)\Windows Kits\10\include\10.0.22621.0\um\oaidl.acf
oaidl.acf
Processing C:\Program Files (x86)\Windows Kits\10\include\10.0.22621.0\um\ocidl.acf
ocidl.acf
C:\Program Files (x86)\Windows Kits\10\include\10.0.22621.0\um\shobjidl_core.idl(1745) : error MIDL2455 : The feature cannot be used on the target system : disable_consistency_check [ Parameter 'apt' of Procedure 'SelectAndPositionItems' ( Interface 'IFolderView' ) ]
C:\testcp\c#_cp_new\TestCredentialProvider\TestCredentialProvider\midl>
Hi, It's just a question no bug report.
I need to create custom provider which login by SmartCard.
I already checked https://docs.microsoft.com/en-us/windows/win32/api/wincred/nf-wincred-credpackauthenticationbuffera and call CredMArshalCredential but sill have problem.
Thanks in advance.
Hi @phaetto, I was searching for a Pre-Logon Access Provider for OpenVPN, but did not found any and there isn't any example for this kind of provider. :(
On the OpenVPN GUI Client (OpenVPN/openvpn-gui#77 (comment)) it seems that nobody knows how to implement this. Could you give them some hints how they cold do it? Thanks! :)
Thanks for this sample, It's just a question no bug report.
Is it possible to trigger the authentication by Api?
I saw your sample and shows the Prompt, Actually I want to call the custom provider directly by Api, no user click or any action from user.
Thanks in advance.
Hey how can i support password reset in the custom credential provider i have built which overrides the login screen?
This is where we receive credential through RDP
public int UpdateRemoteCredential(ref _CREDENTIAL_PROVIDER_CREDENTIAL_SERIALIZATION pcpcsIn, out _CREDENTIAL_PROVIDER_CREDENTIAL_SERIALIZATION pcpcsOut)
{
ShowInfo showInfo = new ShowInfo();
showInfo.ShowMessage("RDP Filter -> UpdateRemoteCredential");
pcpcsOut = pcpcsIn;
pcpcsOut.clsidCredentialProvider = new Guid(Constants.CredentialProviderUID);
this.rdp_login = true;
return HResultValues.S_OK;
}
After this, in SetSerialization
public int SetSerialization(ref _CREDENTIAL_PROVIDER_CREDENTIAL_SERIALIZATION pcpcs)
{
Log.LogMethodCall();
ShowInfo showInfo = new ShowInfo();
showInfo.ShowMessage("SetSerialization");
my_pcpcs = pcpcs;
my_pcpcs.clsidCredentialProvider = Guid.Parse(Constants.CredentialProviderUID);
this.rdp_login = true;
return HResultValues.S_OK;
}
After this, in GetCredentialCount
public int GetCredentialCount(out uint pdwCount, out uint pdwDefault, out int pbAutoLogonWithDefault)
{
Log.LogMethodCall();
pdwCount = 1; // Credential tiles number
pdwDefault = unchecked ((uint)0);
//pbAutoLogonWithDefault = 0; // Try to auto-logon when all credential managers are enumerated (before the tile selection)
if (this.rdp_login)
{
pbAutoLogonWithDefault = 1;
ShowInfo showInfo = new ShowInfo();
showInfo.ShowMessage("GetCredentialCount");
}
else
{
pbAutoLogonWithDefault = 0;
}
return HResultValues.S_OK;
}
This will invoke GetSerialization
if (this.rdp_login)
{
showInfo.ShowMessage("GetSerialization for RDP");
//pcpcs = my_pcpcs;
pcpcs = new _CREDENTIAL_PROVIDER_CREDENTIAL_SERIALIZATION();
pcpcs.clsidCredentialProvider = my_pcpcs.clsidCredentialProvider;
pcpcs.rgbSerialization = my_pcpcs.rgbSerialization;
pcpcs.cbSerialization = my_pcpcs.cbSerialization;
//RetrieveNegotiateAuthPackage(out var authPackage);
pcpcs.ulAuthenticationPackage = my_pcpcs.ulAuthenticationPackage;
pcpgsr = _CREDENTIAL_PROVIDER_GET_SERIALIZATION_RESPONSE.CPGSR_RETURN_CREDENTIAL_FINISHED;
ppszOptionalStatusText = "RDP Success";
pcpsiOptionalStatusIcon = _CREDENTIAL_PROVIDER_STATUS_ICON.CPSI_SUCCESS;
return HResultValues.S_OK;
}
After this, when we try to login via RDP (mstsc.exe) unable to unlock the workstation getting error as "Invalid Token"
Hello Pheatto/Alexander
Nice article. But, mine is not an issue
I have considerable experience in C# but have never worked on a credentials provider.
And it has been some time since my last C# app after having shifted to mobile app development. So, I need your help to build and run this code on my computer for a project I need to work on.
Which code/project should I run? Or is just build and get a DLL and run from somewhere?
I know my request sounds kind of trivial but can you help me? I will be very thankful to you for this.
Best
Srishu
Hi phaetto,
I tried your code and turn on the auto login function.
It can login to the system after 5 seconds. However, after another 5 seconds, it will return to the login page again.
"TestWindowsCredentialProvider: Created object" is displayed multiple times, causing the timer created multiple.
Hello there, great product:
I am using CredentialProvider to develop my custom login method,After my research,the Credential Provider seems to require the user's original Windows password. my question is : Is the Credential Provider have to know the original Windows password, and pass it to the operating system for verification, Otherwise the user cannot log in successfully?
Hi,
Thanks for this sample!!. However I encountered some issues in your demo.
I added username and password in loginUI
public List<_CREDENTIAL_PROVIDER_FIELD_DESCRIPTOR> CredentialProviderFieldDescriptorList = new List<_CREDENTIAL_PROVIDER_FIELD_DESCRIPTOR> {
new _CREDENTIAL_PROVIDER_FIELD_DESCRIPTOR
{
cpft = _CREDENTIAL_PROVIDER_FIELD_TYPE.CPFT_SMALL_TEXT,
dwFieldID = 0,
pszLabel = "Rebootify Awesomeness",
},
new _CREDENTIAL_PROVIDER_FIELD_DESCRIPTOR
{
cpft = _CREDENTIAL_PROVIDER_FIELD_TYPE.CPFT_EDIT_TEXT,
dwFieldID = 1,
pszLabel = "Sample UserName",
guidFieldType =Guid.Parse("da15bbe8-954sd-4fd3-b0f4-1fb5b90b174b")
//GUID has 33 character so runtime error. This Guid get from https://docs.microsoft.com/en-us/windows/desktop/api/credentialprovider/ns-credentialprovider-credential_provider_field_descriptor
},
new _CREDENTIAL_PROVIDER_FIELD_DESCRIPTOR
{
cpft = _CREDENTIAL_PROVIDER_FIELD_TYPE.CPFT_PASSWORD_TEXT,
dwFieldID = 2,
pszLabel = "Sample Password",
guidFieldType =Guid.Parse("60624cfa-a477-47b1-8a8e-3a4a19981827")
},
new _CREDENTIAL_PROVIDER_FIELD_DESCRIPTOR
{
cpft = _CREDENTIAL_PROVIDER_FIELD_TYPE.CPFT_SUBMIT_BUTTON,
dwFieldID = 3,
pszLabel = "Login",
}
};
If i added a new field other than CPFT_SMALL_TEXT, then Rebootify option is not listing login UI(without guidFieldType field).
I added guidFieldType for user name(microsoft doc providing incorrect GuID) and password but still its not work. Also i trying without username field, only password (bcz username guidFieldType is incorrect) but still the result is same Rebootify option is not listing login UI.
Also one more point, in GetSerialization method i need to use 3rdparty IAM service, is it possible. then how to i create _CREDENTIAL_PROVIDER_CREDENTIAL_SERIALIZATION?
Any help on this would be greatly appreciated.
how can I show this credential provider as an option in for sign-in in windows 10
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.