Closed sergiomartindev closed 1 year ago
@sergiomartindev Can you paste snippets of your usage of @okta/okta-auth-js
? The error your mentioned is thrown by auth-js, not okta-vue
.
I'd also recommend mounting your LoginCallback
component on a path other than '/'
. Our samples usually use '/login/callback'
@jaredperreault-okta Sure thing. Here it goes:
const oktaAuth = new OktaAuth({
issuer: 'https://xxxxxxxxxxx',
clientId: 'xxxxxxxxxxxxxx',
scopes: ['openid', 'email', 'profile'],
redirectUri: 'https://localhost:3000/',
});
export default {
oktaAuth,
};
I am not redirecting to /login/callback
due to some policies of my company. So for the moment I am redirecting to /
. Is that relevant?
The LoginCallback is not the source of your bug, just a recommendation.
Do you call oktaAuth.signInWithRedirect()
somewhere in your app? I'm not sure what authStore.login()
actually does
@jaredperreault-okta I am not calling oktaAuth.signInWithRedirect()
anywhere in the app.
The development flow is as follows:
I'm showing you the content of authStore.login(
) at the end of the following flow, which follows the application's authentication process.
Inside the root file, I instantiate the Vue application and associate it with the Okta-vue plugin:
import { createApp } from 'vue';
import App from './App.vue';
import OktaVue from '@okta/okta-vue';
import okta from '@app/okta';
const app = createApp(App);
app.use(OktaVue, okta);
app.mount('#app');
The content of @app/okta
is as follows:
import { OktaAuth } from '@okta/okta-auth-js';
const oktaAuth = new OktaAuth({
issuer: 'https://xxxxxxxxx',
clientId: 'xxxxxxxxxxxxx',
scopes: ['openid', 'email', 'profile'],
redirectUri: 'https://localhost:3000/',
});
export default {
oktaAuth,
};
The redirectUri redirects to /. This is my router configuration for managing that:
import { LoginCallback } from '@okta/okta-vue';
export const routes: AppRoute[] = [
{
path: '/',
component: LoginCallback,
},
];
const router = createRouter({
history: createWebHistory(import.meta.env.BASE_URL),
routes,
});
Furthermore, within a global application guard, I have defined the following condition:
import { navigationGuard as oktaNavigationGuard } from '@okta/okta-vue';
async function beforeEach(to: AppRoute) {
const routeRequiresAuthentication: boolean = Boolean(to.meta.requiresAuth);
if (routeRequiresAuthentication) {
const authStore = useAuthStore();
await oktaNavigationGuard(to);
if (!authStore.isAuthenticated) {
await authStore.login();
}
}
return true;
}
This condition indicates that if the user is not authenticated, it should call the authStore.login()
method, which has the following content:
import { useAuth as useOktaAuth } from '@okta/okta-vue';
export default defineStore('auth', {
actions: {
async login() {
const oktaAuth = useOktaAuth();
this.authToken = oktaAuth.getAccessToken();
}
}
It is worth mentioning that SOMETIMES it manages to generate the token and redirects me to the previous page, being authenticated. But some others it takes me to /
and shows me the AuthSdkError: Unable to retrieve OAuth redirect params from storage
message.
getAccessToken
does not request an access token from the server, it reads an existing token from storage. This method will only return a token if an auth flow has already completed (and the user is currently authenticated). I believe the issue your experiencing is due to navigating to the LoginCallback
component independent of an auth flow redirect.
The LoginCallback
component is designed for Redirect Model (more info). The auth flow goes as follows:
signInWithRedirect()
)redirectUri
, this should be the same path the LoginCallback
component is mounted at)LoginCallback
component will process the resulting authorization code, exchange it for tokens, and write them to storageThe reason we recommend mounting LoginCallback
component on a dedicated route is it's not meant to be rendered outside of the context of a redirect from Okta
Edit: This sample app might help: https://github.com/okta/samples-js-vue/tree/master/okta-hosted-login
@sergiomartindev I am not seeing how/where a request is made to Okta for tokens. If you're not using signInWithRedirect
, how are you requesting tokens from Okta?
@jaredperreault-okta It's because of the OktaNavigationGuard imported from okta-vue:
import { navigationGuard as oktaNavigationGuard } from '@okta/okta-vue';
Once I add it to the router, it redirects to the Okta login page. I thought it did the same job as signInWithRedirect
.
@sergiomartindev My mistake, that is exactly what navigationGuard
does. Not sure how I missed that in your snippets.
A difference I noticed between our sample and tests app and the code snippets your provided
const app = createApp(App);
app.use(router); // samples/test app mount router before OktaVue
app.use(OktaVue, okta);
app.mount('#app');
Secondly, can you initiate a login from you app, then check your browser devtools to see if there is a entry in localStorage
? It's key should be something like okta-transaction
@sergiomartindev Has this been resolved?
Hey @jaredperreault-okta, I apologize for jumping to other tasks and forgetting to close this matter. The error doesn't seem to be appearing anymore, which is kind of weird since I haven't made many changes since the original implementation.
As a summary:
Entry:
import { createApp } from 'vue';
import App from './App.vue';
import router from '@app/router';
import httpClient from '@app/httpClient';
import OktaVue from '@okta/okta-vue';
import okta from '@app/okta';
(async () => {
await httpClient.initHttpClient();
const oktaInstance = await okta.getOktaInstance();
const app = createApp(App);
app.use(router);
app.use(OktaVue, { oktaAuth: oktaInstance });
app.mount('#app');
})();
@app/okta:
import appConfigService from '@app/services/appConfig.service';
import { OktaAuth } from '@okta/okta-auth-js';
async function getOktaInstance(): Promise<OktaAuth> {
const appConfig = await appConfigService.fetchAppConfig();
return new OktaAuth({
issuer: appConfig.oktaTenantId,
clientId: appConfig.oktaClientId,
redirectUri: appConfig.oktaRedirectUri,
postLogoutRedirectUri: appConfig.oktaLogoutURL,
scopes: ['openid', 'email', 'profile'],
state: 'test',
responseMode: 'fragment',
responseType: ['token', 'id_token'],
tokenManager: {
storage: 'localStorage',
},
});
}
export default {
getOktaInstance,
};
@app/router:
import { createRouter, createWebHistory } from 'vue-router';
import AppRoute from '@app/interfaces/AppRoute.interface';
import appGuard from '@app/guards/app.guard';
import { LoginCallback } from '@okta/okta-vue';
import { navigationGuard as oktaNavigationGuard } from '@okta/okta-vue';
export const routes: AppRoute[] = [
{
path: '/',
component: LoginCallback,
meta: {
requiredRoles: [],
},
},
];
const router = createRouter({
history: createWebHistory(import.meta.env.BASE_URL),
// @ts-ignore - Can't parse AppRoute to RouteRecordRaw
routes,
});
router.beforeEach(oktaNavigationGuard);
// @ts-ignore - OurRoute doesn't match with NormalizedRoute
router.beforeEach(appGuard.beforeEach);
export default router;
@app/guards/app.guard:
import AppRoute from '@app/interfaces/AppRoute.interface';
import useAuthStore from '@app/stores/auth.store';
import { useAuth as useOktaAuth } from '@okta/okta-vue';
import httpClient from '@app/httpClient';
import clientService from '@app/httpClient/services/client.service';
async function beforeEach(to: AppRoute) {
const routeRequiresAuthentication: boolean = Boolean(to.meta.requiresAuth);
if (routeRequiresAuthentication) {
const authStore = useAuthStore();
if (!authStore.isAuthenticated) {
const oktaAuth = useOktaAuth();
const oktaAuthToken = oktaAuth.getIdToken();
authStore.setAuthToken(oktaAuthToken as string);
clientService.setAuthHeader(httpClient.getHttpClient(), oktaAuthToken as string);
}
}
}
export default {
beforeEach,
};
And that would be it.
Regarding the okta-transaction key, there is indeed one called okta-shared-transaction-storage. In total, there are four keys: okta-original-uri-storage, okta-cache-storage, okta-shared-transaction-storage, and okta-token-storage."
I'll close this issue for now, feel free to reopen if the issuer occurs again
Describe the bug
Description: After integrating the @okta/okta-vue library into my Vue.js application and configuring the necessary components and routes, I encountered an error message when attempting to log in with Okta. The specific error message is "AuthSdkError: Unable to retrieve OAuth redirect params from storage."
Reproduction Steps:
I imported the required dependencies and configured the Okta plugin in my main app entry file.
I defined a route in my router configuration that uses the LoginCallback component from @okta/okta-vue for the / path.
I implemented a global route guard to trigger the login process if the user is not authenticated.
Within the login process, I retrieved the access token using the useOktaAuth hook and set it as the authToken.
I set the authentication header using clientService.
Expected Behavior: I expected the Okta login process to successfully authenticate the user and redirect them back to my application. The access token should be retrieved and set as the authToken for subsequent requests, and the application should function without any errors.
Actual Behavior: Instead of successfully logging in and redirecting back to the application, I encountered the "AuthSdkError: Unable to retrieve OAuth redirect params from storage" error message. This error occurs when attempting to retrieve the OAuth redirect parameters from the storage mechanism used by the Okta SDK.
This bug prevented successful authentication with Okta and hindered the overall functionality of my application.
To resolve the issue, I performed several troubleshooting steps, including clearing the browser cache and cookies, verifying the Okta configuration, checking browser support, and enabling Okta debugging. However, the issue persisted, leading me to believe it is a bug within the @okta/okta-vue library that requires further investigation and resolution by the library maintainers.
Reproduction Steps?
Import the necessary dependencies in your main app entry file):
Within an immediately invoked async function, create the Vue app, configure it to use the Okta plugin, and mount it:
In your router configuration file, import the LoginCallback component from @okta/okta-vue and define the / path to use it:
Trigger the login process in your global route guard if the user is not authenticated:
In the login method of authStore, use the useOktaAuth hook to retrieve the access token and set it as the authToken. Additionally, set the authentication header using clientService:
SDK Versions
System: OS: Windows 10 10.0.19044 CPU: (8) x64 11th Gen Intel(R) Core(TM) i5-1135G7 @ 2.40GHz Memory: 938.77 MB / 7.74 GB Binaries: Node: 16.17.0 - C:\Program Files\nodejs\node.EXE npm: 8.15.0 - C:\Program Files\nodejs\npm.CMD Browsers: Edge: Spartan (44.19041.1266.0), Chromium (114.0.1823.51)
Internet Explorer: 11.0.19041.1566 npmPackages: @okta/okta-vue: ^5.6.0 => 5.6.0 @vue/eslint-config-prettier: 7.1.0 => 7.1.0 @vue/eslint-config-typescript: 11.0.3 => 11.0.3 @vue/test-utils: 2.3.2 => 2.3.2 @vue/tsconfig: 0.4.0 => 0.4.0 vue: 3.3.4 => 3.3.4 vue-i18n: ^9.2.2 => 9.2.2 vue-router: 4.2.1 => 4.2.1 vue-tsc: 1.4.2 => 1.4.2 vuetify: 3.3.2 => 3.3.2
Additional Information
No response