I'm getting an error trying to login with Azure + TypeScript/JavaScript. The problem is when the user logs in and needs to get redirected to another page. When the response from login is OK, the page remains blank and I need to refresh manually.
This is my config file:
import { Configuration, LogLevel } from "#azure/msal-browser"
export const msalConfig:Configuration = {
auth: {
clientId: process.env.AZURE_CLIENT_LOGIN || "",
authority: "https://login.microsoftonline.com/" + process.env.AZURE_AUTH_LOGIN,
redirectUri: "/admin/dashboard"
},
cache: {
cacheLocation: "sessionStorage", // This configures where your cache will be stored
storeAuthStateInCookie: false, // Set this to "true" if you are having issues on IE11 or Edge
},
system: {
loggerOptions: {
loggerCallback: (level: any, message: any, containsPii: any) => {
if (containsPii) {
return;
}
switch (level) {
case LogLevel.Error:
console.error(message);
return;
case LogLevel.Info:
console.info(message);
return;
case LogLevel.Verbose:
console.debug(message);
return;
case LogLevel.Warning:
console.warn(message);
return;
}
}
}
}
}
export const loginRequest = {
scopes: ["User.Read"]
};
export const graphConfig = {
graphMeEndpoint: "Enter_the_Graph_Endpoint_Herev1.0/me"
};
And this is my index page:
import React, { useEffect } from 'react';
import type { NextPage } from "next";
import { useRouter } from 'next/router';
import { useMsal } from '#azure/msal-react';
import { useIsAuthenticated } from '#azure/msal-react';
import { loginRequest } from '../services/azureLoginApi';
const Home: NextPage = () => {
const router = useRouter()
const { instance } = useMsal()
const isAuthenticated = useIsAuthenticated()
const redirectToAzureLogin = () => {
instance.loginRedirect(loginRequest).catch((e:any) => {
console.log(e);
});
}
const redirectToDashboard = () => {
router.push('/admin/dashboard')
}
useEffect(()=>{
if(isAuthenticated)
redirectToDashboard()
else
redirectToAzureLogin()
},[])
return (
<div className="index">
</div>
);
};
export default Home;
On console, I get this message:
BrowserAuthError: interaction_in_progress: Interaction is currently in progress. Please ensure that this interaction has been completed before calling an interactive API. For more visit: aka.ms/msaljs/browser-errors.
at BrowserAuthError.AuthError [as constructor] (AuthError.js?d98c:27:1)
at new BrowserAuthError (BrowserAuthError.js?be02:197:1)
at Function.BrowserAuthError.createInteractionInProgressError (BrowserAuthError.js?be02:264:1)
at BrowserCacheManager.setInteractionInProgress (BrowserCacheManager.js?6011:886:23)
at PublicClientApplication.ClientApplication.preflightInteractiveRequest (ClientApplication.js?9c57:777:1)
at PublicClientApplication.ClientApplication.preflightBrowserEnvironmentCheck (ClientApplication.js?9c57:762:1)
at PublicClientApplication.eval (ClientApplication.js?9c57:220:1)
at step (_tslib.js?89f4:75:1)
at Object.eval [as next] (_tslib.js?89f4:56:46)
at eval (_tslib.js?89f4:49:1)
at new Promise (<anonymous>)
at __awaiter (_tslib.js?89f4:45:1)
at PublicClientApplication.ClientApplication.acquireTokenRedirect (ClientApplication.js?9c57:214:25)
at PublicClientApplication.eval (PublicClientApplication.js?1b7b:63:1)
at step (_tslib.js?89f4:75:1)
at Object.eval [as next] (_tslib.js?89f4:56:46)
at eval (_tslib.js?89f4:49:1)
at new Promise (<anonymous>)
at __awaiter (_tslib.js?89f4:45:1)
at PublicClientApplication.loginRedirect (PublicClientApplication.js?1b7b:58:25)
at redirectToAzureLogin (index.tsx?db76:18:14)
at eval (index.tsx?db76:31:7)
at invokePassiveEffectCreate (react-dom.development.js?61bb:23487:1)
at HTMLUnknownElement.callCallback (react-dom.development.js?61bb:3945:1)
at Object.invokeGuardedCallbackDev (react-dom.development.js?61bb:3994:1)
at invokeGuardedCallback (react-dom.development.js?61bb:4056:1)
at flushPassiveEffectsImpl (react-dom.development.js?61bb:23574:1)
at unstable_runWithPriority (scheduler.development.js?3069:468:1)
at runWithPriority$1 (react-dom.development.js?61bb:11276:1)
at flushPassiveEffects (react-dom.development.js?61bb:23447:1)
at eval (react-dom.development.js?61bb:23324:1)
at workLoop (scheduler.development.js?3069:417:1)
at flushWork (scheduler.development.js?3069:390:1)
at MessagePort.performWorkUntilDeadline (scheduler.development.js?3069:157:1)
The page remains blank until I give a manual refresh on it. With the manual refresh, the redirect works, but without it the page remains freezed.
I've tried some solutions on StackOverflow and other blogs but didn't work out.
Thank you all for any help you may give!
change instance.loginRirect to instance.loignPopup, that would solve that
Problem solved: the point was the useEffect without dependencies. Adding it solved the problem, now the redirect works without needing to manually update the page.
Related
I am trying to used Azure AD to integrate my application, but I keep getting this error
AuthError.ts:49 Uncaught (in promise) BrowserAuthError: interaction_in_progress: Interaction is currently in progress. Please ensure that this interaction has been completed before calling an interactive API. For more visit: aka.ms/msaljs/browser-errors.
at BrowserAuthError.AuthError [as constructor] (AuthError.ts:49:1)
at new BrowserAuthError (BrowserAuthError.ts:195:1)
at BrowserAuthError.createInteractionInProgressError (BrowserAuthError.ts:276:1)
at BrowserCacheManager.setInteractionInProgress (BrowserCacheManager.ts:1000:1)
at ClientApplication.preflightInteractiveRequest (ClientApplication.ts:837:1)
at ClientApplication.preflightBrowserEnvironmentCheck (ClientApplication.ts:820:1)
at PublicClientApplication.<anonymous> (ClientApplication.ts:272:1)
at step (vendors~main.chunk.js:217:19)
at Object.next (vendors~main.chunk.js:147:14)
at vendors~main.chunk.js:119:67
at new Promise (<anonymous>)
at __awaiter (vendors~main.chunk.js:98:10)
at ClientApplication.acquireTokenRedirect (ClientApplication.ts:268:1)
at index.tsx:50:1
This is my index.tsx file:
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import '#scuf/common/honeywell/theme.css';
import '#scuf/datatable/honeywell/theme.css';
import store from './stores';
import { Provider } from 'mobx-react';
import createRouter from './router';
import './index.scss';
import { msalConfig } from "./stores/authConfig";
import { MsalProvider, MsalAuthenticationTemplate } from "#azure/msal-react";
import { InteractionRequiredAuthError, AuthError } from "#azure/msal-common";
import { PublicClientApplication, InteractionType } from "#azure/msal-browser";
const msalInstance = new PublicClientApplication(msalConfig);
msalInstance.handleRedirectPromise()
.then((redirectResponse) => {
if (redirectResponse !== null) {
// Acquire token silent success
let accessToken = redirectResponse.accessToken;
console.log(accessToken)
// Call your API with token
} else {
// MSAL.js v2 exposes several account APIs, logic to determine which account to use is the responsibility of the developer
const activeAccount = msalInstance.getActiveAccount();
const accounts = msalInstance.getAllAccounts();
if (!activeAccount && accounts.length === 0) {
console.error("User not logged in!!!");
}
const accessTokenRequest = {
scopes: ["user.read", "openid"],
account: activeAccount || accounts[0],
// roles: ["rca.approver"],
};
msalInstance
.acquireTokenSilent(accessTokenRequest)
.then(function (accessTokenResponse) {
// Acquire token silent success
// Call API with token
let accessToken = accessTokenResponse.accessToken;
console.log(accessToken)
// Call your API with token
})
.catch(function (error) {
//Acquire token silent failure, and send an interactive request
console.log(error);
if (error instanceof InteractionRequiredAuthError || error instanceof AuthError) {
msalInstance.acquireTokenRedirect(accessTokenRequest);
}
});
}
})
// Here we are importing our stores file and spreading it across this Provider. All stores added to this will be accessible via child injects
const wrappedApp = (
<MsalProvider instance={msalInstance}>
<MsalAuthenticationTemplate interactionType={InteractionType.Redirect}>
<Provider store={store}>
<App />
</Provider>
</MsalAuthenticationTemplate>
</MsalProvider>
);
// Here the router is bootstrapped
const router = createRouter();
router.start(() => {
ReactDOM.render(wrappedApp, document.getElementById('root') as HTMLElement);
});
and this is my authConfig.js:
export const msalConfig = {
auth: {
clientId: "XXX",
authority: "https://login.microsoftonline.com/YYY",
redirectUri: "http://localhost:3000",
postLogoutRedirectUri: "http://localhost:3000",
},
cache: {
cacheLocation: "sessionStorage", // This configures where your cache will be stored
storeAuthStateInCookie: false, // Set this to "true" if you are having issues on IE11 or Edge
}
};
// Add scopes here for ID token to be used at Microsoft identity platform endpoints.
export const loginRequest = {
scopes: ["User.Read","openid"],
redirectUri: "http://localhost:3000",
};
// Add the endpoints here for Microsoft Graph API services you'd like to use.
export const graphConfig = {
graphMeEndpoint: "https://graph.microsoft.com/v1.0/me"
};
I have tried the solution in net but it still gives me the same error. These are the only two files in my project folder that deals with MSAL packages. Did I miss anything? As I learnt from the documenatation, interactionType redirects to AD authentication on which token is generated which could then be sent to APIs. Please correct me if I am wrong.
I am trying to build my own staking page for my NFT project. I cloned a repo named gem-farm from github. But I am facing with an issue when I start it at localhost.
index.js?9d03:45 TypeError: Cannot read properties of undefined (reading 'protocol')
at isURLSameOrigin (isURLSameOrigin.js?3934:57:1)
at dispatchXhrRequest (xhr.js?b50d:145:1)
at new Promise (<anonymous>)
at xhrAdapter (xhr.js?b50d:15:1)
at dispatchRequest (dispatchRequest.js?5270:58:1)
at Axios.request (Axios.js?0a06:108:1)
at Axios.<computed> [as get] (Axios.js?0a06:129:1)
at Function.wrap [as get] (bind.js?1d2b:9:1)
at _callee$ (cluster.ts?b691:26:1)
at c (blocto-sdk.umd.js?758a:3:1)
I think it is caused by this file since it is the only file using axios
Where it imports axios:
import { TOKEN_PROGRAM_ID } from '#solana/spl-token';
import axios from 'axios';
import { programs } from '#metaplex/js';
This is where it uses axios:
async function getNFTMetadata(
mint: string,
conn: Connection,
pubkey?: string
): Promise<INFT | undefined> {
// console.log('Pulling metadata for:', mint);
try {
const metadataPDA = await Metadata.getPDA(mint);
const onchainMetadata = (await Metadata.load(conn, metadataPDA)).data;
const externalMetadata = (await axios.get(onchainMetadata.data.uri)).data;
return {
pubkey: pubkey ? new PublicKey(pubkey) : undefined,
mint: new PublicKey(mint),
onchainMetadata,
externalMetadata,
};
} catch (e) {
console.log(`failed to pull metadata for token ${mint}`);
}
}
I tried it on both PC & Macos. I couldn't find any solution. Thanks.
I'm having issues with creating a class function with optional parameters. I'm plagued with the following error and since I'm a new comer to typescript I'm not really sure as to what I have to change in my code to fix it. This code works perfectly fine in an earlier project written in JS only.
It specifically highlights the getRequestOptions, when I go check it in base-service.ts in the browser error.
08:32:12.755 client.ts:22 [vite] connecting...
08:32:13.067 client.ts:52 [vite] connected.
08:32:17.043 locales-service.ts:7 getting locales
08:32:17.048 base-service.ts:19 get /Api/GetLocales/ undefined undefined undefined
08:32:17.288 base-service.ts:21 Uncaught (in promise) TypeError: Cannot read properties of undefined (reading 'getRequestOptions')
at request (base-service.ts:21)
at getLocales (locales-service.ts:9)
at setup (locale-selector.vue:22)
at callWithErrorHandling (runtime-core.esm-bundler.js:6737)
at setupStatefulComponent (runtime-core.esm-bundler.js:6346)
at setupComponent (runtime-core.esm-bundler.js:6302)
at mountComponent (runtime-core.esm-bundler.js:4224)
at processComponent (runtime-core.esm-bundler.js:4199)
at patch (runtime-core.esm-bundler.js:3791)
at mountChildren (runtime-core.esm-bundler.js:3987)
And my code
base-service.ts
import axios from '#/plugins/axios'
export default class BaseService {
getRequestOptions(url:any, method:any, data?:any, params?:any , customHeaders?:any) {
const headers = {
...customHeaders
}
return {
url:url,
method:method,
data: data,
params: params,
headers: headers,
}
}
async request(method:any, url:any, data?:any, params?:any, headers?:any) {
console.log(method,url,data,params,headers)
const options = this.getRequestOptions(method, url, data, params, headers)
try {
console.log(options)
const response = await axios(options)
console.log("Getting response from api")
console.log(response)
if (response.status === 200) {
return response.data
}
} catch (error) {
console.log(error)
}
}
}
locales-service.ts
import BaseService from '../base-service'
//?Import models in the future
//import { } from '#/common/models'
class LocaleServ extends BaseService {
async getLocales() {
console.log("getting locales")
let result = await super.request(
'get',
'/Api/GetLocales/'
)
console.log(result)
return result
}
}
export const LocaleService = new LocaleServ()
Any help would be greatly appreciated
Edit:
<script lang="ts">
import { ref } from 'vue'
import { defineComponent } from 'vue'
import CountryFlag from 'vue-country-flag-next'
import { LocaleService } from '#/services'
export default defineComponent({
name: 'LocaleSelector',
components: {
CountryFlag
},
setup () {
const { getLocales } = LocaleService
const data = getLocales()
return {
data:data
}
}
})
</script>
And then in the component I call it with {{data}}
The issue lied in the way I called the destructured getLocales() method from LocaleService in locale-service.vue
I noticed that this was undefined after attaching a debugger. According to this article, destructuring it caused it to lose it's context. Therefore when I called getLocales() in base-service.ts, this was undefined.
Simple work around to fix the, caused due to inexperience, problem was to turn.
const { getLocales } = LocaleService
const data = getLocales()
into
const data = LocaleService.getLocales()
I have a Link tag that looks like <Link href='/api/twitter/generate-auth-link'>Login with Twitter</Link>.
I have already created pages/api/twitter/generate-auth-link.ts that looks like:
import { NextApiResponse } from 'next'
import TwitterApi from 'twitter-api-v2'
import { TWITTER_CONFIG } from '../../../lib/config'
import { SERVER_URL } from '../../../utils/index'
import { NextIronRequest } from '../../../types/index'
import handler from '../../../server/api-route'
const generateAuthLink = async (
req: NextIronRequest,
res: NextApiResponse
) => {
// Generate an authentication URL
const { url, oauth_token, oauth_token_secret } = await new TwitterApi({
appKey: TWITTER_CONFIG.consumerKey,
appSecret: TWITTER_CONFIG.consumerSecret,
}).generateAuthLink(`${SERVER_URL}api/twitter/get-verifier-token`, {linkMode:'authorize'})
req.session.set(oauth_token, oauth_token_secret)
await req.session.save()
// redirect to the authentication URL
res.redirect(url)
}
export default handler().get(generateAuthLink)
When I click on it, it throws the following error:
1 of 1 unhandled error
Unhandled Runtime Error
Error: Failed to load script: /_next/static/chunks/pages/api/twitter/generate-auth-link.js
Call Stack
HTMLScriptElement.script.onerror
node_modules/next/dist/client/route-loader.js (83:51)
How do I fix it?
Reproduction → https://github.com/deadcoder0904/twitter-api-v2-3-legged-login-using-next-connect
I'm doing the Meteor + Ionic tutorial and, after having corrected several errors, I'm completely stuck with one.
Changing my main.ts code with this one
import 'meteor-client';
import { platformBrowserDynamic } from '#angular/platform-browser-dynamic';
import { MeteorObservable } from 'meteor-rxjs';
import { Meteor } from 'meteor/meteor';
import { AppModule } from './app.module';
Meteor.startup(() => {
const subscription = MeteorObservable.autorun().subscribe(() => {
if (Meteor.loggingIn()) {
return;
}
setTimeout(() => subscription.unsubscribe());
platformBrowserDynamic().bootstrapModule(AppModule);
});
});
Throws the next error
ReferenceError: Tracker is not defined at autorun
(http://localhost:8100/build/vendor.js:178469:13) at
Observable._subscribe
(http://localhost:8100/build/vendor.js:178480:27) at
Observable._trySubscribe
(http://localhost:8100/build/vendor.js:23023:25) at
Observable.subscribe (http://localhost:8100/build/vendor.js:23011:93)
at http://localhost:8100/build/main.js:57:65 at maybeReady
(http://localhost:8100/build/vendor.js:123856:57) at
HTMLDocument.loadingCompleted
(http://localhost:8100/build/vendor.js:123868:9) at t.invokeTask
(http://localhost:8100/build/polyfills.js:3:15660) at r.runTask
(http://localhost:8100/build/polyfills.js:3:10834) at e.invokeTask [as
invoke] (http://localhost:8100/build/polyfills.js:3:16794)
I've checked all the dependencies and everything is ok
My guess is that subscribe isn't directly connected to autorun. Try splitting the two up with this:
const sub = MeteorObservable.subscribe('mySubscriptionForSomeData');
const autorun = MeteorObservable.autorun();
Observable.merge(sub, autorun).subscribe(() => {
this.jobs = SomeCollection.find().zone(); // Data is ready here
}, (err) => {
console.log(err); // error fetching data
}, () => {
console.log('This will print always, whether data is fetched or err happened');
});
Source: https://github.com/Urigo/meteor-rxjs/issues/98
A fresh node install solved the problem