If you’ve ever had an experience with Credential Providers in the past, you may think the title of this post is insane — it’s not.

I recently came across an interesting Github project that showed it was theoretically possible. I wanted to see if I could replicate the results myself without digging too deeply into how they did it. As it happens, I could.

I created a sample project that outlines how you can do it on Github: CredProvider.NET

.NET Credential Provider

Historically, Credential Providers have been complex components to write because they’re COM-based, and because they have weird restrictions you have to contend with since they run in the winlogon UI process. Both of these restrictions should make any sane developer run away — doubly so if you’re a .NET developer. However, if you’ve been around long enough, you may remember that COM-interop thing that makes it possible to call .NET code from COM components (and conversely, call COM components from .NET) and have the runtime do a whole host of evil to keep the two relatively stable.

The trick with interop is getting the interfaces right. Everything communicates through interfaces — it’s the only way to guarantee a stable contract between APIs. This is the crux of our implementation. You can codify them manually through MSDN definitions, but that’s error prone and not necessarily completely accurate. Thankfully, the Windows SDK contains an IDL file that defines the interfaces we need. All we need to do is convert them to something .NET understands. We do this in a two step process where we first compile the IDL to a type library, and then convert the type library to a .NET assembly.

You can compile a type library using the midl.exe tool. You’ll need to install the Windows SDK first though, otherwise you won’t have the IDL file.

midl "C:\Program Files (x86)\Windows Kits\10\Include\10.0.16299.0\um\credentialprovider.idl" 
-target NT62 /x64

You can see I’m using the latest 10.0.16299.0 build of the SDK. This particular version requires you explicitly target a version for some reason — older versions of this IDL don’t require the targeting.

This produces a few files, but most notably is the credentialprovider.tlb file. This is the type library. We need to convert this to an assembly. Normally, you’d just use tlbimp.exe, but it’s notoriously opinionated on how you talk to COM, leaving you stuck in a few ways (for instance, it expects you to throw exceptions instead of returning HRESULTs, despite the interface requiring you to return HRESULTs). It turns out the CLR Interop team built a set of tools to help you through this pain — specifically tlbimp2.exe (why they didn’t just ship this capability in the original tool is a mystery).

TlbImp2.exe credentialprovider.tlb /out:CredProvider.NET.Interop.dll 
/unsafe /verbose /preservesig namespace:CredProvider.NET

The key is the /preservesig parameter.

Once you’ve created the assembly, you can import it into a project and start creating your credential provider.

Credential Providers are made up of two core interfaces:

  • ICredentialProvider — Manages the interaction between the UI
  • ICredentialProviderCredential — tells the UI how to receive credentials from the user

There are a few related interfaces, but they are just there to enhance the capabilities of the credential provider. Once you implement your interfaces you need to decorate the class with some attributes to tell what’s exposed as COM implementations:

You only need to do this on the ICredentialProvider interface.

At this point you may notice a few annoying things. First, not all the interfaces are present in the assembly. A few interfaces were added in the Windows 8.0 timeframe, specifically the ICredentialProviderCredential2 interface, that allows you to follow the newer design guidelines. Second, some of the typedef’s don’t translate correctly. For instance, HBITMAP gets mangled. Fixing these issues requires a little surgery on the credentialprovider.idl file.

First, you need to move the library declaration to the beginning of the file. It’s already present somewhere in the middle of the file (search “library CredentialProviders”). Just move it to the beginning of the file so it includes all the extra interfaces. Second, find and replace any mangled pointer to HANDLE (e.g. HBITMAP* to HANDLE*). Now you’ll need to recompile with midl, and regenerate the library with tlbimp2.

You can see how I did it with this diff.

Unrelated, but you may notice a number of things were taken out. This is because I modified the file without making a backup (doh!), and had to search for the original online and could only find the first release (I suppose I could have just reinstalled the SDK, but that’s beside the point). Anyway, notice how there’s an ICredentialProviderCredential3? I suspect that’s how Windows Hello does the eye-of-Sauron graphic when it’s looking for you.

Windows Hello

You may also want to explicitly register for COM interop on build too. This will make the provider available on each build, but the downside is that it requires running Visual Studio as admin.

Register for COM interop

You need to tell Windows you’ve got a Credential Provider once it’s registered. You do this by adding it to the registry.

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Authentication\Credential Providers\{00006d50-0000-0000-b090-00006b0b0000}]
@=”Credential Provider.NET”

Notice that the GUID matches the Guid in the class attribute. This is intentional. This tells Windows that the COM component with that given guid is a Credential Provider, and it should new-up an instance of it.

The other thing you’ll want to figure out is how to test this thing. You’ll notice all the images above show it being used within a user session, prompted via CredUIPromptForWindowsCredentials. This is intended because testing it on your own machine’s winlogon interface is an exercise in madness. Unhandled errors that cause your provider to crash will render the logonUI unusable and, well, you’re screwed. You have to boot into safe mode and remove the provider registration, but the provider is still loaded so you can’t log into safe mode! So you need to boot into recovery mode, and… — have you made a recovery image? Using CredUIPromptForWindowsCredentials will let you test your code easily and quickly, and it generally behaves like winlogon. Lastly, test it on a VM once it’s ready for more in depth testing.

