I am setting up a basic Vue authentication app using Okta, based on the following: https://github.com/okta/okta-vue. I am attempting to convert the logic that handles routing and signin redirecting from Options API to Composition API. In other words, the login/logout functionality in App.vue, which is currently written like this:
async login () {
await this.$auth.signInWithRedirect()
this.$router.push('/protected')
},
async logout () {
await this.$auth.signOut()
}
https://github.com/okta/okta-vue#show-login-and-logout-buttons
Would probably look something like this in Composition API (I think):
setup() {
const router = useRouter()
const login = () => {
this.$auth.signInWithRedirect()
}
const logout = () => {
this.$auth.signOut()
}
return {login, logout, router}
}
However, I'm not sure how to change this.$auth.signInWithRedirect()
and this.$auth.signOut()
to work with Composition API, since $auth doesn't appear to be an accepted property. How can I set up the Okta methods signInWithRedirect()
and signOut()
to work with composition API? I'm new to Composition API and Vue in Typescript. Feedback is appreciated!
Here is the rest of the code below:
App.vue
<template>
<div id="app">
<button v-if='authState && authState.isAuthenticated' @click='logout' id='logout-button'> Logout </button>
<button v-else @click='login' id='login-button'> Login </button>
<router-view/>
</div>
</template>
<script lang="ts">
import { defineComponent } from 'vue'
import { useRouter } from 'vue-router'
export default defineComponent({
name: 'app',
setup() {
const router = useRouter()
const login = () => {
this.$auth.signInWithRedirect()
router.push('/protected')
}
const logout = () => {
this.$auth.signOut()
}
return {login, logout, router}
}
})
</script>
main.ts
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import { OktaAuth } from '@okta/okta-auth-js'
import OktaVue from '@okta/okta-vue'
const oktaAuth = new OktaAuth({
issuer: 'https://{dev-id}.okta.com/oauth2/default',
clientId: '{clientId}',
redirectUri: 'http://localhost:8080/login/callback',
scopes: ['openid', 'profile', 'email']
})
const app = createApp(App)
app.use(OktaVue, { oktaAuth })
app.use(router)
app.mount('#app')
router/index.ts
import { createRouter, createWebHistory, RouteRecordRaw } from 'vue-router'
import { LoginCallback } from '@okta/okta-vue'
import { navigationGuard } from '@okta/okta-vue'
import Protected from '../views/Protected.vue'
const routes: Array<RouteRecordRaw> = [
{
path: '/login/callback',
component: LoginCallback
},
{
path: '/protected',
name: 'Protected',
component: Protected,
meta: {
requiresAuth: true
}
}
]
const router = createRouter({
history: createWebHistory(process.env.BASE_URL),
routes
})
router.beforeEach(navigationGuard)
export default router
The okta-vue
plugin configures a global property named $auth
(which enables this.$auth
usage in the Options API). The property's value is actually the same oktaAuth
instance passed into the plugin via app.use(OktaVue, { oktaAuth })
(i.e., this.$auth
is set to oktaAuth
).
In the Composition API, you could access the app's global properties via getCurrentInstance()
:
// MyComponent.vue
<script lang="ts">
import { getCurrentInstance } from 'vue'
import type { OktaAuth } from '@okta/okta-auth-js'
export default {
setup() {
const oktaAuth = getCurrentInstance()!!.appContext.app.config.globalProperties.$auth as OktaAuth
const login = () => oktaAuth.signInWithRedirect()
const logout = () => oktaAuth.signOut()
⋮
}
}
</script>
Another approach is to move the oktaAuth
instance into a shared file that could be imported when needed, given that oktaAuth
is the same as the $auth
global property:
// auth.ts
import { OktaAuth } from '@okta/okta-auth-js'
export const oktaAuth = new OktaAuth({
issuer: `https://${process.env.VUE_APP_OKTA_DOMAIN}/oauth2/default`,
clientId: `${process.env.VUE_APP_OKTA_CLIENT_ID}`,
redirectUri: window.location.origin + '/login/callback',
scopes: ['openid', 'profile', 'email'],
pkce: true,
})
// main.ts
import OktaVue from '@okta/okta-vue'
import { oktaAuth } from './auth' 👈
const app = createApp(App)
app.use(OktaVue, { oktaAuth })
⋮
// MyComponent.vue
<script lang="ts">
import { oktaAuth } from './auth' 👈
export default {
setup() {
const login = () => oktaAuth.signInWithRedirect()
const logout = () => oktaAuth.signOut()
⋮
}
}
</script>