UNPKG

txt-domain-verification

Version:

A production-ready Node.js package for verifying domain ownership through DNS TXT records with authoritative nameserver queries, security features, and comprehensive error handling.

3 lines (2 loc) 3.17 kB
import e from"dns";import r from"dns2";import t from"crypto";function n(e){return e&&e.__esModule&&Object.prototype.hasOwnProperty.call(e,"default")?e.default:e}const o=e,{Client:s}=r,a=t,i={VERIFICATION_PREFIX:"_verify",TOKEN_EXPIRY_HOURS:72,MAX_RETRIES:3,RETRY_DELAY_MS:1e3,DNS_TIMEOUT_MS:1e4,MIN_NAMESERVERS_VERIFIED:1};function c(e){if("string"!=typeof e)throw new Error("Domain must be a string");return e.trim().toLowerCase().replace(/\.$/,"")}function m(e,r,t,n=new Date){if(!e||!r||!t)throw new Error("Secret, userId, and domain are required");const o=`${r}|${t}|${n.toISOString()}`,s=a.createHmac("sha256",e);return s.update(o),s.digest("base64url")}async function u(e){const r=c(e);try{const e=await o.promises.resolveNs(r);if(!e||0===e.length)throw new Error(`No nameservers found for ${r}`);const t=[];for(const r of e)try{const e=await o.promises.resolve4(r);t.push(...e)}catch(e){console.warn(`Warning: Could not resolve nameserver ${r}: ${e.message}`)}if(0===t.length)throw new Error(`Could not resolve any nameserver IPs for ${r}`);return t}catch(e){throw new Error(`Failed to resolve nameservers for ${r}: ${e.message}`)}}async function l(e,r,t){return new Promise((n,o)=>{const a=new s({nameServers:[e],timeout:i.DNS_TIMEOUT_MS}),c=`${t}.${r}`;a.on("message",e=>{const r=(e.answers||[]).filter(e=>"TXT"===e.type).map(e=>e.data.join(""));n(r)}),a.on("error",r=>{o(new Error(`Nameserver query failed for ${e}: ${r.message}`))}),a.on("timeout",()=>{o(new Error(`Nameserver query timeout for ${e}`))}),a.query(c,"TXT")})}var f=n({generateVerificationCode:function(e,r,t,n="",o="{{businessName}} Domain Verification: {{token}}",s=new Date){const a=c(e),u=m(r,t,a,s),l=o.replace("{{businessName}}",n).replace("{{token}}",u);return{token:u,formattedString:l,domain:a,issuedAt:s,expiresAt:new Date(s.getTime()+60*i.TOKEN_EXPIRY_HOURS*60*1e3),instructions:`Please add the following TXT record to your DNS settings for ${a}:\nName: ${i.VERIFICATION_PREFIX}\nValue: ${l}`,verificationRecord:{name:`${i.VERIFICATION_PREFIX}.${a}`,value:l}}},verifyDomain:async function(e,r,t=i.VERIFICATION_PREFIX,n={}){const o=c(e),s=n.maxRetries||i.MAX_RETRIES,a=n.retryDelay||i.RETRY_DELAY_MS;let m;for(let e=1;e<=s;e++)try{const n=await u(o),s=n.map(async e=>{try{return{nameserver:e,records:await l(e,o,t),success:!0}}catch(r){return{nameserver:e,error:r.message,success:!1}}}),a=await Promise.all(s),i=a.filter(e=>e.success),c=a.filter(e=>!e.success);let f=!1,d=[];for(const e of i)for(const t of e.records)t.includes(r)&&(f=!0,d.push({nameserver:e.nameserver,record:t}));const E={verified:f,domain:o,attempt:e,totalNameservers:n.length,successfulQueries:i.length,failedQueries:c.length,matchingRecords:d,partialPropagation:i.length>0&&i.length<n.length,nameserverResults:a,timestamp:new Date};if(f)return E;if(i.length>0)return E;m=new Error(`All nameserver queries failed for ${o}`)}catch(r){if(m=r,e<s){const r=a*Math.pow(2,e-1);await new Promise(e=>setTimeout(e,r))}}throw m||new Error(`Verification failed after ${s} attempts`)},generateSecureToken:m,normalizeDomain:c,resolveAuthoritativeNameservers:u,CONFIG:i});export{f as default}; //# sourceMappingURL=index.mjs.map