And that’s all it takes to start writing a Credential Provider in .NET.

Some Notes

It’s worth noting that this is possibly (probably?) a bad idea. I don’t know how stable this will be in the wild.

Some References

I came across this Stack Overflow post in my attempts to figure out the ICredentialProviderCredential2 problem, which lead to this sample. Their recommendation to use tlbimp2 was a huge revelation.

68 Comments

  1. John Moline

    Steve,

    Thank you for the article. I am also exploring how to create custom credential providers for Windows 7 and 10. Question for you, please: How can I create a custom credentials ui that I can invoke when one of the tile buttons is clicked at the login screen? Any ideas? Thanks ahead of time.

    Reply
    • What sort of UI do you mean? Clicking the tile raises the advise event, which you can use to trigger UI changes like changing fields. Alternatively, if that doesn’t get you enough customization, you can always pop up a Window of some sort that renders whatever you want. Though I don’t recommend doing that, because it breaks design guidelines.

      Reply
      • John Moline

        Steve, thanks for the quick response.

        So in your demo, you appear to be calling one of the prompts that comes from credui.dll. I do know that you can change the text in these features, etc. This is totally clear to me.

        What I am thinking about is this: With my custom credential provider installed, it will invoke a custom ui “pop-up” or dialog instead of the prompt within credui.dll. Can I build this dialog in .NET and invoke it from the credential provider when the user is not logged in yet? Does a .NET app have this capability to exist outside of the login screen? If not, what options do you think I should try.

        Thanks again for the advice.

        Reply
        • Ah, I think I understand. You can certainly pop up a custom UI from the login screen. I fiddled with doing this using a basic .NET Forms Window class, so presumably you can use pretty much whatever you want. You can also launch a custom app as well, but then you have to communicate back to the credential provider that you have credentials.

          You also have to be careful because the logon UI often ends up as the topmost window, so you need to anchor it properly otherwise you risk your window getting stuck behind.

          Reply
          • John Moline

            Thanks Steve. Is it possible if you can point me in the direction on how the credential provider tile will launch the custom UI? I don’t see any documentation on how to do this today?

          • John Moline

            Steve, do you have any feedback from the question I mentioned from last Friday? Is there something specific that I need to do to launch an EXE from outside of the login screen? If the session was already logged in, I understand how to launch a new process but this is different. Any ideas or pointers on what I would need to do to launch this custom UI from the credential provider tile? Again, I do appreciate any feedback. Thanks.

          • Programmatically it’s the same via CreateProcess() or the .NET Process.Start() call. Otherwise you can’t really start a process any other way from within the logon UI.

            The environment is fairly similar to a normal session, with the caveat that you’re running as system, so you can do lots of dangerous things.

          • John Moline

            Ok, understood. I appreciate you following up. Thank you for the information.

  2. Steve, thank your for this article. I am working on a credential-provider in C# and I suspect that a parameter in a method should be of an ‘out’-parameter but it isn’t in it’s interface.
    I’m talking about the GetBitmap() method that, as I understand, is called to get a IntPtr to an Bitmap-image. This IntPtr should be an out-parameter, I think. Please have look at my question: https://stackoverflow.com/questions/47835715/what-is-the-c-sharp-equivalent-of-this-c-code-with-inptr

    I’m working with CredentialProvider.Interop.dll created by someone else but I just recreated it with your steps. When I browse the classes in the .DLL I can clearly see that the parameter is not an ‘out’-parameter. Is it possible that this parameter is created wrong in the above steps?
    Thanks for your help!
    Robert

    Reply
      • Thanks for your quick reply!
        We are building it on Windows 10, version with these commands (and others of course):

        midl “C:\Program Files (x86)\Windows Kits\10\Include\10.0.16299.0\um\credentialprovider.idl” -target NT62 /x64

        C:\code54\Code54\Interop\TlbImp2.exe “C:\Users\testa\source\credentialprovider.tlb” /out:”C:\Users\testa\source\CredProvider.NET.Interop.dll” /unsafe /verbose /preservesig namespace:CredProvider.NET

        Maybe a stupid question but is there a way to just download the DLL with the correct out-parameter?
        Thanks a lot!
        Robert

        Reply
          • Great Steve,

            I really appreciate this and I’m going to test if this solves the issue with the out-parameter.

            Best,
            Robert

        • Interesting! I tried going down that route but never got it working safely. I’ll have to give this a try!

          Reply
  3. Max

    Hi Steve,

    first of all thank you for this great tutorial.
    Somehow when i run the project only the default windows login (user, password) is displayed.
    Do you have an idea what i did wrong? (The registry entry is existing)

    Best regards
    Max

    Reply
    • A couple things to check out…

      1. Did the assembly get registered correctly? The checkbox needs to be set in the project, and you need to be running as admin for it to register. You may have to run a full solution rebuild for it to take effect. Alternatively you need to register it manually using something like regasm.exe.

      2. Are you on a 32 bit build on Windows? This is currently targeted at 64 bit only. You can probably rebuild as 32 bit without issue, but it’s not been tested.

      3. This is based on a Windows 10 IDL, so you might have trouble on older builds of Windows, like 7 or 8. You could potentially try recreating the dependent assemblies using an older SDK.

      4. Are you seeing any output in the console window at all? If nothing at all, that would indicate the classes never got instantiated. If you ARE seeing output, try forcing the cred UI to redraw by moving it around on screen, collapsing the window, etc.

      Reply
      • Max

        1.) Yes the checkbox is set.
        2.) Im on 64bit
        3.) Im using Win 10
        4.) The console out put is:
        18-01-15 12:24:42Z [CredentialProvider.Initialize] cpus: CPUS_CREDUI; dwFlags: 0
        2018-01-15 12:24:42Z [CredentialProviderBase.SetUserArray] count: 0; options: CPAO_EMPTY_LOCAL
        2018-01-15 12:24:42Z [CredentialProviderBase.Advise] upAdviseContext: 1
        2018-01-15 12:24:42Z [CredentialProviderBase.GetCredentialCount]
        2018-01-15 12:24:42Z [CredentialProviderBase.GetCredentialAt] dwIndex: 0
        2018-01-15 12:24:42Z [CredentialView.GetField] dwIndex: 0; descriptors: 4
        2018-01-15 12:24:42Z [CredentialView.GetField] dwIndex: 1; descriptors: 4
        2018-01-15 12:24:42Z [CredentialView.GetField] dwIndex: 2; descriptors: 4
        2018-01-15 12:24:42Z [CredentialView.GetField] dwIndex: 3; descriptors: 4
        2018-01-15 12:24:42Z [CredentialProviderCredential.GetBitmapValue] dwFieldID: 0
        2018-01-15 12:24:42Z [CredentialProviderCredential.GetFieldState] dwFieldID: 0
        2018-01-15 12:24:42Z [CredentialProviderCredential.GetStringValue] dwFieldID: 1
        2018-01-15 12:24:42Z [CredentialProviderCredential.GetFieldState] dwFieldID: 1

        Also moving the window didn’t helped. Resizing is not possible.

        We had changed requirements in our project so i stopped trying further. But if i have time i will try it later with an older SDK.

        Thanks a lot for your help.

        Reply
        • Hmm. It’s loading the provider into Cred UI as part of the Initialize() call. Can you confirm it’s not showing up in the collapsed More Choices list below the selected provider?

          Otherwise, I vaguely remember having a similar issue once, but I don’t recall the voodoo that fixed it other than trying to force a redraw. I don’t think it was a coding change.

          I don’t think rebuilding against an older SDK will be necessary in this case because it’s loading the provider, and all we need the SDK for is getting the interfaces right.

          It looks like the log you posted is cut off after GetFieldState for id 1. Is this just a subset of the log, or is that the last thing that shows up in the console? It *should* have a bunch of stuff after that, which indicates it might be breaking while trying to load the password field, which is dwFieldID 2.

          2018-01-15 17:58:22Z [CredentialProvider.Initialize] cpus: CPUS_CREDUI; dwFlags: 0
          2018-01-15 17:58:22Z [CredentialProviderBase.SetUserArray] count: 0; options: CPAO_EMPTY_LOCAL
          2018-01-15 17:58:22Z [CredentialProviderBase.Advise] upAdviseContext: 1
          2018-01-15 17:58:22Z [CredentialProviderBase.GetCredentialCount]
          2018-01-15 17:58:22Z [CredentialProviderBase.GetCredentialAt] dwIndex: 0
          2018-01-15 17:58:22Z [CredentialView.GetField] dwIndex: 0; descriptors: 4
          2018-01-15 17:58:22Z [CredentialView.GetField] dwIndex: 1; descriptors: 4
          2018-01-15 17:58:22Z [CredentialView.GetField] dwIndex: 2; descriptors: 4
          2018-01-15 17:58:22Z [CredentialView.GetField] dwIndex: 3; descriptors: 4
          2018-01-15 17:58:22Z [CredentialProviderCredential.GetBitmapValue] dwFieldID: 0
          2018-01-15 17:58:22Z [CredentialProviderCredential.GetFieldState] dwFieldID: 0
          2018-01-15 17:58:22Z [CredentialProviderCredential.GetStringValue] dwFieldID: 1
          2018-01-15 17:58:22Z [CredentialProviderCredential.GetFieldState] dwFieldID: 1
          2018-01-15 17:58:22Z [CredentialProviderCredential.GetStringValue] dwFieldID: 2
          2018-01-15 17:58:22Z [CredentialProviderCredential.GetFieldState] dwFieldID: 2
          2018-01-15 17:58:22Z [CredentialProviderCredential.GetStringValue] dwFieldID: 3
          2018-01-15 17:58:22Z [CredentialProviderCredential.GetFieldState] dwFieldID: 3
          2018-01-15 17:58:22Z [CredentialProviderCredential.GetUserSid] Identity: …snip…
          2018-01-15 17:58:22Z [CredentialProviderCredential.Advise]
          2018-01-15 17:58:22Z [CredentialProviderCredential.Advise] pcpce is ICredentialProviderCredentialEvents2
          2018-01-15 17:58:23Z [CredentialProviderCredential.SetSelected]
          2018-01-15 17:58:23Z [CredentialProviderCredential.GetSerialization]
          2018-01-15 17:58:23Z [CredentialProviderCredential.SetDeselected]

          One annoying thing about how this is coded is that these calls don’t do a good job of handling errors. The logger doesn’t always pick them up, so it could be failing and just silently moving on to the next provider. Also, debugging is kind of a pain so you might try sticking log lines into various spots to narrow down where it might be failing.

          Reply
  4. Catana Simona

    Hi Steve,

    Great article! I managed to make a credential provider C# which partially suits my needs. However, I bumped into a problem. I want
    to display an image at a certain point, by using the method SetFieldBitmap. The problem is that the third parameter expected by the
    method should be of type _userHBITMAP

    namespace CredProvider.NET.Interop2
    {
    [SuppressUnmanagedCodeSecurity]
    public struct _userHBITMAP
    {
    public int fContext;
    public __MIDL_IWinTypes_0007 u;
    }
    }

    Method signature:
    int SetFieldBitmap(ICredentialProviderCredential pcpc, uint dwFieldID, [ComAliasName(“CredProvider.NET.Interop2.wireHBITMAP”)] ref _userHBITMAP hbmp);

    I got the IntPtr from the Bitmap, and then I tried to obtain the _userHBITMAP but without success (I get an AccessViolationException). Please see the following code:
    var hbitmap = bitmat.GetHbitmap();
    var finalBitmap = (_userHBITMAP)Marshal.PtrToStructure(intt, typeof(_userHBITMAP));
    pcpce.SetFieldBitmap(this, (uint)FIELD_ID.FI_TILEIMAGE, finalBitmap);

    GetBitmapValue works fine because it expects an IntPtr.

    I am totally lost… Could you please give me a suggestion regarding how this should be done?

    Thank you very much,
    Simona

    Reply
    • Catana Simona

      Hi,
      I have managed to resolve the issue by modifying the .idl file: changed the third parameter of SetFieldBitmap from HBITMAP to HANDLE, then created the tlb file and then the assembly.
      By doing that, I was able to use the variable hbitmap, obtained from
      var hbitmap = bitmap.GetHbitmap();
      as a parameter for the SetFieldBitmap method.

      Best regards,
      Simona

      Reply
      • Yep, this is the correct solution. You fixed it before I even had a chance to see your first comment! 🙂

        Reply
  5. Catana Simona

    Hi Steve,

    I come back to you with some other question :). In my credential provider the user has to enter:
    – some credential information sent to a server (these are not the ones stored on the PC, but are some credentials stored on a database on the server side)
    – a number received from a server which will be verified on the credential provider side
    – currently also the password associated to the account of the user the credential provider targets (these are used in GetSerialization method)

    My question is … do you know if there is a way to skip the 3rd step but still login successfully on the targeted account? I would like to not enter the password at all. Because the success of the first 2 steps guarantees me that the user is the right one. I read that there is a way of prestoring the password, but this does not cover the situation in which the password changes.

    Any suggestion would be greatly appreciated.

    Thanks,
    Simona

    Reply
    • There’s really no good or safe way to do this. The Credential Provider is just way to ferry the creds into a authentication package (e.g. Negotiate, Kerberos, NTLM) which then does the actual auth locally against the SAM, or against AD. The result from that process is what actually lets you sign in. Given that, you’d need a custom authentication package to do this, and then you’d need to figure out the AD scenario.

      Reply
      • Catana Simona

        I understand. Thank you for the information!

        Reply
  6. Jason

    Hi Steve, thank you for posting this excellent article. I’ve tried to do work the project in windows 10 x64, but I couldn’t. I thought that the only step I needed to do was register the dll, through the install.reg file, and copy all files from the x64 folder into system32 folder. But after do that, nothing happened in the logon screen. So, what am I doing wrong, please?

    Reply
    • I think you will also need to register it as a COM component with regasm. This is what the VS build does behind the scenes.

      Reply
  7. Jason

    Hello Steve, thank you so much for your response. I’ve tried what you said me, but nothing happened. I registered the CredProvider.NET.dll as a COM component with regasm (C:\Windows\Microsoft.NET\Framework64\v4.0.30319\RegAsm.exe “C:\Windows\System32\CredProvider.NET.dll” /tlb /codebase) and then I executed the register.reg file. Also I enabled the option “Interactive Logon: Do not require Ctrl+Alt+Del” in the local security policies and enabled the option “Do not display the lock screen” in the Administrative Templates.
    Please, some help, is there any place where I can see a log file? I don’t know if the library is loaded properly or not.
    Thank you.

    Reply
    • Are you trying to get this to show up on the winlogon screen? It definitely will NOT do that in it’s current state because it would lock you out of the machine. Currently it’ll only show up through a CredUI prompt like in the test app. If you run it, you’ll see the logs dump to the console window.

      What you’d need to do is change the usage scenario to include unlock/logon: https://github.com/SteveSyfuhs/CredProvider.NET/blob/master/CredProvider.NET/CredentialProvider.cs#L63

      Keep in mind that if you do change it, you may end up in a hosed state if the provider doesn’t load for whatever reason, and you’ll have to manually remove the provider from the registry.

      Reply
      • Jason

        Hello Steve, thank you so much for your response. Indeed, I’m trying what you say. I don’t have achieved do it changing the method what you indicated, but taking this example https://github.com/phaetto/windows-credentials-provider, and changing some aspects, I finally did it!
        Thank you.
        Regards.

        Reply
        • Matko

          Hi, what exact changes are needed except changing supported scenarios? I did all the above and on windows lock screen I still have standard login and options.

          Reply
  8. Marc

    Hello Steve, thanks also for providing this sample project. I am up to actually MIDL’ing the credentialprovider.idl and have got pass several hurdles, but it is trying to compile the oaidl.idl, which I have extended the command line to find, but is giving me the following error:

    oaidl.idl(29) : error MIDL2025 : syntax error : expecting an interface name or DispatchInterfaceName or CoclassName or ModuleName or LibraryName or ContractName or a type specification near “ifndef”.

    The command line I am using is:

    midl “C:\Projects\IdentityCheckpoint\VS2017\CredentialProvider\CPTypeLib\Credentialprovider.idl” -target NT62 /x64 /no_cpp /I “C:\Program Files (x86)\Microsoft SDKs\Include”

    I started by using the current 10.0.16299.0 version of the file, but went back to the 10.0.10586.0 version as a test ending with the same results.

    Did MIDL include oaidl.idl during your compiles? Is there another argument I need to pass?

    Reply
  9. Marc

    Steve, Thanks for providing the sample project. I am trying to MIDL the “credentialprovider.idl” and have got past several of the curdles in doing so. MIDL however is trying to include oaidl.idl for some reason. As a result I modified the command line in enable it to find it:

    midl “C:\Projects\IdentityCheckpoint\VS2017\CredentialProvider\CPTypeLib\Credentialprovider.idl” -target NT62 /x64 /no_cpp /I “C:\Program Files (x86)\Microsoft SDKs\Include”

    I am using the current 10.0.16299.0 SDK version of it as well as the “credentialprovider.idl” and MIDL, just relocated it to the path with its associated files. As result MIDL is finding it and starting the compile, but issuing this error:

    oaidl.idl(29) : error MIDL2025 : syntax error : expecting an interface name or DispatchInterfaceName or CoclassName or ModuleName or LibraryName or ContractName or a type specification near “ifndef”

    >>#ifndef DO_NO_IMPORTS
    >>import “objidl.idl”;
    >>#endif

    Did your compiles include the “oaidl.idl” file? Is there an argument that I need to be setting? An “interface name”?

    Reply
    • Marc

      Sorry about the double comment postings, but I got an error message when I went to post the first comment and it didn’t initially appear until after I post this comment.

      Reply
    • Are you using the IDL file provided in the midl folder of the GitHub project, or are you grabbing it from the SDK? If you’re grabbing it from the SDK, you have to make a couple tweaks to it. Check out the diff here: https://github.com/SteveSyfuhs/CredProvider.NET/commit/340caafefdc76e17dbf4c2ea18bfdd38bdd5ca37#diff-ad16ca0a002fbf602b9a3d01b02ee767

      One other thing of interest. You’re targeting /x64, but passing the (x86) include path. This might be picking up the wrong version of the include files.

      Reply
      • Marc

        I followed your modifications at the beginning of my efforts and tweaked the IDL as directed as I wanted to see the tweaks. I just tried using your IDL version with the MIDL command as you documented, “midl “C:\Projects\IdentityCheckpoint\VS2017\CredentialProvider\CPTypeLib\Credentialprovider.idl” -target NT62 /x64″ and experienced MIDL complaining that it couldn’t find the “oaidl.idl” file, “midl : command line error MIDL1001 : cannot open input file oaidl.idl”.

        The include path I had created and had copied the “oaidl.idl” there from the Windows 10 SDK at “C:\Program Files (x86)\Windows Kits\10\Include\10.0.16299.0\um”. To hopefully eliminate potential problems of finding the designated imports in the “oaidl.idl” file, I changed the include path to be the same as that for MIDL, resulting in the command “C:\Program Files (x86)\Windows Kits\10\bin\10.0.16299.0\x64>midl “C:\Projects\IdentityCheckpoint\VS2017\CredentialProvider\CPTypeLib\Credentialprovider.idl” -target NT62 /x64 /no_cpp /I “C:\Program Files (x86)\Windows Kits\10\Include\10.0.16299.0\um”. Same results; failing at the “#ifndef DO_NO_IMPORTS” line.

        Reply
        • Marc

          Did your compiles include the “oaidl.idl” file?

          Reply
          • Marc

            I meant that I changed the include path to be the same as that for imports where it originally was located.

  10. Marc

    I took an even more drastic direction and moved MIDL and all of its related apps and libraries into the SDK folder containing the IDLs, including replacing the credentialprovider.idl with yours so that MIDL didn’t have to go searching for anything and inclusion. After responding to the subsequent error messages and gaining, my activities lead to eventually discovering that what I really needed was to have been in the Developers Command Prompt to perform this work.

    I now have my .h, .tlb and .c files.

    Reply
    • Marc

      After rebuilding tlbimp2 from the MIT project to operate on my machine, stopping the “System.BadImageFormatException” errors I was getting when trying to run the download version, I am now able to build my CredProvider.NET.Interop.dll. However, I am getting the following warnings; should I ignore them?

      TlbImp : warning TI3015 : At least one of the arguments for ‘CredProvider.NET.Interop.ICredentialProviderCredentialEvents2.OnCreatingWindow’ cannot be marshaled by the runtime marshaler. Such arguments will therefore be passed as a pointer and may require unsafe code to manipulate.
      TlbImp : warning TI3016 : The type library importer could not convert the signature for the member ‘CredProvider.NET.Interop.tagBSTRBLOB.pData’.

      Reply
      • Sorry, I should have made it clear that you need the developer prompt, and the right CPU to match whatever you’re building. The BadImageFormatException tends to happen when you’re running an x64 build on an x86 machine.

        As for the actual warning, you’re probably fine unless you actually use the OnCreatingWindow callback, which is not necessary in most scenarios. I didn’t make any changes to account for it, and it still works.

        Reply
        • Hackeitos

          I can’t create the assembly, I have an x64 system and it throws me the BadImageFormatException anyways. Some fix?

          Reply
  11. Marc

    Steve,

    1. Are the credential providers invoked after the traditional login if they are not PLAP’s? I.e. is the UserID available?

    2. Is it necessary for a credential provider to provide tiles or have a UI, i.e. just interact with a device, server or service?

    3. If the machine is setup for general network access, is it enabled at the time the credential provider is invoked? (I think I read it was, just the network connections unique to the user haven’t be completed.)

    Thanks again for the sample project, as it demonstrates how to code for the COM interactions in C#!!!

    Reply
    • 1. Which Id? In remote connections you’d get access to the credentials presented through NLA. You can wrap an existing Credential Provider, so it does all the work to get the Id, but otherwise you have full control over the credential lifecycle.

      2. Not specifically. You’d want to wrap an existing provider if you don’t want to touch UI. Otherwise you need to go really deep using an SSP, where it presents credentials for processing. But that would need to be written in C/C++.

      3. Yes, this is correct. PLAP’s are intended to help initiate the per-session connections, but system-wide connections are already available.

      Reply
  12. Marc

    I am referring to the traditional local NLA Domain/UserId which can be obtained using GetloggedinUserName(). Does a CP override Windows logon or supplement it? If the former, I assume you can wrap it so the NLA is completed?

    Looking at my registry, beneath HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Authentication\Credential Providers\ there are numerous GUID keys, all of which seem by content to be a CP. What are they?

    And in the key itself, I have a string entry of “2FAHelper” with a GUID listed. What is its relationship to the authentication process? Doing a quick search, it appears that it is related to Azure multi-factor.

    Finally, when I add your GUID to the registry, am I adding it beneath with the other keys, or directly to key the same as “2FAHelper”?

    Reply
  13. I guess you would say that it can do both. It’ll handle the credentials presented by NLA, but you’re not logged in as that user yet, or you can provide you let the user provide their own credentials.

    The GUIDs are for different credential providers. They handle various scenarios. I don’t know what they all do.

    I also don’t know what the 2FAHelper value is for.

    You would add the GUID as a key \Credential Providers\.

    Reply
  14. Steve,

    Hello and thank you for the example. We have a custom Gina and Credential provider for our software “XyLoc” that we’ve written in C++ with the UI written in pure win32. Im aiming to redo the interface using WPF, but im having some issues with the sample here. I cannot seem to get your sample UI to load. Is this a 32 bit or 64 bit project? Specifically, does the “CredProvider.NET.Interop2.dll” work in 64 bits on windows 10. Our current UI works on both win 7 & 10 and requires only a registry change to port to 8 & 8.1. I cannot seem to get your example to load on windows 10 pro X64. I also cannot seem to recompile the “CredProvider.NET.Interop2.dll” as i keep getting an error from midl about the preprocessor fro cl.exe. I’d like to start by just getting your example to load and function. I cannot seem to find much online about it, a lot of the information on custom credential providers was written by the previous engineer that worked here as he struggled to port the XP gina to Vista. Is there an event viewer error i can check for to see if its trying to load and failing? Any info to point me in the right direction would be a great help. Thanks in advance,Scott

    Reply
    • It’s an x64 project. You’ll have to redo the build process for x86.

      What are you seeing when it doesn’t load? The DLL needs to be dropped into System32 in this case because the registry entries don’t have absolute paths.

      The midl compilation is tricky because of pathing. The best approach is to install the SDK and make any tweaks to the IDL file in Program Files, and build against that, otherwise it can’t find imports. Alternatively, I’m sure there are ways to get the right paths set up.

      This was more of an experimental idea so it’s not fully fleshed out, with many sharp edges. The best thing you can do is probably tweak the Logger to also write to a file: https://github.com/SteveSyfuhs/CredProvider.NET/blob/master/CredProvider.NET/Logger.cs

      That will tell you the stages of loading. The last time I started this from scratch, this is the process I went through:

      1. git pull
      2. Start Visual Studio as local admin (this is because of the assembly registration step on build)
      3. Adjust project references to point to DLLs in /CredProvider.NET/midl/
      3. Build
      4. Create registry entries from file
      5. Copy DLL to System32
      6. Start test app

      This can definitely be optimized to all happen automatically, but this was what I ended up having to do.

      Reply
      • Scott Jasin

        Hello,

        What ive done:
        Added the registry keys
        Placed the files into system 32 “CredProvider.NET.dll” & “CredProvider.NET.Interop2.dll”
        at this point it should show up when i log off or lock the screen right? In our CP version, we have a COM dll and a UI dll thats called into by the COM component for things like getting the username and password for example. Is the demo application needed?
        my registry looks like this, modeled after our software’s registry upon install of our CP

        [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Authentication\Credential Providers\{00006d50-0000-0000-b090-00006b0b0000}]
        @=”Credential Provider.NET”

        [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Authentication\Credential Provider Filters\{00006d50-0000-0000-b090-00006b0b0000}]
        @=”Credential Provider.NET”

        [HKEY_CLASSES_ROOT\CLSID\{00006d50-0000-0000-b090-00006b0b0000}]
        @=”Credential Provider.NET”

        [HKEY_CLASSES_ROOT\CLSID\{00006d50-0000-0000-b090-00006b0b0000}\InprocServer32]
        @=”Credential Provider.NET”
        “ThreadingModel”=”Apartment”

        Reply
      • Scott Jasin

        Hello,

        What ive done:
        Added the registry keys
        Placed the files into system 32 “CredProvider.NET.dll” & “CredProvider.NET.Interop2.dll”
        at this point it should show up when i log off or lock the screen right? In our CP version, we have a COM dll and a UI dll thats called into by the COM component for things like getting the username and password for example. Is the demo application needed?
        my registry looks like this, modeled after our software’s registry upon install of our CP

        [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Authentication\Credential Providers\{00006d50-0000-0000-b090-00006b0b0000}]
        @=”Credential Provider.NET”

        [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Authentication\Credential Provider Filters\{00006d50-0000-0000-b090-00006b0b0000}]
        @=”Credential Provider.NET”

        [HKEY_CLASSES_ROOT\CLSID\{00006d50-0000-0000-b090-00006b0b0000}]
        @=”Credential Provider.NET”

        [HKEY_CLASSES_ROOT\CLSID\{00006d50-0000-0000-b090-00006b0b0000}\InprocServer32]
        @=”Credential Provider.NET”
        “ThreadingModel”=”Apartment”

        I should mention im testing on a VM so I’m trying to load it without visual studio or any IDE.

        Reply
      • Scott Jasin

        I’m sorry, i tried to modify the comment and it posted repeats 🙁

        Reply
  15. Scott Jasin

    Hello,

    What ive done:
    Added the registry keys
    Placed the files into system 32 “CredProvider.NET.dll” & “CredProvider.NET.Interop2.dll”
    at this point it should show up when i log off or lock the screen right? In our CP version, we have a COM dll and a UI dll thats called into by the COM component for things like getting the username and password for example. Is the demo application needed?

    Reply
    • You will NOT see the credential provider show up on the lock screen because it was explicitly coded to not do that. Otherwise trying to dev against it would inevitably lock you out entirely. That’s what the test app is for. If you read the comments above it shows how to set the scenario selector so it works on the lock screen.

      Reply
      • Scott Jasin

        I will look above thanks, it should not lock you out though unless you tell it to filter out the standard windows CP. Ours for example can by bypassed if the filter is is set to “not enabled”; you can slide it to the side and enter the creds normally.

        Reply
        • Mostly. The other part is that you won’t be able to log in to anything at all if your CP craps out during development. This is why it’s more useful to do it in a test app, and then move it to a VM for things explicitly requiring running during logon.

          Reply
  16. Scott Jasin

    Just to be clear here, i should not necessarily have to compile the midl correct? If I’m aiming for X64, the CredProvider.NET.Interop2.dll you’ve provided should work fine? I have the CredProv.NET project compiling fine, but when i run the test app it:
    1. does not start unless the app is in the same directory as the CredProvider.NET.dll
    2. when it is in the same directory, it DOES start but none of the credential provider options are shown.
    I am testing this on a VM that is separate from my development machine and does not have an IDE on it; its a clean win10 pro X64 install.

    My other question is, in theory, this CredProvider.NET.dll should be able to fire up another UI inside of a dll by instantiating it correct?
    We have a pretty complex Logon UI which has in it IPC communication to a windows service, a listbox for displaying RF proximity badges in the area, as well as a number of other things it does. My goal here is to use what you have as a template, and instantiate during the logon/unlock process a dialog thats inside of another DLL.
    This is the way we do it today in C++ is, there is a COM DLL which loads some exported methods from another DLL which also contains the dialog and all other functionality needed for our software to function correctly. Basically our credential provider is made of 2 dll’s; the COM DLL and the “front end” UI dll which is a win 32 dialog box app.
    For this port project I’m working on, I have a WPF window inside a DLL that I’d like to instantiate from this “CredProvider.NET.dll” com object. and subsequently pass the creds from the front end to your COM dll and subsequently to windows.

    Unfortunately, all the development I’ve done here has been to the “front end” c++ dll regarding the IPC and logic therein and have never had to touch the COM dll until now. In your professional opinion, does what I’m describing seem possible with using your “CredProvider.NET.dll” as a starting point or should i try to pursue another rout?

    P.S. i changed the switch and it does not load still from locked/logged off screen, but I’m assuming if its not showing in the test app its not going to work anyhow, so i need to solve the problem of it not displaying in the test app on the target machine first.

    Thank you so much in advance for any and all help and sorry for being annoying 🙁

    Reply
    • You probably do not have to compile the IDL file. I only say probably because there might be specific things that you need to tweak that it didn’t automatically get right. There’s a few mangled pointer/structures.

      You do need to register the DLL using the x64 build of regasm before it will work. Once the CP DLL is in system32, the test program should run from anywhere on that box.

      Yes, it can fire up another UI. This is somewhat complicated and you’ll have to consult the original docs for how this all works because you need to get the right window handles and things otherwise you may end up with a window sitting below the logon screen. This will work though. Another, possible option is to put that UI into a separate exe and launching that instead.

      Building this out using this project as a starting point might be reasonable. There are a lot of missing pieces here that you will need to account for, because this isn’t a complete end-to-end sample. It doesn’t do anything once it’s received creds. Since you have an existing CP, the logic should be relatively easy to port.

      You are correct. It will not load on logon if it doesn’t load in the test app.

      Reply
      • Scott Jasin

        I Appreciate all your help. Thank you! I don’t think i can use an application version of the UI as, if I’m not mistaken, the COM portion will need to import some functions so when the event is set to unlock/logon, it can call getPWD,GetUsername,GetDomain for example to give to windows. Oh how i miss the days of GINA when you could just tell windows “open sesame” and it would comply, even without valid credentials. I will fart around with this today ans see where I get. Again I thank you for this example as it appears this was just what i was looking for. We are currently porting all of our configuation tool like fingerprint enrolling, configuration, and out badge ranging graph to WPF and I thought it only fitting to move the CP over to match them all as well. I’m just getting into C# as I come from a C/C++ background but with niceties like LINQ etc… I think I’m in love 😀

        Reply
      • Scott Jasin

        Hey Steve,

        I just wanted to stop back and thank you again. I now have my WPF UI firing up during locked/logged out state. Thanks for your example and thank you for taking the time to respond to me. It’s really helped me out a lot!

        Thanks again!
        Scott

        Reply
  17. wes

    Does anyone know of a credential provider that can make a call to Azure MFA for a second factor of authentication?

    Reply
  18. mohamed

    hi,
    how can I show output window instead of Windows 10 sign in window

    Reply
    • Scott Jasin

      look at the hardware event example for credential provider and replace the UI portion with what you want to display

      Reply
      • mohamed

        thanks for reply Scott I build your great sample well but I want to test login using my pc username and password can not add submit_buutonm kindly how can I handle this button to log in successfully using my pc username/password

        Reply
        • Scott Jasin

          What i did is launch a separate application that is the user interface to collect the credentials. Set the domain, username, and password in the COM object DLL using IPC. Then trigger the credentialschanged event to initiate the logon

          Reply
          • mohamed

            I know how to fire credentialschanged but how I can Set the domain, username, and password in the COM object DLL using IPC
            sorry for my little info.

  19. mohamed

    I know how to fire credentialschanged but how I can Set the domain, username, and password in the COM object DLL using IPC
    sorry for my little info.

    Reply
  20. Ram

    I’m using the above sample code to do a LogonUI credential provider and I got it working. Now I wanted to move it to a windows 10 x64 VM and thoroughly test it. The issue I face is, I’m unable to load the credential provider in the Logon UI case in the VM. The same works for the CredUI case. Interestingly, the log also does not get written in the LogonUI case(in the VM).

    When I tried in a physical machine, everything worked as expected. I’m not sure if its an issue with the VM. I downloaded the VM from here, https://developer.microsoft.com/en-us/microsoft-edge/tools/vms/

    Reply
  21. Ram

    hi, thanks for the sample. I tried to build a cred provider for LogonUI case and it worked. But when I tried to use the same in a Windows10 VM downloaded from here https://developer.microsoft.com/en-us/microsoft-edge/tools/vms/, the Credprovider works for CredUI case but it does not even get called during the LogonUI case. I am not sure if this is a VM issue or issue with my code.

    Reply

Leave a Reply to Matko Cancel Reply