{"id":42,"date":"2026-08-02T18:47:07","date_gmt":"2026-08-02T09:47:07","guid":{"rendered":"https:\/\/www.ysharada.com\/?p=42"},"modified":"2026-08-02T18:47:07","modified_gmt":"2026-08-02T09:47:07","slug":"microsoft-entra-id-%e3%81%ae%e8%a8%bc%e6%98%8e%e6%9b%b8%e8%aa%8d%e8%a8%bc%e3%81%a7-smtp-oauth2-%e3%83%a1%e3%83%bc%e3%83%ab%e9%80%81%e4%bf%a1","status":"publish","type":"post","link":"https:\/\/www.ysharada.com\/?p=42","title":{"rendered":"Microsoft Entra ID \u306e\u8a3c\u660e\u66f8\u8a8d\u8a3c\u3067 SMTP OAuth2 \u30e1\u30fc\u30eb\u9001\u4fe1"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">Microsoft Entra ID \u306e\u8a3c\u660e\u66f8\u8a8d\u8a3c\u3067 SMTP OAuth2 \u30e1\u30fc\u30eb\u9001\u4fe1<br>\u6982\u8981\uff1a\u3053\u308c\u307e\u3067 Client Secret \u3092\u4f7f\u7528\u3057\u3066\u3044\u305f Node.js \u306e\u30e1\u30fc\u30eb\u9001\u4fe1\u30d0\u30c3\u30c1\u3092\u3001Microsoft Entra ID \u306e\u8a3c\u660e\u66f8\u8a8d\u8a3c\u3078\u5909\u66f4\u3057\u305f\u969b\u306e\u30e1\u30e2\u3067\u3059\u3002<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\u74b0\u5883\uff1a<br>\u3000Windows 11<br>\u3000Node.js<br>\u3000nodemailer<br>\u3000@azure\/msal-node 5.4.3<br>\u3000Exchange Online SMTP AUTH (OAuth2)<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">\u81ea\u5df1\u7f72\u540d\u8a3c\u660e\u66f8\u306e\u4f5c\u6210<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">PowerShell \u3067\u4f5c\u6210\u3002<br>$cert = New-SelfSignedCertificate <code>-Subject \"CN=MailBatchCert\"<\/code><br>-CertStoreLocation &#8220;Cert:\\CurrentUser\\My&#8221; <code>-KeyAlgorithm RSA<\/code><br>-KeyLength 2048 <code>-KeyExportPolicy Exportable<\/code><br>-NotAfter (Get-Date).AddYears(5)<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\u516c\u958b\u8a3c\u660e\u66f8(.cer)\u51fa\u529b<br>Export-Certificate <code>-Cert $cert<\/code><br>-FilePath C:\\temp\\MailBatchCert.cer<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\u79d8\u5bc6\u9375\u4ed8\u304d\u8a3c\u660e\u66f8(.pfx)\u51fa\u529b<br>$password = ConvertTo-SecureString <code>\"\u4efb\u610f\u306e\u30d1\u30b9\u30ef\u30fc\u30c9\"<\/code><br>-AsPlainText `<br>-Force<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Export-PfxCertificate <code>-Cert $cert<\/code><br>-FilePath C:\\temp\\MailBatchCert.pfx `<br>-Password $password<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Entra ID \u5074\u8a2d\u5b9a<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">\u30a2\u30d7\u30ea\u767b\u9332\u306e\u753b\u9762\u3067\u3001\u8a72\u5f53\u306e\u30a2\u30d7\u30ea\u306b\u516c\u958b\u8a3c\u660e\u66f8(.cer)\u3092\u30a2\u30c3\u30d7\u30ed\u30fc\u30c9\u3002\uff08\u79d8\u5bc6\u9375\u4ed8\u304d\u306e PFX \u306f\u767b\u9332\u3057\u306a\u3044\uff09<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">PFX\u304b\u3089\u79d8\u5bc6\u9375\u3092\u53d6\u5f97<\/h2>\n\n\n\n<div class=\"wp-block-group\"><div class=\"wp-block-group__inner-container is-layout-constrained wp-block-group-is-layout-constrained\">\n<p class=\"wp-block-paragraph\">const forge = require(&#8220;node-forge&#8221;);<br>const crypto = require(&#8220;crypto&#8221;);<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">function getThumbprint(cert) {<br>const der = forge.asn1.toDer(<br>forge.pki.certificateToAsn1(cert)<br>);<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">return crypto<br>.createHash(&#8220;sha1&#8221;)<br>.update(Buffer.from(der.getBytes(), &#8220;binary&#8221;))<br>.digest(&#8220;hex&#8221;)<br>.toUpperCase();<br>}<br>return {<br>privateKey: pkcs8PrivateKey,<br>thumbprint: getThumbprint(cert)<br>};<\/p>\n<\/div><\/div>\n\n\n\n<div class=\"wp-block-group is-vertical is-layout-flex wp-container-core-group-is-layout-4fc3f8e1 wp-block-group-is-layout-flex\">\n<p class=\"wp-block-paragraph\">MSAL\u8a2d\u5b9a<br>const cca =<br>new msal.ConfidentialClientApplication({<br>auth: {<br>  clientId,<br>  authority:<br><code>  https:\/\/login.microsoftonline.com\/${tenantId}<\/code>,<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">  clientCertificate: {<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">    thumbprint : certInfo.thumbprint,<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">    privateKey:certInfo.privateKey<br>  }}});<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">\u30cf\u30de\u3063\u305f\u30dd\u30a4\u30f3\u30c8<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>\u00d7 thumbprintSha256 \u3092\u4f7f\u3063\u3066\u3044\u305f<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\u6700\u521d\u306fthumbprintSha256\u3092\u81ea\u524d\u3067\u4f5c\u6210\u3057\u3066\u3044\u305f\u304c\u3001<br>\u3000\u8a8d\u8a3c\u30a8\u30e9\u30fc<br>\u3000\u3000AADSTS700027<br>\u3000\u3000No certificate SHA-1 thumbprint,<br>\u3000\u3000certificate SHA-256 thumbprint,<br>\u3000\u3000nor keyId specified in token header<br>\u304c\u767a\u751f\u3002<\/p>\n<\/div>\n\n\n\n<p class=\"wp-block-paragraph\"><br><strong>\u25cb thumbprint \u3092\u4f7f\u7528<\/strong><br>MSAL Node \u3067\u306f<br>clientCertificate: {<br>thumbprint: &#8220;\u8a3c\u660e\u66f8\u306eSHA1 Thumbprint&#8221;,<br>privateKey: &#8220;\u79d8\u5bc6\u9375&#8221;<br>}<br>\u3092\u6307\u5b9a\u3059\u308b\u3002<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><br>PowerShell\u3067\u78ba\u8a8d\u53ef\u80fd\u3002<br>Get-PfxCertificate .\\MailBatchCert.pfx |<br>fl Subject,Thumbprint<br>\u4f8b\uff1aThumbprint : 1D663C16FAF9BCA8E8D03BAD0B55B2E5D91E2EC7<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>\u00d7 pkcs8PrivateKey<\/strong><br>\u4ee5\u4e0b\u306f\u8a8d\u8b58\u3055\u308c\u306a\u3044\u3002<br>clientCertificate: {<br>pkcs8PrivateKey: \u2026<br>}<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>\u25cb privateKey<\/strong><br>\u6b63\u3057\u304f\u306f<br>clientCertificate: {<br>privateKey: \u2026<br>}<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">\u8a8d\u8a3c\u306e\u4ed5\u7d44\u307f<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">\u3000Client Secret \u8a8d\u8a3c<br>\u3000\u3000Client ID\uff0bClient Secret\u2192Entra ID<br>\u3000\u3000\u79d8\u5bc6\u60c5\u5831\u3092\u9001\u4fe1\u3059\u308b\u65b9\u5f0f\u3002<br>\u3000\u8a3c\u660e\u66f8\u8a8d\u8a3c<br>\u3000\u3000\u79d8\u5bc6\u9375(PFX)\u2192JWT\u3078\u96fb\u5b50\u7f72\u540d\u2192Entra ID\u2192\u516c\u958b\u9375(CER)<br>\u3000\u3000\u3067\u691c\u8a3c<br>\u3000\u3000\u79d8\u5bc6\u9375\u305d\u306e\u3082\u306e\u306f\u9001\u4fe1\u3055\u308c\u306a\u3044\u3002<br>\u3000\u3000\u305d\u306e\u305f\u3081 Secret \u3088\u308a\u5b89\u5168\u6027\u304c\u9ad8\u3044\u3002<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">\u307e\u3068\u3081<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">\u3000Entra ID\u306b\u306f .cer \u3092\u767b\u9332<br>\u3000\u30b5\u30fc\u30d0\u30fc\u306b\u306f .pfx \u3092\u914d\u7f6e<br>\u3000node-forge\u3067PFX\u304b\u3089\u79d8\u5bc6\u9375\u53d6\u5f97<br>\u3000MSAL\u306f thumbprint \u3068 privateKey \u3092\u6307\u5b9a<br>\u3000SMTP\u9001\u4fe1\u51e6\u7406(nodemailer)\u306f\u5909\u66f4\u4e0d\u8981<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Client Secret\u304b\u3089\u8a3c\u660e\u66f8\u8a8d\u8a3c\u3078\u306e\u79fb\u884c\u306f\u3001MSAL\u90e8\u5206\u306e\u4fee\u6b63\u3060\u3051\u3067\u5b9f\u73fe\u3067\u304d\u307e\u3057\u305f\u3002 \ud83c\udf89<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">\u4eca\u56de\u306e\u6559\u8a13<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">\u3000thumbprintSha256 \u3068 thumbprint(SHA1) \u306f\u5225\u7269\u3067\u3059\u3002<br>\u3000AADSTS700027 \u304c\u51fa\u305f\u3089\u3001\u307e\u305a clientCertificate \u306e thumbprint \u3068 privateKey \u306e\u6307\u5b9a\u3092\u7591\u3046\u3079\u3057\u3002 \ud83d\ude04<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Microsoft Entra ID \u306e\u8a3c\u660e\u66f8\u8a8d\u8a3c\u3067 SMTP OAuth2 \u30e1\u30fc\u30eb\u9001\u4fe1\u6982\u8981\uff1a\u3053\u308c\u307e\u3067 Client Secret \u3092\u4f7f\u7528\u3057\u3066\u3044\u305f Node.js \u306e\u30e1\u30fc\u30eb\u9001\u4fe1\u30d0\u30c3\u30c1\u3092\u3001Microsoft Entra I&hellip; <a class=\"more-link\" href=\"https:\/\/www.ysharada.com\/?p=42\">\u7d9a\u304d\u3092\u8aad\u3080 <span class=\"screen-reader-text\">Microsoft Entra ID \u306e\u8a3c\u660e\u66f8\u8a8d\u8a3c\u3067 SMTP OAuth2 \u30e1\u30fc\u30eb\u9001\u4fe1<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[6],"tags":[],"class_list":["post-42","post","type-post","status-publish","format-standard","hentry","category-m365","entry"],"_links":{"self":[{"href":"https:\/\/www.ysharada.com\/index.php?rest_route=\/wp\/v2\/posts\/42","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.ysharada.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.ysharada.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.ysharada.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.ysharada.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=42"}],"version-history":[{"count":1,"href":"https:\/\/www.ysharada.com\/index.php?rest_route=\/wp\/v2\/posts\/42\/revisions"}],"predecessor-version":[{"id":43,"href":"https:\/\/www.ysharada.com\/index.php?rest_route=\/wp\/v2\/posts\/42\/revisions\/43"}],"wp:attachment":[{"href":"https:\/\/www.ysharada.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=42"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.ysharada.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=42"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.ysharada.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=42"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}