在应用程序中获取用于访问 API 的令牌之前,需要经身份验证的用户上下文。 若要对用户进行身份验证,可以使用弹出窗口和/或重定向登录方法。
如果应用程序可以访问经身份验证的用户上下文或 ID 令牌,则可跳过登录步骤,直接获取令牌。 有关详细信息,请参阅具有用户提示的单一登录 (SSO)。
在弹出窗口或重定向体验之间进行选择
在弹出窗口和重定向体验之间进行的选择取决于应用程序流。
通过弹出窗口登录
const config = {
auth: {
clientId: "your_app_id",
redirectUri: "your_app_redirect_uri", //defaults to application start page
postLogoutRedirectUri: "your_app_logout_redirect_uri",
},
};
const loginRequest = {
scopes: ["User.ReadWrite"],
};
let accountId = "";
const myMsal = new PublicClientApplication(config);
myMsal
.loginPopup(loginRequest)
.then(function (loginResponse) {
accountId = loginResponse.account.homeAccountId;
// Display signed-in user content, call API, etc.
})
.catch(function (error) {
//login failure
console.log(error);
});
若要调用特定路由的登录体验,请导入 @angular/router
并将 MsalGuard
添加到路由定义。
// In app-routing.module.ts
import { NgModule } from "@angular/core";
import { Routes, RouterModule } from "@angular/router";
import { ProfileComponent } from "./profile/profile.component";
import { MsalGuard } from "@azure/msal-angular";
import { HomeComponent } from "./home/home.component";
const routes: Routes = [
{
path: "profile",
component: ProfileComponent,
canActivate: [MsalGuard],
},
{
path: "",
component: HomeComponent,
},
];
@NgModule({
imports: [RouterModule.forRoot(routes, { useHash: false })],
exports: [RouterModule],
})
export class AppRoutingModule {}
若要启用弹出窗口体验,请在 MsalGuardConfiguration
中将 interactionType
配置设置为 InteractionType.Popup
。 也可传递需要同意的作用域。
// In app.module.ts
import { PublicClientApplication, InteractionType } from "@azure/msal-browser";
import { MsalModule } from "@azure/msal-angular";
@NgModule({
imports: [
MsalModule.forRoot(
new PublicClientApplication({
auth: {
clientId: "your_app_id",
},
cache: {
cacheLocation: "localStorage",
storeAuthStateInCookie: isIE,
},
}),
{
interactionType: InteractionType.Popup, // MsalGuard Configuration
authRequest: {
scopes: ["https://microsoftgraph.chinacloudapi.cn/User.Read"],
},
},
null
),
],
})
export class AppModule {}
若要在用户尚未登录时调用登录体验,请使用 @azure/msal-react
中的 MsalAuthenticationTemplate
功能。 MSAL React 包装器通过将特定组件包装在 MsalAuthenticationTemplate
组件中来对其进行保护。
import { InteractionType } from "@azure/msal-browser";
import { MsalAuthenticationTemplate, useMsal } from "@azure/msal-react";
function WelcomeUser() {
const { accounts } = useMsal();
const username = accounts[0].username;
return <p>Welcome, {username}</p>;
}
// Remember that MsalProvider must be rendered somewhere higher up in the component tree
function App() {
return (
<MsalAuthenticationTemplate interactionType={InteractionType.Popup}>
<p>This will only render if a user is not signed-in.</p>
<WelcomeUser />
</MsalAuthenticationTemplate>
);
}
若要根据用户交互(例如按钮选择)调用特定的登录体验,请使用 @azure/msal-react
中的 AuthenticatedTemplate
和/或 UnauthenticatedTemplate
功能。
import {
useMsal,
AuthenticatedTemplate,
UnauthenticatedTemplate,
} from "@azure/msal-react";
function signInClickHandler(instance) {
instance.loginPopup();
}
// SignInButton Component returns a button that invokes a popup sign in when clicked
function SignInButton() {
// useMsal hook will return the PublicClientApplication instance you provided to MsalProvider
const { instance } = useMsal();
return <button onClick={() => signInClickHandler(instance)}>Sign In</button>;
}
function WelcomeUser() {
const { accounts } = useMsal();
const username = accounts[0].username;
return <p>Welcome, {username}</p>;
}
// Remember that MsalProvider must be rendered somewhere higher up in the component tree
function App() {
return (
<>
<AuthenticatedTemplate>
<p>This will only render if a user is signed-in.</p>
<WelcomeUser />
</AuthenticatedTemplate>
<UnauthenticatedTemplate>
<p>This will only render if a user is not signed-in.</p>
<SignInButton />
</UnauthenticatedTemplate>
</>
);
}
使用重定向登录
const config = {
auth: {
clientId: "your_app_id",
redirectUri: "your_app_redirect_uri", //defaults to application start page
postLogoutRedirectUri: "your_app_logout_redirect_uri",
},
};
const loginRequest = {
scopes: ["User.ReadWrite"],
};
let accountId = "";
const myMsal = new PublicClientApplication(config);
function handleResponse(response) {
if (response !== null) {
accountId = response.account.homeAccountId;
// Display signed-in user content, call API, etc.
} else {
// In case multiple accounts exist, you can select
const currentAccounts = myMsal.getAllAccounts();
if (currentAccounts.length === 0) {
// no accounts signed-in, attempt to sign a user in
myMsal.loginRedirect(loginRequest);
} else if (currentAccounts.length > 1) {
// Add choose account code here
} else if (currentAccounts.length === 1) {
accountId = currentAccounts[0].homeAccountId;
}
}
}
myMsal.handleRedirectPromise().then(handleResponse);
若要启用重定向体验,请在 MsalGuardConfiguration
中将 interactionType
配置设置为 InteractionType.Redirect
,然后启动 MsalRedirectComponent
来处理重定向。
// In app.module.ts
import { PublicClientApplication, InteractionType } from "@azure/msal-browser";
import { MsalModule, MsalRedirectComponent } from "@azure/msal-angular";
@NgModule({
imports: [
MsalModule.forRoot(
new PublicClientApplication({
auth: {
clientId: "Enter_the_Application_Id_Here",
},
cache: {
cacheLocation: "localStorage",
storeAuthStateInCookie: isIE,
},
}),
{
interactionType: InteractionType.Redirect, // Msal Guard Configuration
authRequest: {
scopes: ["https://microsoftgraph.chinacloudapi.cn/user.read"],
},
},
null
),
],
bootstrap: [AppComponent, MsalRedirectComponent],
})
export class AppModule {}
若要在用户未登录时调用登录体验,请使用 @azure/msal-react
中的 MsalAuthenticationTemplate
功能。
import { InteractionType } from "@azure/msal-browser";
import { MsalAuthenticationTemplate, useMsal } from "@azure/msal-react";
function WelcomeUser() {
const { accounts } = useMsal();
const username = accounts[0].username;
return <p>Welcome, {username}</p>;
}
// Remember that MsalProvider must be rendered somewhere higher up in the component tree
function App() {
return (
<MsalAuthenticationTemplate interactionType={InteractionType.Redirect}>
<p>This will only render if a user is not signed-in.</p>
<WelcomeUser />
</MsalAuthenticationTemplate>
);
}
若要根据用户交互(例如按钮选择)调用特定的登录体验,请使用 @azure/msal-react
中的 AuthenticatedTemplate
和/或 UnauthenticatedTemplate
功能。
import {
useMsal,
AuthenticatedTemplate,
UnauthenticatedTemplate,
} from "@azure/msal-react";
function signInClickHandler(instance) {
instance.loginRedirect();
}
// SignInButton Component returns a button that invokes a popup login when clicked
function SignInButton() {
// useMsal hook will return the PublicClientApplication instance you provided to MsalProvider
const { instance } = useMsal();
return <button onClick={() => signInClickHandler(instance)}>Sign In</button>;
}
function WelcomeUser() {
const { accounts } = useMsal();
const username = accounts[0].username;
return <p>Welcome, {username}</p>;
}
// Remember that MsalProvider must be rendered somewhere higher up in the component tree
function App() {
return (
<>
<AuthenticatedTemplate>
<p>This will only render if a user is signed-in.</p>
<WelcomeUser />
</AuthenticatedTemplate>
<UnauthenticatedTemplate>
<p>This will only render if a user is not signed-in.</p>
<SignInButton />
</UnauthenticatedTemplate>
</>
);
}
浏览器上的退出登录行为
若要确保安全退出一个或多个应用的登录,建议使用以下方法:
有关详细信息,请参阅 Microsoft 的 Internet 隐私最佳做法。
如果用户选择不使用这些建议退出登录,以下是启用退出登录功能的其他方法:
Microsoft OpenID Connect 的前通道注销,适用于联合退出登录。当应用与新应用共享登录状态但只管理自己的会话令牌/Cookie 时,可以使用此选项。 此实现存在一些限制,即内容将被阻止,例如浏览器阻止第三方 Cookie 的情况。
弹出窗口和/或重定向,适用于本地应用退出登录。弹出窗口和重定向方法在终结点结束用户的会话,适用于本地应用。 但是,如果阻止了前通道通信,这些方法可能不会立即清除其他联合应用程序的会话。
使用弹出窗口退出登录
MSAL.js v2 及更高版本提供了一种 logoutPopup
方法,该方法可清除浏览器存储中的缓存,并打开一个指向 Microsoft Entra 退出登录页面的弹出窗口。 退出登录后,重定向默认为登录起始页,弹出窗口将关闭。
对于退出登录后的体验,可以设置 postLogoutRedirectUri
以将用户重定向到特定的 URI。 此 URI 应在应用程序注册中注册为重定向 URI。 还可配置 logoutPopup
,将 mainWindowRedirectUri
作为请求的一部分进行传递,以将主窗口重定向到其他页面,例如主页或登录页面。
const config = {
auth: {
clientId: "your_app_id",
redirectUri: "your_app_redirect_uri", // defaults to application start page
postLogoutRedirectUri: "your_app_logout_redirect_uri",
},
};
const myMsal = new PublicClientApplication(config);
// you can select which account application should sign out
const logoutRequest = {
account: myMsal.getAccountByHomeId(homeAccountId),
mainWindowRedirectUri: "your_app_main_window_redirect_uri",
};
await myMsal.logoutPopup(logoutRequest);
// In app.module.ts
@NgModule({
imports: [
MsalModule.forRoot( new PublicClientApplication({
auth: {
clientId: 'your_app_id',
postLogoutRedirectUri: 'your_app_logout_redirect_uri'
}
}), null, null)
]
})
// In app.component.ts
logout() {
this.authService.logoutPopup({
mainWindowRedirectUri: "/"
});
}
import {
useMsal,
AuthenticatedTemplate,
UnauthenticatedTemplate,
} from "@azure/msal-react";
function signOutClickHandler(instance) {
const logoutRequest = {
account: instance.getAccountByHomeId(homeAccountId),
mainWindowRedirectUri: "your_app_main_window_redirect_uri",
postLogoutRedirectUri: "your_app_logout_redirect_uri",
};
instance.logoutPopup(logoutRequest);
}
// SignOutButton component returns a button that invokes a pop-up sign out when clicked
function SignOutButton() {
// useMsal hook will return the PublicClientApplication instance you provided to MsalProvider
const { instance } = useMsal();
return (
<button onClick={() => signOutClickHandler(instance)}>Sign Out</button>
);
}
// Remember that MsalProvider must be rendered somewhere higher up in the component tree
function App() {
return (
<>
<AuthenticatedTemplate>
<p>This will only render if a user is signed-in.</p>
<SignOutButton />
</AuthenticatedTemplate>
<UnauthenticatedTemplate>
<p>This will only render if a user is not signed-in.</p>
</UnauthenticatedTemplate>
</>
);
}
使用重定向退出登录
MSAL.js 在 v1 中提供了 logout
方法,在 v2 中提供了 logoutRedirect
方法,该方法可清除浏览器存储中的缓存,并重定向到 Microsoft Entra 退出登录页面。 退出登录后,重定向默认为登录起始页。
对于退出登录后的体验,可以设置 postLogoutRedirectUri
以将用户重定向到特定的 URI。 此 URI 应在应用程序注册中注册为重定向 URI。
由于此方法不显示 Microsoft 关于使用隐私浏览器和锁屏界面的 Internet 隐私最佳做法的提醒,因此你可能需要描述最佳做法并提醒用户关闭所有浏览器窗口。
const config = {
auth: {
clientId: "your_app_id",
redirectUri: "your_app_redirect_uri", //defaults to application start page
postLogoutRedirectUri: "your_app_logout_redirect_uri",
},
};
const myMsal = new PublicClientApplication(config);
// you can select which account application should sign out
const logoutRequest = {
account: myMsal.getAccountByHomeId(homeAccountId),
};
myMsal.logoutRedirect(logoutRequest);
// In app.module.ts
@NgModule({
imports: [
MsalModule.forRoot( new PublicClientApplication({
auth: {
clientId: 'your_app_id',
postLogoutRedirectUri: 'your_app_logout_redirect_uri'
}
}), null, null)
]
})
// In app.component.ts
logout() {
this.authService.logoutRedirect();
}
import {
useMsal,
AuthenticatedTemplate,
UnauthenticatedTemplate,
} from "@azure/msal-react";
function signOutClickHandler(instance) {
const logoutRequest = {
account: instance.getAccountByHomeId(homeAccountId),
postLogoutRedirectUri: "your_app_logout_redirect_uri",
};
instance.logoutRedirect(logoutRequest);
}
// SignOutButton Component returns a button that invokes a redirect logout when clicked
function SignOutButton() {
// useMsal hook will return the PublicClientApplication instance you provided to MsalProvider
const { instance } = useMsal();
return (
<button onClick={() => signOutClickHandler(instance)}>Sign Out</button>
);
}
// Remember that MsalProvider must be rendered somewhere higher up in the component tree
function App() {
return (
<>
<AuthenticatedTemplate>
<p>This will only render if a user is signed-in.</p>
<SignOutButton />
</AuthenticatedTemplate>
<UnauthenticatedTemplate>
<p>This will only render if a user is not signed-in.</p>
</UnauthenticatedTemplate>
</>
);
}
后续步骤
转到此方案中的下一篇文章:获取应用的令牌。