PART 2 - SCEP certificate enrolling using ConfigMgr 2012, CRP, NDES and Windows Intune

After many feedback from customers and partners, I’ve decided to write another post with more detailed information on how to successfully implement NDES in combination with ConfigMgr and Intune. I hope this helps you implement quicker.

Update 1: Consider reading my other post on adding a reverse proxy.
Update 2: Publish NDES via Azure AD Application Proxy as described in my other post.
Update 3: Updated 16/3/2016 with more detailed info (thanks Kevin Myrup)

NDES Design High level architecture:


  • The issuing CA needs to be Windows Server 2008R2 (with KB2483564) or preferable an higher Windows Server OS.
  • The NDES server needs to be Windows Server 2012 R2.
  • The NDES server needs to be domain joined to the same domain as the issuing CA. Please consult this TechNet article in case you want to deploy in a separate forest, isolated network or internal domain.
  • The NDES server cannot be the same as the issuing CA, even though that configuration is not blocked by setup, the policymodule will not work as expected in those conditions

Update 21/10/2014, please check my "Part 3" blog for more information on how to use an additional Web Application Proxy in front of the domain joined NDES server. 


From internet to DMZ:

  • Allow port 443 from all hosts/IP’s on the internet to the NDES server

From DMZ to trusted:

  • Allow all ports and protocols needed for domain access on the domain joined NDES. The NDES servers needs access to the Certificates Servers, DNS Servers, ConfigMgr Server(s) and Domain Controllers.

Now let’s start with the actual configuring, if something isn’t clear please leave a reply (a reply is always welcome)

Issuing Certificate Authority:

  • Log in as a Enterprise Administrator
  • Install all Windows Updates.
  • If your issuing Certificate Authority is Windows Server 2008 R2, install the hotfix mentioned earlier from here. Preferably use a newer Windows Operating system for your issuing CA.
  • Create certificate template(s) on the CA by duplicating an existing one
    • It’s easiest to duplicate the template from the included “User Template” and modify that.
    • Match purpose NDES template type (sig -> sig, crypt -> crypt, sig/crypt -> generalpurpose)
    • Make sure “Supply in Request” is selected on Subject Name Tab
    • Client Auth must be specified in the application policy
    • Have a look at these template configurationscreenshots.
      • Important note regarding the additional Application Policies (in the 4th screenshot), only add the application policies required. Consult your security department to ensure the appropiate configuration is done.
  • Enable the certificate template on the issuing CA.

NDES Server:

  • Log in as a Enterprise Administrator
  • Install all Windows Updates.
  • Make sure the NDES server is domain joined and has access to DNS, ConfigMgr, Certificate Authority and Domain Controller servers.
  • Go to Add Roles and Features.
  • Install Request Filtering which is located under Web Server (IIS) -> Web Server –> Security
  • Install Active Directory Certificate Services (ADCS) role. (Uncheck Certificate Authority component, and instead check Network Device Enrollment Service)
    • In parallel create a domain user/service account, e.g. “NDESUser”
      • Make sure the user has the "Logon Localy", "Logon as a Service" and "Logon as a batch job" rights. This should be the case by default, however some companies have hardening policies in place to disallow/remove these rights.
    • Make this user a member of the local IIS_IUSRS group.
    • Make sure this user has Enroll permissions on he certificate templates which will be used to issue user certificates via NDES (and which later will be configured in the registry on the NDES server under HKLM\Software\Microsoft\Cryptography\MSCEP).
    • Make sure the ConfigMgr admins who will create SCEP profiles have Read rights to the template so they can browse to it when creating SCEP profile configuration items in the ConfigMgr admin console.
  • Create a Service Principal Name (SPN) for the NDESUser
    • Open an elevated command prompt and type the following command (change the FQDN for the NDES server, Domain and NDESUser account to match your environment)
    • setspn -s http/ndesserver.mydomain.local mydomain\NDESUser
      If the SPN is not created; NDES to CA call may fail Kerberos authentication. If you are truly using a user account (not a service account e.g. network service or local service); then the fallback to NTLM will work just fine and you will not see any issues apart from some entries in security event log. If you block NTLM in your environment, this step is mandatory.
  • Continue to configure the Network Device Enrollment Service
    • CA for NDES – browse and locate your CA server using CA name or Computer name.
    • RA Information – you can leave the defaults.
    • Cryptography for NDES – Configure the CA value to be used by NDES server Make the key length match what is configured in your CA template – 1024 or 2048)
  • The NDES server will receive very long URL’s (queries) and therefore a few changes are needed. Open the registry editor and add two entries:

