UNPKG

@commercelayer/js-auth

Version:

A JavaScript library designed to simplify authentication when interacting with the Commerce Layer API.

2 lines 8.67 kB
var d=class extends Error{constructor(t){super(t),this.name="TokenError"}};var u=class extends d{constructor(t){super(t),this.name="InvalidTokenError"}};function x(e,t){if(typeof btoa<"u"){let r=e;if(t==="utf-8"){let o=new TextEncoder().encode(e);r=String.fromCharCode(...o)}return btoa(r).replaceAll("=","").replaceAll("+","-").replaceAll("/","_")}return Buffer.from(e,t).toString("base64url")}function T(e,t){if(typeof atob<"u"){let r=atob(e.replaceAll("-","+").replaceAll("_","/").padEnd(e.length+(4-e.length%4)%4,"="));if(t==="utf-8"){let o=new Uint8Array([...r].map(n=>n.charCodeAt(0)));return new TextDecoder().decode(o)}return r}return Buffer.from(e,"base64url").toString(t)}function c(e){let[t,r,o]=`${e}`.split(".");if(t==null||r==null||o==null)throw new u("Invalid token format");return{header:JSON.parse(T(t,"binary")),payload:JSON.parse(T(r,"utf-8")),signature:o}}function K(e){return e.application.kind==="user"}function $(e){return e.application.kind==="dashboard"}function B(e){return e.application.kind==="integration"}function _(e){return e.application.kind==="sales_channel"}function D(e){return e.application.kind==="webapp"}function S(e){return e.replace(/[A-Z]/g,t=>`_${t.toLowerCase()}`)}function y(e){return e?.payload?.iss?.startsWith("https://auth.")?e.payload.iss:"https://auth.commercelayer.io"}function w(e,t){return Object.keys(e).reduce((r,o)=>{let n=t(o);return r[n]=e[o],r},{})}async function z(e){let t=w(e,S),r=c(e.token),o=y(r);return await(await fetch(`${o}/oauth/revoke`,{method:"POST",cache:"no-store",headers:{"Content-Type":"application/json",Accept:"application/json"},body:JSON.stringify(t)})).json()}function k(e){return"owner"in e&&e.owner?.id!=null}function P(e){return e.replace(/([-_][a-z])/g,t=>t.toUpperCase().replace("-","").replace("_",""))}async function v(e,{domain:t="commercelayer.io",headers:r,...o}){let n=w({grant_type:e,...o},S),s=await(await fetch(`https://auth.${t}/oauth/token`,{method:"POST",cache:"no-store",headers:{"Content-Type":"application/json",Accept:"application/json",...r},body:JSON.stringify(n)})).json();return s.errors==null&&(s.expires=new Date(Date.now()+s.expires_in*1e3)),s.errors!=null&&!Array.isArray(s.errors)&&(s.errors=[s.errors]),w(s,P)}var j=e=>{let t=new Map;return function(...r){return new Promise((o,n)=>{let i=JSON.stringify(r),s=t.get(i);s===void 0?(t.set(i,{requestQueue:[]}),Promise.resolve(e.apply(this,r)).then(l=>{let m=t.get(i)?.requestQueue??[];t.delete(i),o(l);for(let h of m)h.resolve(l)}).catch(l=>{let m=t.get(i)?.requestQueue??[];t.delete(i),n(l);for(let h of m)h.reject(l)})):s.requestQueue.push({resolve:o,reject:n})})}};function b(e,t,{logPrefix:r,guestOnly:o=!1}){let n={...e,scope:e.scope??"market:all"};function i(p,...a){n.debug===!0&&console.log(`[CommerceLayer \u2022 auth.js] [${r}] ${p}`,...a)}let s=t.getKey??((p,a)=>`cl_${a}-${p.clientId}-${p.scope}`),l=async()=>{try{if(o===!1){let R=await s({clientId:n.clientId,scope:n.scope},"customer");i("Checking for customer key:",R);let g=I(await(t.customerStorage??t.storage).getItem(R));if(g?.ownerType==="customer"){if(g.expiresIn>=600)return i("Found customer authorization in storage",g),g;if(i("Customer authorization expired",g),g.refreshToken!=null){let W=await v("refresh_token",{...n,refreshToken:g.refreshToken}),O=await m({accessToken:W.accessToken,scope:W.scope,refreshToken:W.refreshToken});return i("Refreshed customer authorization",O),O}}}let a=await s({clientId:n.clientId,scope:n.scope},"guest");i("Checking for guest key:",a);let f=I(await t.storage.getItem(a));if(f?.ownerType==="guest"&&f.expiresIn>=600)return i("Found guest authorization in storage",f),f;i("No valid authorization found, requesting a new guest token");let C=await v("client_credentials",n);return await m({accessToken:C.accessToken,scope:C.scope})}catch(a){throw i("Error getting the authorization.",a),a}},m=async p=>{let a=I(p),f=await s({clientId:n.clientId,scope:p.scope},a.ownerType),C={accessToken:a.accessToken,scope:a.scope,refreshToken:a.ownerType==="customer"?a.refreshToken:void 0};return await(a.ownerType==="customer"?t.customerStorage??t.storage:t.storage).setItem(f,C),i("Stored authorization in storage",a),a},h=async p=>{let a=await s({clientId:n.clientId,scope:n.scope},p);await(p==="customer"?t.customerStorage??t.storage:t.storage).removeItem(a),i(`Removed "${p}" authorization from storage`,a)};return{options:n,getAuthorization:j(l),setAuthorization:m,removeAuthorization:h}}function I(e){if(e==null)return null;let t=c(e.accessToken);if(k(t.payload)&&t.payload.owner.type.toLowerCase()!=="customer")throw new Error("The provided access token does not contain a valid customer owner.");let r=k(t.payload)?{ownerType:"customer",ownerId:t.payload.owner.id,refreshToken:e.refreshToken}:{ownerType:"guest"},o=Math.round(t.payload.exp-Date.now()/1e3);return{...r,tokenType:"bearer",createdAt:t.payload.iat,scope:e.scope,accessToken:e.accessToken,expiresIn:o,expires:new Date(Date.now()+o*1e3)}}function E(e){return{async getItem(t){for(let r of e){let o=await r.getItem(t);if(o!==null){for(let n of e.slice(0,e.indexOf(r)))await n.setItem(t,o);return o}}return null},async setItem(t,r){await Promise.all(e.map(o=>o.setItem(t,r)))},async removeItem(t){await Promise.all(e.map(r=>r.removeItem(t)))},async dispose(){await Promise.all(e.map(t=>t.dispose?.()))}}}function U(e,t){let r=b(e,t,{logPrefix:"integration",guestOnly:!0});return{options:e,getAuthorization:r.getAuthorization,removeAuthorization:async()=>await r.removeAuthorization("guest"),revokeAuthorization:async()=>{let{ownerType:o,accessToken:n}=await r.getAuthorization();return o==="guest"?(await r.removeAuthorization("guest"),await z({clientId:e.clientId,clientSecret:e.clientSecret,token:n})):{}}}}function q(e,t){let r=b(e,t,{logPrefix:"sales_channel"});return{options:e,getAuthorization:r.getAuthorization,removeAuthorization:async(o="all")=>{if(o==="all"){await r.removeAuthorization("customer"),await r.removeAuthorization("guest");return}return r.removeAuthorization(o)},setCustomer:async o=>{let n=c(o.accessToken);if(k(n.payload))return await r.setAuthorization(o);throw new Error("The provided access token does not contain a valid customer owner.")},logoutCustomer:async()=>{let{ownerType:o,accessToken:n}=await r.getAuthorization();return o==="customer"?(await r.removeAuthorization("customer"),await z({clientId:e.clientId,token:n})):{}}}}var A=class extends d{constructor(){super("Token expired"),this.name="TokenExpiredError"}};function V(e,t={}){let{shouldThrow:r=!0}=t,o=c(e);if(!("organization"in o.payload)){if(r)throw new u("Invalid token format");return null}return y(o).replace("auth",o.payload.organization.slug)}function N(e,t={}){let{shouldThrow:r=!0}=t,o=c(e);if(!o?.payload?.scope?.includes("provisioning-api")){if(r)throw new u("Invalid token format");return null}return y(o).replace("auth","provisioning")}async function M({payload:e}){return await G(e,"cl")}async function G(e,t){let o=x(JSON.stringify({alg:"HS512",typ:"JWT"}),"binary"),n=x(JSON.stringify({...e,iat:Math.floor(Date.now()/1e3)}),"utf-8"),i=`${o}.${n}`,s=await H(i,t);return`${i}.${s}`}async function H(e,t){let r=new TextEncoder,o={name:"HMAC",hash:"SHA-512"},n=await crypto.subtle.importKey("raw",r.encode(t),o,!1,["sign","verify"]),i=await crypto.subtle.sign(o.name,n,r.encode(e));return x(String.fromCharCode(...new Uint8Array(i)),"binary")}function L(e){return Date.now()>=e.payload.exp*1e3}async function Q(e,{ignoreExpiration:t=!1,jwk:r}={}){let o=c(e),n=r??await F(o);if(n==null||n.kid!==o.header.kid)throw new u('Invalid token "kid"');if(!t&&L(o))throw new A;let i={name:"RSASSA-PKCS1-v1_5",hash:"SHA-512"},s=await crypto.subtle.importKey("jwk",n,i,!0,["verify"]),l=new Uint8Array(Array.from(T(o.signature,"binary"),p=>p.charCodeAt(0))),m=new TextEncoder().encode(e.split(".").slice(0,2).join("."));if(!await crypto.subtle.verify(i,s,l,m))throw new u("Invalid signature");return o}var J={};async function F(e){let{kid:t}=e.header;if(J[t]!=null)return J[t];let r=await Z(e);return J[t]=r.find(o=>o.kid===t),J[t]}async function Z(e){let t=`${y(e)}/.well-known/jwks.json`,r=await fetch(t).then(async o=>await o.json());if(r.keys==null)throw new d(`Invalid jwks response from "${t}": ${JSON.stringify(r)}`);return r.keys}export{u as InvalidTokenError,d as TokenError,A as TokenExpiredError,v as authenticate,M as createAssertion,E as createCompositeStorage,V as getCoreApiBaseEndpoint,N as getProvisioningApiBaseEndpoint,c as jwtDecode,$ as jwtIsDashboard,B as jwtIsIntegration,_ as jwtIsSalesChannel,K as jwtIsUser,D as jwtIsWebApp,Q as jwtVerify,U as makeIntegration,q as makeSalesChannel,z as revoke}; //# sourceMappingURL=index.js.map