{"id":1904,"date":"2026-04-06T20:11:42","date_gmt":"2026-04-06T20:11:42","guid":{"rendered":"https:\/\/www.ultrexstaff.com\/?p=1904"},"modified":"2026-04-06T20:11:42","modified_gmt":"2026-04-06T20:11:42","slug":"setting-up-certificate-based-authentication-cba-in-microsoft-entra-id-from-scratch","status":"publish","type":"post","link":"https:\/\/www.ultrexstaff.com\/?p=1904","title":{"rendered":"Setting Up Certificate-Based Authentication (CBA) in Microsoft Entra ID \u2014 From Scratch"},"content":{"rendered":"\n<p><\/p>\n\n\n\n<p>Certificate-Based Authentication (CBA) lets users sign in to Microsoft 365 and Azure services using an X.509 certificate instead of a password. It&#8217;s phishing-resistant, passwordless, and pairs beautifully with smart cards and USB security keys. This guide walks you through the entire process of enabling CBA in a brand-new Entra ID tenant, from creating your own Certificate Authority to a successful first login.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Prerequisites<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li>A Microsoft Entra ID (Azure AD) tenant with at least a P1 license<\/li>\n\n\n\n<li>Global Administrator or Authentication Policy Administrator role<\/li>\n\n\n\n<li>OpenSSL installed on your machine (comes pre-installed on macOS and most Linux distros; on Windows, install via <a href=\"https:\/\/gitforwindows.org\/\">Git for Windows<\/a> or <a href=\"https:\/\/slproweb.com\/products\/Win32OpenSSL.html\">OpenSSL for Windows<\/a>)<\/li>\n\n\n\n<li>A user account to test with<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Step 1: Create Your Root Certificate Authority<\/h2>\n\n\n\n<p>You need a Certificate Authority (CA) to sign user certificates. For production environments you&#8217;d use Active Directory Certificate Services or a third-party CA, but a self-signed root CA works perfectly for smaller organizations.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">On macOS \/ Linux<\/h3>\n\n\n\n<p>Open Terminal and run:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>openssl genrsa -out rootCA.key 4096\nopenssl req -x509 -new -key rootCA.key -sha256 -days 1825 -out rootCA.crt -subj \"\/CN=YourOrg Root CA\"\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">On Windows<\/h3>\n\n\n\n<p>Open PowerShell or Git Bash and run:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>openssl genrsa -out rootCA.key 4096\nopenssl req -x509 -new -key rootCA.key -sha256 -days 1825 -out rootCA.crt -subj \"\/CN=YourOrg Root CA\"\n<\/code><\/pre>\n\n\n\n<p>This creates two files:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>rootCA.key<\/strong> \u2014 Your CA&#8217;s private key. Guard this carefully. Anyone with this file can issue trusted certificates for your tenant.<\/li>\n\n\n\n<li><strong>rootCA.crt<\/strong> \u2014 Your CA&#8217;s public certificate. This gets uploaded to Entra ID.<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Step 2: Convert the Root CA to .cer Format<\/h2>\n\n\n\n<p>Entra ID expects a <code>.cer<\/code> file for upload. Convert your root certificate:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>openssl x509 -in rootCA.crt -out rootCA.cer -outform DER\n<\/code><\/pre>\n\n\n\n<p>If you run into issues with DER format during upload, try PEM instead:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>openssl x509 -in rootCA.crt -out rootCA.cer -outform PEM\n<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Step 3: Upload the Root CA to Entra ID<\/h2>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Sign in to the <a href=\"https:\/\/entra.microsoft.com\/\">Microsoft Entra admin center<\/a><\/li>\n\n\n\n<li>Navigate to <strong>Security \u2192 Certificate authorities<\/strong><\/li>\n\n\n\n<li>Click <strong>Upload<\/strong><\/li>\n\n\n\n<li>Upload your <code>rootCA.cer<\/code> file<\/li>\n\n\n\n<li>Toggle <strong>&#8220;Is root CA&#8221;<\/strong> to <strong>Yes<\/strong><\/li>\n\n\n\n<li>Click <strong>Save<\/strong><\/li>\n<\/ol>\n\n\n\n<p>You should now see your CA listed with its thumbprint and expiration date.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Step 4: Enable Certificate-Based Authentication<\/h2>\n\n\n\n<ol class=\"wp-block-list\">\n<li>In the Entra admin center, go to <strong>Security \u2192 Authentication methods \u2192 Policies<\/strong><\/li>\n\n\n\n<li>Find <strong>Certificate-based authentication<\/strong> and click on it<\/li>\n\n\n\n<li>On the <strong>Enable and Target<\/strong> tab:\n<ul class=\"wp-block-list\">\n<li>Toggle the method to <strong>Enabled<\/strong><\/li>\n\n\n\n<li>Under <strong>Target<\/strong>, set it to <strong>All users<\/strong> or select a specific group<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li>Click <strong>Save<\/strong><\/li>\n<\/ol>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Step 5: Configure Username Binding<\/h2>\n\n\n\n<p>This is the step that trips most people up. You need to tell Entra ID how to match a certificate to a user account.<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Still in the CBA configuration, click the <strong>Configure<\/strong> tab<\/li>\n\n\n\n<li>Scroll down to <strong>Username binding<\/strong><\/li>\n\n\n\n<li>You should see default rules for <strong>PrincipalName<\/strong>, <strong>RFC822Name<\/strong>, and <strong>SKI<\/strong><\/li>\n<\/ol>\n\n\n\n<p>The <strong>PrincipalName<\/strong> binding maps the certificate&#8217;s Subject Alternative Name (SAN) UPN field to the user&#8217;s <code>userPrincipalName<\/code> in Entra. This is the binding we&#8217;ll use.<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p><strong>Important:<\/strong> The PrincipalName binding looks for the Microsoft UPN OID (<code>1.3.6.1.4.1.311.20.2.3<\/code>) in the certificate&#8217;s SAN extension \u2014 not the Subject CN field. Your certificates must include this SAN, or authentication will fail with &#8220;No value in the certificate, as requested by tenant policy, is able to validate the user claim.&#8221;<\/p>\n<\/blockquote>\n\n\n\n<h3 class=\"wp-block-heading\">Optional: CRL Validation<\/h3>\n\n\n\n<p>On the Configure tab you&#8217;ll also see <strong>Certificate revocation list (CRL) validation<\/strong>. For initial setup, leave &#8220;Require CRL validation&#8221; <strong>unchecked<\/strong>. You can enable it later once you have a CRL distribution point configured for your CA.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Step 6: Generate a User Certificate<\/h2>\n\n\n\n<p>Now create a certificate for your first user. The critical piece is including the UPN in the Subject Alternative Name using the Microsoft UPN OID.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">On macOS \/ Linux<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>openssl genrsa -out user-cba.key 2048\n\nopenssl req -new -key user-cba.key \\\n  -out user-cba.csr \\\n  -subj \"\/CN=user@yourdomain.com\" \\\n  -addext \"subjectAltName=otherName:1.3.6.1.4.1.311.20.2.3;UTF8:user@yourdomain.com\"\n\nopenssl x509 -req -in user-cba.csr \\\n  -CA rootCA.crt -CAkey rootCA.key -CAcreateserial \\\n  -out user-cba.crt -days 365 -sha256 \\\n  -copy_extensions copyall\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">On Windows<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>openssl genrsa -out user-cba.key 2048\n\nopenssl req -new -key user-cba.key -out user-cba.csr -subj \"\/CN=user@yourdomain.com\" -addext \"subjectAltName=otherName:1.3.6.1.4.1.311.20.2.3;UTF8:user@yourdomain.com\"\n\nopenssl x509 -req -in user-cba.csr -CA rootCA.crt -CAkey rootCA.key -CAcreateserial -out user-cba.crt -days 365 -sha256 -copy_extensions copyall\n<\/code><\/pre>\n\n\n\n<p>Replace <code>user@yourdomain.com<\/code> with the user&#8217;s actual UPN in Entra ID.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Step 7: Bundle into a .pfx File<\/h2>\n\n\n\n<p>Combine the certificate and private key into a PKCS#12 (.pfx) file. This is the portable format you&#8217;ll import onto the user&#8217;s machine.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">On macOS<\/h3>\n\n\n\n<p>macOS Keychain requires the legacy PKCS#12 format. If you&#8217;re on OpenSSL 3.x (check with <code>openssl version<\/code>), add the <code>-legacy<\/code> flag:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>openssl pkcs12 -export -out user-cba.pfx \\\n  -inkey user-cba.key \\\n  -in user-cba.crt \\\n  -certfile rootCA.crt \\\n  -legacy\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">On Windows<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>openssl pkcs12 -export -out user-cba.pfx -inkey user-cba.key -in user-cba.crt -certfile rootCA.crt\n<\/code><\/pre>\n\n\n\n<p>You&#8217;ll be prompted to set an export password. Remember it \u2014 you&#8217;ll need it during import.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Step 8: Import the Certificate<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">On macOS<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>security import user-cba.pfx -k ~\/Library\/Keychains\/login.keychain-db -P \"YourPassword\"\nsecurity import rootCA.cer -k ~\/Library\/Keychains\/login.keychain-db\n<\/code><\/pre>\n\n\n\n<p>If the <code>security import<\/code> command fails with &#8220;MAC verification failed during PKCS12 import,&#8221; you need to recreate the <code>.pfx<\/code> with the <code>-legacy<\/code> flag (see Step 7).<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">On Windows<\/h3>\n\n\n\n<p>Option A \u2014 GUI:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Double-click the <code>.pfx<\/code> file<\/li>\n\n\n\n<li>The Certificate Import Wizard opens<\/li>\n\n\n\n<li>Choose <strong>Current User<\/strong> and click Next<\/li>\n\n\n\n<li>Enter the export password<\/li>\n\n\n\n<li>Leave defaults and click through to finish<\/li>\n<\/ol>\n\n\n\n<p>Option B \u2014 Command line (run as Administrator):<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>certutil -addstore Root rootCA.cer\ncertutil -importpfx user-cba.pfx\n<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Step 9: Test the Login<\/h2>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>Fully quit your browser<\/strong> (Cmd+Q on Mac, or close all windows on Windows)<\/li>\n\n\n\n<li>Reopen the browser and navigate to <a href=\"https:\/\/login.microsoftonline.com\/\">https:\/\/login.microsoftonline.com<\/a><\/li>\n\n\n\n<li>Enter the user&#8217;s email address<\/li>\n\n\n\n<li>When prompted, choose <strong>&#8220;Use a certificate or smart card&#8221;<\/strong><\/li>\n\n\n\n<li>Your OS will present a certificate picker \u2014 select the correct certificate<\/li>\n\n\n\n<li>On macOS, you&#8217;ll be prompted for your Mac login password (Keychain password) \u2014 enter it and click <strong>Always Allow<\/strong><\/li>\n<\/ol>\n\n\n\n<p>If everything is configured correctly, you&#8217;ll be signed in.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Troubleshooting<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">&#8220;No certificate detected&#8221;<\/h3>\n\n\n\n<p>The certificate isn&#8217;t installed in your OS certificate store, or your browser needs to be restarted. Make sure both the user <code>.pfx<\/code> and root CA <code>.cer<\/code> are imported.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">&#8220;We couldn&#8217;t sign you in with a certificate&#8221;<\/h3>\n\n\n\n<p>The certificate was found and sent, but Entra rejected it. Check the <strong>Sign-in logs<\/strong> in Entra admin center for the specific error code.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Error 1001009: &#8220;No value in the certificate&#8230; is able to validate the user claim&#8221;<\/h3>\n\n\n\n<p>Your certificate doesn&#8217;t have the UPN in the SAN field. Regenerate the certificate with the <code>-addext \"subjectAltName=otherName:1.3.6.1.4.1.311.20.2.3;UTF8:user@domain.com\"<\/code> flag and use <code>-copy_extensions copyall<\/code> when signing.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">&#8220;MAC verification failed during PKCS12 import&#8221; (macOS)<\/h3>\n\n\n\n<p>OpenSSL 3.x uses newer encryption that macOS Keychain doesn&#8217;t support. Recreate the <code>.pfx<\/code> with the <code>-legacy<\/code> flag.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Security Best Practices<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Protect your Root CA key.<\/strong> Store <code>rootCA.key<\/code> offline or in a hardware security module. Anyone with this key can issue certificates trusted by your tenant.<\/li>\n\n\n\n<li><strong>Set reasonable certificate lifetimes.<\/strong> 365 days for user certificates is a good balance between security and convenience.<\/li>\n\n\n\n<li><strong>Enable CRL validation<\/strong> once you have a revocation infrastructure in place, so you can revoke compromised certificates.<\/li>\n\n\n\n<li><strong>Consider Multi-Factor strength.<\/strong> In the CBA configuration, you can set the authentication strength to Multi-factor if CBA should satisfy your MFA requirements on its own.<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Automating Certificate Deployment via USB (Windows)<\/h2>\n\n\n\n<p>If you&#8217;re deploying certificates as part of a Windows unattended install, you can automate the import. Place <code>rootCA.cer<\/code> and <code>user-cba.pfx<\/code> in a <code>Certs<\/code> folder on your USB drive, then add the following to your <code>autounattend.xml<\/code>:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;RunSynchronousCommand wcm:action=\"add\"&gt;\n    &lt;Order&gt;1&lt;\/Order&gt;\n    &lt;Path&gt;powershell -ExecutionPolicy Bypass -Command \"$d=(Get-Volume -FileSystemLabel 'ESD-USB').DriveLetter; certutil -addstore Root ${d}:\\Certs\\rootCA.cer; certutil -importpfx -p 'YourPassword' ${d}:\\Certs\\user-cba.pfx\"&lt;\/Path&gt;\n    &lt;Description&gt;Import CBA Certificates&lt;\/Description&gt;\n&lt;\/RunSynchronousCommand&gt;\n<\/code><\/pre>\n\n\n\n<p>This automatically finds the USB by volume label and imports both certificates during Windows setup.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">What&#8217;s Next?<\/h2>\n\n\n\n<p>Now that your tenant is set up for CBA, adding new users is straightforward \u2014 you just generate a new certificate for each user using the same Root CA. See the companion article: <strong>Issuing CBA Certificates for New Users<\/strong>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Certificate-Based Authentication (CBA) lets users sign in to Microsoft 365 and Azure services using an X.509 certificate instead of a password. It&#8217;s phishing-resistant, passwordless, and pairs beautifully with smart cards and USB security keys. This guide walks you through the entire process of enabling CBA in a brand-new Entra ID tenant, from creating your own [&hellip;]<\/p>\n","protected":false},"author":8,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-1904","post","type-post","status-publish","format-standard","hentry","category-uncategorized","post-preview"],"_links":{"self":[{"href":"https:\/\/www.ultrexstaff.com\/index.php?rest_route=\/wp\/v2\/posts\/1904","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.ultrexstaff.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.ultrexstaff.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.ultrexstaff.com\/index.php?rest_route=\/wp\/v2\/users\/8"}],"replies":[{"embeddable":true,"href":"https:\/\/www.ultrexstaff.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=1904"}],"version-history":[{"count":1,"href":"https:\/\/www.ultrexstaff.com\/index.php?rest_route=\/wp\/v2\/posts\/1904\/revisions"}],"predecessor-version":[{"id":1905,"href":"https:\/\/www.ultrexstaff.com\/index.php?rest_route=\/wp\/v2\/posts\/1904\/revisions\/1905"}],"wp:attachment":[{"href":"https:\/\/www.ultrexstaff.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=1904"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.ultrexstaff.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=1904"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.ultrexstaff.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=1904"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}