Location: HKLM\SYSTEM\CurrentControlSet\Services\HTTP\Parameters
Value: MaxFieldLength
Data: 65534 (decimal)

Location: HKLM\SYSTEM\CurrentControlSet\Services\HTTP\Parameters  
Value: MaxRequestBytes
Data: 65534 (decimal)

  • Open IIS manager, browse to the Default Web Site and select Request Filtering. On the right side of the console hit Edit Feature Setting and change the Maximum URL length and Maximum query string to 65534


  • After this reboot the server. This is mandatory – restarting IIS is not sufficient.
  • Next, browse to https://FQDN/certsrv/mscep/mscep.dll and you should receive a NDES page similar to the one below.


If you get an error 503 "Service unavailable", check the eventviewer. It's likely that the application pool is stopped due to a missing right for the NDESuser.

This website will be hardened later on – don’t worry.

  • The NDES server will need two certificates (or one with two EKU's - read on for more info), make sure you request those from the CA:
    • Traffic between the NDES server and the CRP (Certificate Registration Point) needs to be encrypted using SSL. The NDES server needs a certificate with Client Authentication Enhanced Key Usages (EKU’s)
    • A certificate using with a Server authentication EKU that it will use as it's SSL certificate for the IIS web server (to supply an https url for NDES so clients can connect using https to NDES server – absolutely recommended but not required).
  • If you request a certificate from your local CA, double check you have the correct EKU's in place.
    • The two mentioned certificates can be the same certificate (if the certificate has both capabilities), but they do not have to be. In case you want to have different expire lifetimes of the certificates e.g. you could generate one SSL certificate to last for 2 years, but client authentication certificate to expire after 1 year.
  • I prefer to take the easy way and requested a certificate with both the Client Authentication and Server Authentication EKU’s and used them for both scenarios.


Update 16/3/2016 by request - for both NDES and CRP SSL certificates (and the NDES client auth certificate) some more info related to the Subject Alternative Name (SAN):

SAN on the SSL certificate should contain the internal DNS name of the CRP server (which the NDES server will use when contacting it for cert verification requests). This DNS name should match what is entered as the CRP URL when installing the policymodule on the NDES server.

SAN on the SSL certificate should contain the public external DNS name of the NDES server (the one which will be a part of the uURLrl that devices will be provided to use for certificate enrollment requests). If using a WAP or other reverse proxy, this name should match what is published there.
SAN on the client auth certificate should contain the internal DNS name of the NDES server (which it will use to authenticate itself over the internal network to the CRP server). It may also contain the public DNS name.

  • In IIS manager, go to “Edit Bindings” of the Default Web Site and add a port 443 binding.
  • Add the certificate to the HTTPS binding.
  • Consider changing the SSL settings to “Require” SSL but “Ignore” client certificates.



CRP Site Server Role in ConfigMgr:

  • Install IIS - if it isn’t installed already.
  • Make sure to add the following optional role services (which will trigger several other dependent components to be added also)
    • Windows Server 2012 R2:
      • ASP .NET 3.5
      • ASP .NET 4.5
      • WCF HTTP Activation
    • Windows Server 2008 R2: 
      • ASP.NET  
      • WCF HTTP Activation 
      • (not in wizard but also do this) aspnet_regiis.exe –i (run this from .NET 4 folder: ex. C:\Windows\Microsoft.NET\Framework\v4.0.30319)
    • IIS 6 Management Compatibility (including IIS 6 Management WMI Compatibility also)
  • Bind the CRP cert to https 443:
  • In IIS Manager select Default Web Site
  • Right-click and choose Edit Bindings
  • Choose https (it will use port 443 by default)
  • Add or choose a CRP SSL certificate. (If you don't have this, request a default webserver certificate and add that)
  • Make sure after the certificate is selected, you see bindings for all IP address - * like in below screenshot below


Note: If you are installing CRP to a remote machine from the site server, you will need to add the machine account of site server to the local administrators group on the CRP machine (by default remote site role is installed using site server machine account). Alternatively, you can specify a specific user to install as in the CRP site role installation wizard, and in that case this user would need to be added as a local administrator on the remote CRP site machine.

  • Test if you can browse to the destination CRP server \\ipaddress\c$, if not make sure to enable “File and Sharing” firewall port
  • Deploy CRP as new site system from site server (CAS or Primary Site)
    • Open the Configuration Manager Admin Console
    • Navigate to Administration -> Site Configuration -> Servers and Site System Roles
    • Right click on primary site and select the Add Roles –> CRP
    • If you are installing on a site server not CAS or Primary Site, configure an account that will perform the installation by changing the “Site System Installation Account”

  • Specify the URL for NDES (for at least one NDES server), now this is important:

This URL will be part of the profile send to the devices. This means that the device – out there somewhere on the internet – needs to access this URL. Specify the internet facing URL, not any internal FQDN’s.


  • Specify/browse to the exported trusted root certificate (.cer file) for the server who signed the NDES client authentication certificate.  


  • Verify that the CRP installed successfully by opening the following logfiles (locations might be different depending on the ConfigMgr installation path):
  • C:\Program Files\Microsoft Configuration Manager\Logs\CRPMSI.log
    • This log must read “Installation success or error status: 0
  • C:\Program Files\Microsoft Configuration Manager\Logs\crpsetup.log
  • This log must read “CRP.msi exited with return code: 0
  • If errors like “GetIISWebServiceStringProperty failed” are listed, make sure the correct SSL certificate is bound and no “hostname” is specified in the “Edit Site Bindings”
  • C:\Program Files\Microsoft Configuration Manager\Logs\crpctrl.log

    • It should show that CRP status is 0 (online) like this line:

    “CRP's previous status was 0 (0 = Online, 1 = Failed, 4 = Undefined) SMS_CERTIFICATE_REGISTRATION_POINT 4/25/2014 9:50:21 PM 6496 (0x1960)”

    However, right after installation of CRP, it might not show that yet.  The self-health check runs every 10 minutes, so after 10 minutes it should change from 4 to 0 (online). This can be speed up by restarting the SMS_CERTIFICATE_REGISTRATION_POINT thread if desired.

  • C:\Program Files\SMS_CCM\CRP\Logs\CRP.log
    • This log should not contain any errors.
    • If you see a "Security Exception is thrown in reading inbox path" error, grant the "Network Service" account read permissions to the HKLM\SOFTWARE\Microsoft\SMS\MPFDM\Inboxes registry key.
  • Open a browser on the CRP server and browse to https://FQDN/CMCertificateRegistration
  • You should get a 403 Forbidden error. If you get anything else (e.g. a 404 or 500, stop right there and check all logs files and/or reboot the server)
    • If you receive a 404, open IIS Manager and navigate to CMCertificateRegistration below the Default Website. Change the SSL settings to "Require SSL" and "Require Client Certificates". Restart the SMS_EXEC service.
  • After the CRP is installed, the system will automatically export the certificate that will be used for NDES plugin (could take up to an hour or so) to the folder under inboxes on the site server. Be patient, it will be generated automatically.


  • Copy this certificate the NDES server – we will need it soon.
  • Copy the policymodule directory containing the installation files, you will find it in the ConfigMgr installation files under SMSSETUP\PolicyModule\X64 to the NDES server. We will need it at the next step.


Back to the NDES Server

  • On the NDES server, start “PolicyModuleSetup.exe” (copied earlier from the ConfigMgr installation files)
  • Specify the URL for the CRP e.g. https://crp.contoso.local/CMCertificateRegistration)
  • Specify the CRP port (if using something other than 443 on CRP).
  • Select a PKI certificate that supports client authentication. You might already have a suitable certificate installed on the computer that you can use, or you might have to (or prefer to) deploy a certificate specifically for this purpose. Hit next.
  • Select the cert that was copied from the CRP’s directory earlier.
  • Open the registry editor and browse to HKLM\SOFTWARE\Microsoft\Cryptography\MSCEP
  • Make sure that the values of “EncryptionTemplate”, “GeneralPurposeTemplate” and “SignatureTemplate” match the names of the template on your CA, triple check this!


Update 16/3/2016:

They should not all be set to the same thing. Most configurations will simply use GeneralPurposeTemplate, but they could also be using SignatureTemplate and/or EncryptionTemplate. If they do, though, those would be set to use a different template name. The mapping of Key Usage to registry key is as follows:

Encryption -> EncryptionTemplate
Signature and Encryption -> GeneralPurposeTemplate
Signature -> SignatureTemplate

  • Open an elevated command prompt and run “iisreset”.
  • Now open Internet Explorer on the NDES server and browse to, you should no longer see the web page but instead you should see an http 403 - Forbidden error. This is expected.

Configure the Certificate Profile on ConfigMgr

  • Logon to your ConfigMgr and open the console.
  • Open the Assets and compliance tab -> Compliance Settings -> Company Resource Access -> Certificate Profiles
  • Create a new profile, choose Trusted CA Certificate and hit next. Import your root CA certificate and hit next. Select which platforms you will be deploying this against. Hit finish at the end.


  • Now deploy this profile to your choice of users or devices.


  • Create a new Certificate Profile, this time a SCEP profile.
  • Change the desired options in the “enrollment parameters” window, I would go for the defaults.
  • Hit browse in the “Certificate template name”, remember this name must match whatever you entered in the registry on the NDES server!!
  • If the template they created on CA doesn’t show when browsing from this wizard, it could be due to one of two likely causes:
    • The ConfigMgr administrator does not have “Read” permissions to the template in AD (configure this on the template object from MMC on the CA).
    • The template has been created, but not published to AD. (publishing to AD is done using the MMC snapin called “Certification Authority”, and you right-click “Certificate Templates” folder, and choose New -> Certificate Template to Issue”)


  • At this point, be-aware that:
    • iOS doesn’t support fully distinguished name as the subject name format or including e-mail address in subject name.
    • You configure the settings according to what you have specified in the template (e.g. SHA-1/SHA-2/SHA-3 and the key-length).
    • If the template name contains non-ASCII characters the cert will not be deployed


  • Select the Root CA certificate and you should be good to go!
  • Hit next, select the destination platforms and finish the wizard.
  • Deploy the profile to the desired user or device collection(s).

Communication workflow

  1. Administrator configures policy in SCCM.
  2. Policy is sent to Intune service where details about the cert policy are used to create the challenge for the device(s).
  3. Policy is pushed to mobile device by Intune service during the next check-in. This policy contains the URL of the NDES server as well as the challenge generated by Intune.
  4. Device contacts the NDES server using the URL from #3 and provides the challenge response. (This is why your NDES server needs to be available externally in some way.)
  5. NDES Server (using our SCCM policy module) talks to the SCCM Certificate Registration Point (CRP) to validate challenge. You’ll need to make sure that 443 (SSL) is open between the NDES Server and the CRP for this validation to happen.
  6. CRP responds to NDES server with “true” or “false” to challenge verification. (Again, over 443 SSL.)
  7. If challenge is OK then the NDES server communicates with the CA to get a certificate for the device. You’ll need to make sure that the appropriate ports are open between NDES and CA for this to happen.
  8. NDES delivers certificate to mobile device.

Thanks Bob Roudebush for sharing.

Now what if it doesn’t work? Check these things first:

  1. The device time should be accurate. If it’s off 5 minutes or more, you will not get SCEP certificate.

  2. Did the Root CA (of the issuing CA) certificate you deployed in ConfigMgr got pushed to the device?

  3. Can you access the NDES URL from the internet using a browser?

    1. Are you getting any certificate errors?
    2. Make sure the URL corresponds with what is listed on the certificate ( and not https://ndes.yourinternaldomain.local)
  4. Visit You should get a response and the option to download a file.

  5. Push a certificate profile to a Windows device and check in the registry whether the request arrived.

    1. Open the registry editor and locate the following key: HKCU\Software\Microsoft\Windows\CurrentVersion\MDM
    2. The request will be visible as a subkey like shown in the screenshow below.
  6. The certificate thumbprint will be populated when the actual certificate is received.

  7. Open the CRPCTRL.LOG on the ConfigMgr server. The "previous status" should be 0.

    Check out the file C:\Program Files\Configuration Manager\Logs\crpctrl.log (could also be in x86 program files folder)

    There should be an entry as follows:
    CRP's previous status was 0 (0 = Online, 1 = Failed, 4 = Undefined)

  8. Do you get any requests logged on the IIS server of the NDES? What is the status code? Should be 200 in most cases!    
    Check out the last modified log in C:\inetpub\logs\LogFiles\W3SVC1

    Entries should look similair to this (notice the port number 443):2014-07-07 13:45:27 GET /certsrv/mscep/mscep.dll/pkiclient.exe operation=GetCACert&message=MDM 443 - - - 200 0 0 0

  9. Do you see any requests logged in the NDES.log?
    Check out the the log at C:\Program Files\Microsoft Configuration Manager\Logs\NDESPlugin.log
    Entries should look similair to this:
    <![LOG[==========[ NDES policy module started in process 2332 ]==========]LOG]!><time="22:37:15.204+00" date="03-18-2014" component="NDESPlugin" context="" type="1" thread="1356" file="ndesplugin.cpp:195">
    <![LOG[Calling Initialize...]LOG]!><time="22:37:15.204+00" date="03-18-2014" component="NDESPlugin" context="" type="1" thread="1356" file="ndesplugin.cpp:226">
    <![LOG[certificate registration point web server is sccm.internaldomain.local]LOG]!><time="22:37:15.204+00" date="03-18-2014" component="NDESPlugin" context="" type="1" thread="1356" file="ndesplugin.cpp:250">
    <![LOG[NDES thumbprint is 874b8e5864139ad337be36fdd86937fbce1aff9f.]LOG]!><time="22:37:15.204+00" date="03-18-2014" component="NDESPlugin" context="" type="1" thread="1356" file="ndesplugin.cpp:272">
    <![LOG[certificate registration point webservice URL is CMCertificateRegistration]LOG]!><time="22:37:15.204+00" date="03-18-2014" component="NDESPlugin" context="" type="1" thread="1356" file="ndesplugin.cpp:314">
    <![LOG[CA Issuer Name is ca01.internaldomain.local\\pcitdemo-CA01-CA]LOG]!><time="22:37:15.204+00" date="03-18-2014" component="NDESPlugin" context="" type="1" thread="1356" file="ndesplugin.cpp:356">
    <![LOG[Certificate registration port number is 443]LOG]!><time="22:37:15.204+00" date="03-18-2014" component="NDESPlugin" context="" type="1" thread="1356" file="ndesplugin.cpp:387">
    <![LOG[Exiting Initialize with 0x0]LOG]!><time="22:37:15.204+00" date="03-18-2014" component="NDESPlugin" context="" type="1" thread="1356" file="ndesplugin.cpp:396">
    <![LOG[Calling VerifyRequest ...]LOG]!><time="22:37:19.978+00" date="03-18-2014" component="NDESPlugin" context="" type="1" thread="1356" file="ndesplugin.cpp:646">
    <![LOG[Sending request to certificate registration point.]LOG]!><time="22:37:19.978+00" date="03-18-2014" component="NDESPlugin" context="" type="1" thread="1356" file="httprequest.cpp:114">
    <![LOG[Verify challenge returns false]LOG]!><time="22:37:20.563+00" date="03-18-2014" component="NDESPlugin" context="" type="1" thread="1356" file="ndesplugin.cpp:834">
    <![LOG[Exiting VerifyRequest with 0x0]LOG]!><time="22:37:20.563+00" date="03-18-2014" component="NDESPlugin" context="" type="1" thread="1356" file="ndesplugin.cpp:874">

  10. Do you see any request logged on the IIS server of the CRP? What is the status code? Should be 200 in most cases!    
    Check out the last modified log in C:\inetpub\logs\LogFiles\W3SVC1

  11. Do you see any request logged in the CRP log on the CRP server?
    C:\Program Files\SMS_CCM\CRP\Logs\crp.log

  12. Are you getting this error: 

    CRP's previous status was 1 (0 = Online, 1 = Failed, 4 = Undefined)
    Health check request failed, status code is 403, 'Forbidden'.

    Make sure you change IIS on your ConfigMgr server - CMCertificateRegistration SSL Settings to Ignore Client Certificates

  13. Do you see a certificate being issued on the issuing CA?


14. Are you getting this output in the ndes logfile?

 <![LOG[Failed to retrieve client certificate. Error -2147467259]LOG]!><time="20:48:44.215+00" date="08-17-2015" component="NDESPlugin" context="" type="3" thread="4064" file="httprequest.cpp:240">
<![LOG[Exiting VerifyRequest with 0x80004005]LOG]!><time="20:48:44.215+00" date="08-17-2015" component="NDESPlugin" context="" type="1" thread="4064" file="ndesplugin.cpp:874">

The client auth cert needs to have the internal dns name to present to the CRP.The easiest way to do this is to put both DNS names in the SAN of the certificate. See this technet post for more info.

14. Are you getting Event ID 29 in the NDES Plugin Log? The eventlog might give you this entry:

Event ID: 29The password in the certificate request cannot be verified. It may have been used already. Obtain a new password to submit with this request.
Source: Microsoft-Windows-NetworkDeviceEnrollmentService
Description: The Network Device Enrollment Service failed to process a client device's request because the submitted password is invalid.
Diagnose: Check the IIS log to find out what query string was submitted.
Check the device configuration to ensure that the correct password is being submitted as part of the request.
Use certutil to check whether the PKCS7 package from the client is valid (certutil -v p7request.txt, where p7request.txt is a file in which the query string is captured).
Otherwise, enable CAPI2 diagnostics and, if possible, reproduce the error. Resolve: If necessary, contact the vendor of the SCEP client and ensure that the request is being submitted correctly.

So what's up with that? Your service certificate (e.g. for Client Authentication) expired or was revoked.
Note: the registry value of HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Cryptography\MSCEP\Modules\NDESPolicy\NDESCertThumbprint needs to be MANUALLY update with the thumbprint of the new service certificate, replacing the old certificate’s thumbprint, else NDES will continue trying to use the old certificate, even if it’s archived. Thanks Mr. Hammami for getting to this solution.


Hope this post helped you implement NDES with Microsoft Intune, please consider leaving a reply if it did!