在 App Service 上部署后反应 msal-browser 不工作
React msal-browser not working after deploy on App Service
我使用“msal-browser”和“msal-react”创建了与 Azure AD B2C 集成的 React 应用程序。如果用户未登录,应用程序重定向到 AD 授权,如果用户登录,应用程序让用户使用整个应用程序。
一切都在当地运作良好。当我将应用程序部署到 Azure 应用程序服务时出现问题。
打开应用程序后,我正确地重定向到登录页面。登录后,我陷入了无限循环。 Url 从 https://domain.azurewebsites.net/ to https://domain.azurewebsites.net/#state=[...] and again to https://domain.azurewebsites.net/ and again to https://domain.azurewebsites.net/#state=[...] 等不断变化
在开发控制台中出现错误:POST
https://{tenant}.b2clogin.com/{tenant}.onmicrosoft.com/{signUpSignInPolicies}/oauth2/v2.0/token 400 (Bad Request)
这是我的代码:
App.tsx:
function App() {
return (
<MainRoutes />
);
}
export default withAuthHOC(App);
withAuthHOC.tsx:
const withAuthHOC = (WrappedComponent: React.FunctionComponent) => {
return () => {
const pca = new PublicClientApplication(msalConfig);
useMsalRedirect();
return (
<MsalProvider instance={pca}>
<AuthenticatedValidation />
<AuthenticatedTemplate>
<WrappedComponent />
</AuthenticatedTemplate>
</MsalProvider>
);
}
};
export default withAuthHOC;
useMsalRedirect.tsx:
const useMsalRedirect = () => {
const { instance } = useMsal();
useEffect(() => {
const callbackId = instance.addEventCallback((event: any) => {
if (event.eventType === EventType.LOGIN_FAILURE) {
if (event.error && event.error.errorMessage.indexOf("AADB2C90118") > -1) {
if (event.interactionType === InteractionType.Redirect) {
instance.loginRedirect(b2cPolicies.authorities.forgotPassword as RedirectRequest);
} else if (event.interactionType === InteractionType.Popup) {
instance.loginPopup(b2cPolicies.authorities.forgotPassword as RedirectRequest)
.catch(e => {
return;
});
}
}
}
if (event.eventType === EventType.LOGIN_SUCCESS || event.eventType === EventType.ACQUIRE_TOKEN_SUCCESS) {
if (event?.payload) {
if (event.payload.idTokenClaims["tfp"] === b2cPolicies.names.forgotPassword) {
window.alert("Password has been reset successfully. \nPlease sign-in with your new password.");
return instance.logout();
} else if (event.payload.idTokenClaims["tfp"] === b2cPolicies.names.editProfile) {
window.alert("Profile has been edited successfully. \nPlease sign-in again.");
return instance.logout();
}
}
}
});
return () => {
if (callbackId) {
instance.removeEventCallback(callbackId);
}
};
}, [instance]);
}
export default useMsalRedirect;
AuthenticatedValidation.tsx:
export const AuthenticatedValidation = () => {
const isAuthenticated = useIsAuthenticated();
const { instance, inProgress } = useMsal();
useEffect(() => {
if (inProgress === InteractionStatus.None && !isAuthenticated) {
instance.loginRedirect(loginRequest);
}
});
return null;
}
export default AuthenticatedValidation;
authConfig.js
import { LogLevel } from "@azure/msal-browser";
export const b2cPolicies = {
names: {
signUpSignIn: "B2C_1A_signup_signin",
forgotPassword: "B2C_1_passwordreset",
editProfile: "B2C_1_profileediting"
},
authorities: {
signUpSignIn: {
authority: "https://{tenant}.b2clogin.com/{tenant}.onmicrosoft.com/B2C_1A_signup_signin",
},
forgotPassword: {
authority: "https://{tenant}.b2clogin.com/{tenant}.onmicrosoft.com/B2C_1_passwordreset",
},
editProfile: {
authority: "https://{tenant}.b2clogin.com/{tenant}.onmicrosoft.com/B2C_1_profileediting"
}
},
authorityDomain: "{tenant}.b2clogin.com"
}
export const msalConfig = {
auth: {
clientId: "{clientId}",
authority: b2cPolicies.authorities.signUpSignIn.authority,
knownAuthorities: [b2cPolicies.authorityDomain],
redirectUri: "https://domain.azurewebsites.net/", //localhost: "/"
postLogoutRedirectUri: "https://domain.azurewebsites.net/", //localhost: "/"
navigateToLoginRequestUrl: false,
},
cache: {
cacheLocation: "sessionStorage",
storeAuthStateInCookie: false,
},
system: {
loggerOptions: {
loggerCallback: (level, message, containsPii) => {
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;
default:
return;
}
}
}
}
};
export const loginRequest = {
scopes: ['openid', 'profile'],
};
我使用 visual studio 代码部署应用程序。我的应用程序服务是带有启动命令的 Node 12 LTS:pm2 serve /home/site/wwwroot/build --no-daemon --spa
在 Azure AD B2C 属性中我有:
Inculde web app/web API: Yes
Allow implict flow: yes
Replay URLs and redirect URIs: https://domain.azurewebsites.net/ and https://localhost:3000
App ID URI: https://{tenant}.onmicrosoft.com/{clientId}
Include native client: yes
我的 signUpSignIn 策略是使用身份体验框架创建的。
该应用程序在本地主机上运行良好。将 export default with Auth HOC (App);
更改为 export default App;
后。该应用程序在 azure 上运行良好(禁用授权)。因此,我认为问题出在 authConfig.js
文件的配置上。有人知道我做错了什么吗?
我通过将实例化 PublicClientApplication 移动到反应组件之外解决了这个问题 - 索引 tsx
我使用“msal-browser”和“msal-react”创建了与 Azure AD B2C 集成的 React 应用程序。如果用户未登录,应用程序重定向到 AD 授权,如果用户登录,应用程序让用户使用整个应用程序。
一切都在当地运作良好。当我将应用程序部署到 Azure 应用程序服务时出现问题。
打开应用程序后,我正确地重定向到登录页面。登录后,我陷入了无限循环。 Url 从 https://domain.azurewebsites.net/ to https://domain.azurewebsites.net/#state=[...] and again to https://domain.azurewebsites.net/ and again to https://domain.azurewebsites.net/#state=[...] 等不断变化
在开发控制台中出现错误:POST
https://{tenant}.b2clogin.com/{tenant}.onmicrosoft.com/{signUpSignInPolicies}/oauth2/v2.0/token 400 (Bad Request)
这是我的代码: App.tsx:
function App() {
return (
<MainRoutes />
);
}
export default withAuthHOC(App);
withAuthHOC.tsx:
const withAuthHOC = (WrappedComponent: React.FunctionComponent) => {
return () => {
const pca = new PublicClientApplication(msalConfig);
useMsalRedirect();
return (
<MsalProvider instance={pca}>
<AuthenticatedValidation />
<AuthenticatedTemplate>
<WrappedComponent />
</AuthenticatedTemplate>
</MsalProvider>
);
}
};
export default withAuthHOC;
useMsalRedirect.tsx:
const useMsalRedirect = () => {
const { instance } = useMsal();
useEffect(() => {
const callbackId = instance.addEventCallback((event: any) => {
if (event.eventType === EventType.LOGIN_FAILURE) {
if (event.error && event.error.errorMessage.indexOf("AADB2C90118") > -1) {
if (event.interactionType === InteractionType.Redirect) {
instance.loginRedirect(b2cPolicies.authorities.forgotPassword as RedirectRequest);
} else if (event.interactionType === InteractionType.Popup) {
instance.loginPopup(b2cPolicies.authorities.forgotPassword as RedirectRequest)
.catch(e => {
return;
});
}
}
}
if (event.eventType === EventType.LOGIN_SUCCESS || event.eventType === EventType.ACQUIRE_TOKEN_SUCCESS) {
if (event?.payload) {
if (event.payload.idTokenClaims["tfp"] === b2cPolicies.names.forgotPassword) {
window.alert("Password has been reset successfully. \nPlease sign-in with your new password.");
return instance.logout();
} else if (event.payload.idTokenClaims["tfp"] === b2cPolicies.names.editProfile) {
window.alert("Profile has been edited successfully. \nPlease sign-in again.");
return instance.logout();
}
}
}
});
return () => {
if (callbackId) {
instance.removeEventCallback(callbackId);
}
};
}, [instance]);
}
export default useMsalRedirect;
AuthenticatedValidation.tsx:
export const AuthenticatedValidation = () => {
const isAuthenticated = useIsAuthenticated();
const { instance, inProgress } = useMsal();
useEffect(() => {
if (inProgress === InteractionStatus.None && !isAuthenticated) {
instance.loginRedirect(loginRequest);
}
});
return null;
}
export default AuthenticatedValidation;
authConfig.js
import { LogLevel } from "@azure/msal-browser";
export const b2cPolicies = {
names: {
signUpSignIn: "B2C_1A_signup_signin",
forgotPassword: "B2C_1_passwordreset",
editProfile: "B2C_1_profileediting"
},
authorities: {
signUpSignIn: {
authority: "https://{tenant}.b2clogin.com/{tenant}.onmicrosoft.com/B2C_1A_signup_signin",
},
forgotPassword: {
authority: "https://{tenant}.b2clogin.com/{tenant}.onmicrosoft.com/B2C_1_passwordreset",
},
editProfile: {
authority: "https://{tenant}.b2clogin.com/{tenant}.onmicrosoft.com/B2C_1_profileediting"
}
},
authorityDomain: "{tenant}.b2clogin.com"
}
export const msalConfig = {
auth: {
clientId: "{clientId}",
authority: b2cPolicies.authorities.signUpSignIn.authority,
knownAuthorities: [b2cPolicies.authorityDomain],
redirectUri: "https://domain.azurewebsites.net/", //localhost: "/"
postLogoutRedirectUri: "https://domain.azurewebsites.net/", //localhost: "/"
navigateToLoginRequestUrl: false,
},
cache: {
cacheLocation: "sessionStorage",
storeAuthStateInCookie: false,
},
system: {
loggerOptions: {
loggerCallback: (level, message, containsPii) => {
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;
default:
return;
}
}
}
}
};
export const loginRequest = {
scopes: ['openid', 'profile'],
};
我使用 visual studio 代码部署应用程序。我的应用程序服务是带有启动命令的 Node 12 LTS:pm2 serve /home/site/wwwroot/build --no-daemon --spa
在 Azure AD B2C 属性中我有:
Inculde web app/web API: Yes
Allow implict flow: yes
Replay URLs and redirect URIs: https://domain.azurewebsites.net/ and https://localhost:3000
App ID URI: https://{tenant}.onmicrosoft.com/{clientId}
Include native client: yes
我的 signUpSignIn 策略是使用身份体验框架创建的。
该应用程序在本地主机上运行良好。将 export default with Auth HOC (App);
更改为 export default App;
后。该应用程序在 azure 上运行良好(禁用授权)。因此,我认为问题出在 authConfig.js
文件的配置上。有人知道我做错了什么吗?
我通过将实例化 PublicClientApplication 移动到反应组件之外解决了这个问题 - 索引 tsx