UNPKG

vuethenticate

Version:

A Vue 3 authentication state management library using oidc-client-ts

2 lines (1 loc) 13.1 kB
(function(w,r){typeof exports=="object"&&typeof module<"u"?r(exports,require("vue"),require("oidc-client-ts")):typeof define=="function"&&define.amd?define(["exports","vue","oidc-client-ts"],r):(w=typeof globalThis<"u"?globalThis:w||self,r(w.Vuethenticate={},w.Vue,w.OidcClientTs))})(this,function(w,r,p){"use strict";var y=(e=>(e[e.NONE=0]="NONE",e[e.ERROR=1]="ERROR",e[e.WARN=2]="WARN",e[e.INFO=3]="INFO",e[e.DEBUG=4]="DEBUG",e))(y||{});const R={error:(e,...t)=>console.error(e,...t),warn:(e,...t)=>console.warn(e,...t),info:(e,...t)=>console.info(e,...t),debug:(e,...t)=>console.debug(e,...t)},M={error:()=>{},warn:()=>{},info:()=>{},debug:()=>{}},_=(e,t)=>({error:t>=1?e.error:()=>{},warn:t>=2?e.warn:()=>{},info:t>=3?e.info:()=>{},debug:t>=4?e.debug:()=>{}});function B(e){const t=typeof window<"u"?window.location.origin:"";return D(e),{authority:e.authority,client_id:e.clientId,client_secret:e.clientSecret,client_authentication:e.clientAuthentication,redirect_uri:e.redirectUri??`${t}/auth/callback`,scope:e.scope??"openid profile",response_type:e.responseType??"code",userStore:e.storage?new p.WebStorageStateStore({store:W(e.storage)}):void 0,automaticSilentRenew:e.automaticSilentRenew??!0,silent_redirect_uri:e.silentRedirectUri??`${t}/auth/silent-callback`,post_logout_redirect_uri:e.postLogoutRedirectUri??`${t}/auth/logout-callback`,includeIdTokenInSilentRenew:!0,accessTokenExpiringNotificationTimeInSeconds:60}}function W(e){if(typeof window>"u")return P();switch(e){case"localStorage":return window.localStorage;case"sessionStorage":return window.sessionStorage;case"memory":return P();default:return window.localStorage}}function P(){const e=new Map;return{getItem:t=>e.get(t)??null,setItem:(t,n)=>e.set(t,n),removeItem:t=>e.delete(t),clear:()=>e.clear(),get length(){return e.size},key:t=>Array.from(e.keys())[t]??null}}const D=e=>{if(e.logLevel===void 0&&!e.logger)return;const t=e.logger??(e.logLevel!==void 0?R:void 0),n=e.logLevel??y.NONE;t&&(p.Log.setLogger({error:t.error,warn:t.warn,info:t.info,debug:t.debug}),p.Log.setLevel(q(n)))},q=e=>{switch(e){case y.NONE:return p.Log.NONE;case y.ERROR:return p.Log.ERROR;case y.WARN:return p.Log.WARN;case y.INFO:return p.Log.INFO;case y.DEBUG:return p.Log.DEBUG;default:return p.Log.NONE}},S=new Map,G=e=>{try{const{userManager:t,eventCallbacks:n}=e;n.userLoaded&&t.events.removeUserLoaded(n.userLoaded),n.userUnloaded&&t.events.removeUserUnloaded(n.userUnloaded),n.accessTokenExpired&&t.events.removeAccessTokenExpired(n.accessTokenExpired),n.accessTokenExpiring&&t.events.removeAccessTokenExpiring(n.accessTokenExpiring),n.silentRenewError&&t.events.removeSilentRenewError(n.silentRenewError),t.stopSilentRenew(),t.clearStaleState()}catch(t){console.warn("Error during UserManager cleanup:",t)}},O=e=>`${e.authority}_${e.clientId}`,K=()=>S.size===0?null:(S.size===1||console.warn("Multiple auth instances detected. Callback components may not work as expected. Consider using a single auth instance or specify config explicitly."),Array.from(S.values())[0]||null),j=e=>{const t=O(e),n=S.get(t);if(n)return n;const o=Y(e),a=r.ref(!1),d=r.ref(!1),l=r.ref(null),k=r.ref(!1),c=r.ref(null),E=r.ref(null),h=r.computed(()=>!!l.value&&!l.value.expired),u=r.computed(()=>{var A;return((A=l.value)==null?void 0:A.access_token)||null}),g=r.computed(()=>{var A;return!!((A=l.value)!=null&&A.expired)}),f=H(e),L={userManager:o,isInitialized:a,isInitializing:d,user:l,isLoading:k,initError:c,authError:E,isAuthenticated:h,accessToken:u,isExpired:g,logger:f,eventCallbacks:{},initializationPromise:null};return S.set(t,L),L},Y=e=>{const t=B(e);return new p.UserManager(t)},H=e=>{if(!e.logger&&!e.logLevel)return M;const t=e.logger??R,n=e.logLevel??y.NONE;return _(t,n)},C=async e=>{await e.userManager.removeUser(),e.user.value=null},T=(e,t,n,o)=>{const a=e instanceof Error?e:new Error(t);return n.initError.value=a,o==null||o(a),a},v=(e,t,n,o)=>{const a=e instanceof Error?e:new Error(t);return n.authError.value=a,o==null||o(a),a},J=e=>{var t,n;if(!((t=e.authority)!=null&&t.trim()))throw new Error("AuthConfig: authority is required");if(!((n=e.clientId)!=null&&n.trim()))throw new Error("AuthConfig: clientId is required");try{new URL(e.authority)}catch{throw new Error("AuthConfig: authority must be a valid URL")}},z=async(e,t=1e4)=>e.initializationPromise?e.initializationPromise:e.isInitialized.value?Promise.resolve():new Promise((n,o)=>{const a=setTimeout(()=>{o(new Error("Authentication initialization timeout"))},t),d=r.watch(e.isInitialized,l=>{l&&(clearTimeout(a),d(),n())},{immediate:!0})}),Q=e=>{const t=window.location.href;return!!(e.silentRedirectUri&&t.startsWith(e.silentRedirectUri)||e.redirectUri&&t.startsWith(e.redirectUri)||e.postLogoutRedirectUri&&t.startsWith(e.postLogoutRedirectUri))},V=e=>{e.initError.value=null,e.authError.value=null},X=e=>{J(e);const t=j(e),{userManager:n,isInitialized:o,isInitializing:a,user:d,isLoading:l,initError:k,authError:c,isAuthenticated:E,accessToken:h,isExpired:u}=t,g=O(e),f=async()=>{if(!(a.value||o.value))try{a.value=!0,l.value=!0,V(t);const i=await n.getUser();if(i)if(!i.expired)d.value=i,t.logger.info("[Vuethenticate] useAuth: User restored from storage");else if(e.automaticSilentRenew!==!1){t.logger.info("[Vuethenticate] useAuth: Token expired, attempting silent renewal");try{await x()}catch(s){t.logger.warn("[Vuethenticate] useAuth: Silent renewal failed during initialization",s),await C(t)}}else await n.removeUser(),d.value=null;o.value=!0}catch(i){throw t.logger.error("[Vuethenticate] useAuth: Initialization failed",i),T(i,"Authentication initialization failed",t,e.onError),i}finally{a.value=!1,l.value=!1}},L=async i=>{try{l.value=!0,V(t),t.logger.info("[Vuethenticate] useAuth: Starting sign-in flow"),await n.signinRedirect({state:i})}catch(s){t.logger.error("[Vuethenticate] useAuth: Sign-in failed",s),v(s,"Sign in failed",t,e.onError)}finally{l.value=!1}},A=async i=>{try{l.value=!0,V(t),d.value=null,t.logger.info("[Vuethenticate] useAuth: Starting sign-out flow"),await n.signoutRedirect({state:i})}catch(s){t.logger.error("[Vuethenticate] useAuth: Sign-out failed",s),v(s,"Sign out failed",t,e.onError)}finally{l.value=!1}},x=async()=>{try{l.value=!0,V(t);const i=await n.signinSilent();d.value=i}catch(i){throw v(i,"Silent renewal failed",t,e.onError)}finally{l.value=!1}},re=()=>{V(t)},ne=async()=>{try{await C(t),t.logger.info("[Vuethenticate] useAuth: Authentication state reset")}catch(i){t.logger.error("[Vuethenticate] useAuth: Failed to reset authentication state",i),T(i,"Failed to reset authentication state",t,e.onError)}},F=(i,s)=>{const{userManager:U,user:$,eventCallbacks:b}=i;b.userLoaded=m=>{var N;$.value=m,(N=s.onUserLoaded)==null||N.call(s,m)},b.userUnloaded=()=>{var m;$.value=null,(m=s.onUserUnloaded)==null||m.call(s)},b.accessTokenExpired=()=>{var m;(m=s.onAccessTokenExpired)==null||m.call(s)},b.accessTokenExpiring=()=>{var m;(m=s.onAccessTokenExpiring)==null||m.call(s)},b.silentRenewError=async m=>{i.logger.warn("Silent renewal failed:",m);try{await C(i)}catch(N){i.logger.error("Failed to remove user after silent renewal error:",N)}v(m,"Silent renewal failed",i,s.onSilentRenewError)},U.events.addUserLoaded(b.userLoaded),U.events.addUserUnloaded(b.userUnloaded),U.events.addAccessTokenExpired(b.accessTokenExpired),U.events.addAccessTokenExpiring(b.accessTokenExpiring),U.events.addSilentRenewError(b.silentRenewError)},ae=()=>{G(t),S.delete(g)};return t.initializationPromise||(!o.value&&!a.value&&!Q(e)?(t.initializationPromise=f(),F(t,e)):(!o.value&&!a.value&&(F(t,e),o.value=!0),t.initializationPromise=Promise.resolve())),{user:d,isAuthenticated:E,isLoading:l,isInitialized:o,initError:k,authError:c,accessToken:h,isExpired:u,signIn:L,signOut:A,silentRenew:x,clearError:re,resetAuthState:ne,cleanup:ae,initializationPromise:t.initializationPromise}},I=()=>{const e=K();if(!e)throw new Error("Authentication not initialized. Make sure useAuth() is called in a parent component first.");return{processCallback:async()=>{try{await z(e),e.logger.info("[Vuethenticate] useAuthCallbacks: Processing authentication callback");const a=await e.userManager.signinCallback();if(!a)throw new Error("Authentication callback failed: no user returned");return e.logger.info("[Vuethenticate] useAuthCallbacks: Authentication callback successful"),{user:a,state:a.state}}catch(a){throw e.logger.error("[Vuethenticate] useAuthCallbacks: Authentication callback failed",a),await C(e),a}},processLogoutCallback:async()=>{try{await z(e),e.logger.debug("[Vuethenticate] useAuthCallbacks: Processing logout callback");const a=await e.userManager.signoutCallback();return e.logger.info("[Vuethenticate] useAuthCallbacks: Logout callback completed successfully"),{state:a==null?void 0:a.userState}}catch(a){throw e.logger.error("[Vuethenticate] useAuthCallbacks: Logout callback failed",a),await C(e),a}},processSilentCallback:async()=>{try{await z(e),e.logger.debug("[Vuethenticate] useAuthCallbacks: Processing silent callback"),await e.userManager.signinCallback(),e.logger.debug("[Vuethenticate] useAuthCallbacks: Silent callback completed successfully")}catch(a){throw e.logger.error("[Vuethenticate] useAuthCallbacks: Silent callback failed",a),await C(e),a}},isInitialized:e.isInitialized,isInitializing:e.isInitializing,logger:e.logger}},Z=r.defineComponent({__name:"AuthCallback",props:{onSuccess:{type:Function},onError:{type:Function}},emits:["success","error"],setup(e,{emit:t}){const n=e,o=t,{processCallback:a,isInitializing:d,logger:l}=I(),k=r.ref(!0),c=r.ref(null),E=async()=>{var h,u;try{l.info("[Vuethenticate] AuthCallback: Processing authentication callback");const g=await a();l.info("[Vuethenticate] AuthCallback: Authentication callback completed successfully"),(h=n.onSuccess)==null||h.call(n,g.user,g.state),o("success",g.user,g.state)}catch(g){const f=g instanceof Error?g:new Error("Callback processing failed");l.error("[Vuethenticate] AuthCallback: Authentication callback failed",f),c.value=f,(u=n.onError)==null||u.call(n,f),o("error",f)}finally{k.value=!1}};return r.onMounted(()=>{E()}),(h,u)=>(r.openBlock(),r.createElementBlock(r.Fragment,null,[(r.unref(d)||k.value)&&!c.value?r.renderSlot(h.$slots,"default",{key:0},()=>[u[0]||(u[0]=r.createElementVNode("p",null,"Processing authentication...",-1))]):r.createCommentVNode("",!0),c.value?r.renderSlot(h.$slots,"error",{key:1,error:c.value},()=>[r.createElementVNode("div",null,[u[1]||(u[1]=r.createElementVNode("h2",null,"Authentication Error",-1)),r.createElementVNode("p",null,r.toDisplayString(c.value.message),1)])]):r.createCommentVNode("",!0)],64))}}),ee=r.defineComponent({__name:"LogoutCallback",props:{onSuccess:{type:Function},onError:{type:Function}},emits:["success","error"],setup(e,{emit:t}){const n=e,o=t,{processLogoutCallback:a,isInitializing:d,logger:l}=I(),k=r.ref(!0),c=r.ref(null),E=async()=>{var h,u;try{l.info("[Vuethenticate] LogoutCallback: Processing logout callback");const g=await a();l.info("[Vuethenticate] LogoutCallback: Logout callback completed successfully"),(h=n.onSuccess)==null||h.call(n,g.state),o("success",g.state)}catch(g){const f=g instanceof Error?g:new Error("Logout callback processing failed");l.error("[Vuethenticate] LogoutCallback: Logout callback failed",f),c.value=f,(u=n.onError)==null||u.call(n,f),o("error",f)}finally{k.value=!1}};return r.onMounted(()=>{E()}),(h,u)=>(r.unref(d)||k.value)&&!c.value?r.renderSlot(h.$slots,"default",{key:0},()=>[u[0]||(u[0]=r.createElementVNode("p",null,"Processing logout...",-1))]):c.value?r.renderSlot(h.$slots,"error",{key:1,error:c.value},()=>[r.createElementVNode("div",null,[u[1]||(u[1]=r.createElementVNode("h2",null,"Logout Error",-1)),r.createElementVNode("p",null,r.toDisplayString(c.value.message),1)])]):r.renderSlot(h.$slots,"success",{key:2},()=>[u[2]||(u[2]=r.createElementVNode("div",null,[r.createElementVNode("h2",null,"Logout Successful"),r.createElementVNode("p",null,"You have been logged out successfully.")],-1))])}}),te=r.defineComponent({__name:"SilentCallback",props:{onError:{type:Function}},setup(e){const t=e,{processSilentCallback:n,isInitializing:o,logger:a}=I(),d=r.ref(null),l=async()=>{var k;try{a.debug("[Vuethenticate] SilentCallback: Processing silent callback"),await n()}catch(c){const E=c instanceof Error?c:new Error("Silent callback processing failed");a.error("[Vuethenticate] SilentCallback: Silent callback failed",E),d.value=E,(k=t.onError)==null||k.call(t,E)}};return r.onMounted(()=>{l()}),(k,c)=>(r.openBlock(),r.createElementBlock(r.Fragment,null,[r.unref(o)&&!d.value?r.renderSlot(k.$slots,"default",{key:0},()=>[c[0]||(c[0]=r.createElementVNode("p",null,"Processing silent renewal...",-1))]):r.createCommentVNode("",!0),d.value?r.renderSlot(k.$slots,"error",{key:1,error:d.value},()=>[r.createElementVNode("p",null,"Silent renewal error: "+r.toDisplayString(d.value.message),1)]):r.createCommentVNode("",!0)],64))}});w.AuthCallback=Z,w.LogLevel=y,w.LogoutCallback=ee,w.SilentCallback=te,w.consoleLogger=R,w.silentLogger=M,w.useAuth=X,Object.defineProperty(w,Symbol.toStringTag,{value:"Module"})});