问题描述
我正在创建一个$auth
插件,该插件可以使用this.$auth
I am creating an $auth
plugin that works fine from the component using this.$auth
main.js
import { Auth0Plugin } from "./auth";
Vue.use(Auth0Plugin, {
domain: process.env.VUE_APP_AUTH0_DOMAIN,
clientId: process.env.VUE_APP_AUTH0_CLIENT_ID,
audience: process.env.VUE_APP_AUTH0_AUDIENCE,
onRedirectCallback: () => {
router.push("/signed-in");
}
});
auth/index.js
auth/index.js
import Vue from "vue";
import createAuth0Client from "@auth0/auth0-spa-js";
/** Define a default action to perform after authentication */
const DEFAULT_REDIRECT_CALLBACK = () =>
window.history.replaceState({}, document.title, window.location.pathname);
let instance;
/** Returns the current instance of the SDK */
export const getInstance = () => instance;
/** Creates an instance of the Auth0 SDK. If one has already been created, it returns that instance */
export const useAuth0 = ({
onRedirectCallback = DEFAULT_REDIRECT_CALLBACK,
redirectUri = window.location.origin,
...options
}) => {
if (instance) return instance;
// The 'instance' is simply a Vue object
instance = new Vue({
data() {
return {
loading: true,
isAuthenticated: false,
user: {},
auth0Client: null,
popupOpen: false,
error: null
};
},
methods: {
/** Returns the access token. If the token is invalid or missing, a new one is retrieved */
getTokenSilently(o) {
return this.auth0Client.getTokenSilently(o);
},
},
/** Use this lifecycle method to instantiate the SDK client */
async created() {
// Create a new instance of the SDK client using members of the given options object
this.auth0Client = await createAuth0Client({
domain: options.domain,
client_id: options.clientId,
audience: options.audience,
redirect_uri: redirectUri
});
try {
// If the user is returning to the app after authentication..
if (
window.location.search.includes("code=") &&
window.location.search.includes("state=")
) {
// handle the redirect and retrieve tokens
const { appState } = await this.auth0Client.handleRedirectCallback();
// Notify subscribers that the redirect callback has happened, passing the appState
// (useful for retrieving any pre-authentication state)
onRedirectCallback(appState);
}
} catch (e) {
this.error = e;
} finally {
// Initialize our internal authentication state
this.isAuthenticated = await this.auth0Client.isAuthenticated();
this.user = await this.auth0Client.getUser();
this.loading = false;
}
}
});
return instance;
};
// Create a simple Vue plugin to expose the wrapper object throughout the application
export const Auth0Plugin = {
install(Vue, options) {
Vue.prototype.$auth = useAuth0(options);
}
};
我有一个调用api的服务类.我需要从此插件$auth.getTokenSilently()
获取api令牌.如何从我的api-service.js
文件中调用实例化插件?
I have a service class that calls an api.I need to get the api token from this plugin $auth.getTokenSilently()
.How do I call the instantiated plugin from my api-service.js
file?
我知道以下代码不起作用.但这只是为了演示我正在尝试做的事情.utils/api-service.js
I know the below code doesn't work.But it's just to demonstrate what I'm trying to do.utils/api-service.js
export default {
init() {
this.lqdApi = axios.create({
baseURL: process.env.lqdApiBaseUrl,
headers: { Authorization: `Bearer ${$auth.getTokenSilently()}` }
});
return this;
},
}
推荐答案
服务应在Vue中初始化.只需注入初始化数据即可:
The service should be initialized inside Vue. It can just be injected with initialization data:
init(token) {
this.lqdApi = axios.create({
baseURL: process.env.lqdApiBaseUrl,
headers: { Authorization: `Bearer ${token}` }
});
return this;
},
这里的问题是async created
是潜在的反模式,当auth0Client
尚未准备好但由组件使用时,它不会阻止子组件初始化.如果是这种情况,一种可能的解决方案是使Axios实例在Vue原型上可用,如此处所示.需要立即创建该实例,但是可以使用拦截器向其异步提供令牌,因为它们支持promise.它可以作为插件编写,并可以在Vue实例上使用,例如$auth
:
The problem here is that async created
is a potential antipattern, it doesn't prevent child components from being initialized when auth0Client
and therefore api-service
aren't ready but used by components. If this is the case, one of possible solutions is to make Axios instance available on Vue prototype, like shown here. The instance needs to be created immediately, but a token can be provided to it asynchronously with interceptors because they support promises.It can be written as a plugin and become available on Vue instance like $auth
:
install(Vue, options) {
Vue.prototype.$axios = axios.create();
},
created() {
if (this.$root === this) {
this.$axios.interceptors.request.use(async config => {
let auth0Client = await this.auth0ClientPromise;
config.headers.Authorization = `Bearer ${auth0Client.getTokenSilently()}`;
return config;
}
}
并且Vue实例上应该可以使用Auth0客户端实例的承诺,以便被Axios(以及可能依赖于它的其他事物)链接起来:
And a promise of Auth0 client instance should be available on Vue instance in order to be chained by Axios (and probably other things that may depend on it):
this.auth0ClientPromise = createAuth0Client(...);
this.auth0Client = await auth0ClientPromise;
这篇关于在js服务模块中使用Vue.js插件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!