使用 MSAL React 调用 API
Calling an API with MSAL React
我正在尝试使用 Azure AD 保护 API 并从 React SPA 调用它,但我 运行 遇到了 401 未授权错误。我不太确定我做错了什么。
里面appsettings.json
"AzureAD": {
"Instance": "https://login.microsoft.com",
"Domain": "<MyAdDomain>",
"TenantId": "<MyTenantId>",
"ClientId": "<MyApiAppId>",
"Scope": "<MyApiScope>"
}
然后 StartUp.cs
var tenantId = $"{Configuration["AzureAD:TenantId"]}";
var authority = $"{Configuration["AzureAD:Instance"]}/{tenantId}";
var audience = new List<string>
{
$"{Configuration["AzureAD:ClientId"]}",
$"{Configuration["AzureAD:Scope"]}"
};
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.Authority = authority;
options.TokenValidationParameters = new Microsoft.IdentityModel.Tokens.TokenValidationParameters
{
ValidAudiences = audience,
ValidIssuers = new List<string>
{
$"https://sts.windows.net/{tenantId}",
$"https://sts.windows.net/{tenantId}/v2.0",
}
};
});
同时,在我的 React 应用程序中,我使用具有以下配置的 MsalProvider 对其进行保护:
authConfig.ts
export const msalConfig: Configuration = {
auth: {
clientId: "<MyClientApiId>",
authority:
"https://login.microsoftonline.com/<MyTenantId>",
redirectUri: "/",
},
cache: {
cacheLocation: "sessionStorage",
storeAuthStateInCookie: false,
},
// other code
App.tsx
const msalInstance = new PublicClientApplication(msalConfig);
function App() {
return (
<MsalProvider instance={msalInstance}>
<BrowserRouter>
<Routes>
<Route path="/" element={<HomePage />} />
<Route path="/dealer/:accountNumber" element={<DealerContainer />} />
</Routes>
</BrowserRouter>
</MsalProvider>
);
然后在里面 HomePage.tsx:
const getCompanies = useCallback(async () => {
if (isAuthenticated) {
const silentRequest: SsoSilentRequest = {
scopes: ["<MyApiScope>"],
loginHint: instance.getActiveAccount()?.username,
};
const token = await instance.ssoSilent(silentRequest);
const companies = await getCompaniesAsync(token);
setCompaniesList(companies);
setFullCompaniesList(companies);
}
}, [instance, isAuthenticated]);
关于我在这里做错了什么的任何见解?谢谢!
从 Tiny Wang 的评论中获得了一些见解,我最终浏览了一些其他文档并进行了一些 Postman 测试
里面 HomePage.tsx:
const getCompanies = useCallback(async () => {
if (isAuthenticated) {
const account = instance.getAllAccounts()[0];
const silentRequest = {
scopes: ["api://<MyApiAppId>/access_user_data"],
account: account,
};
const token: AuthenticationResult = await instance.acquireTokenSilent(
silentRequest
);
const companies = await getCompaniesAsync(token.accessToken);
// rest of the code here
"AzureAd": {
"Instance": "https://login.microsoft.com",
"Domain": "<MyDomain>",
"TenantId": "<MyTenantId>",
"ClientId": "api://<MyApiAppId>",
"Audience": "<MyFrontEndAppId>",
"Scope": "api://<MyApiAppId>/access_user_data"
},
出于某种原因,ClientId 正在请求 URI 而不仅仅是 ID。
我正在尝试使用 Azure AD 保护 API 并从 React SPA 调用它,但我 运行 遇到了 401 未授权错误。我不太确定我做错了什么。
里面appsettings.json
"AzureAD": {
"Instance": "https://login.microsoft.com",
"Domain": "<MyAdDomain>",
"TenantId": "<MyTenantId>",
"ClientId": "<MyApiAppId>",
"Scope": "<MyApiScope>"
}
然后 StartUp.cs
var tenantId = $"{Configuration["AzureAD:TenantId"]}";
var authority = $"{Configuration["AzureAD:Instance"]}/{tenantId}";
var audience = new List<string>
{
$"{Configuration["AzureAD:ClientId"]}",
$"{Configuration["AzureAD:Scope"]}"
};
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.Authority = authority;
options.TokenValidationParameters = new Microsoft.IdentityModel.Tokens.TokenValidationParameters
{
ValidAudiences = audience,
ValidIssuers = new List<string>
{
$"https://sts.windows.net/{tenantId}",
$"https://sts.windows.net/{tenantId}/v2.0",
}
};
});
同时,在我的 React 应用程序中,我使用具有以下配置的 MsalProvider 对其进行保护:
authConfig.ts
export const msalConfig: Configuration = {
auth: {
clientId: "<MyClientApiId>",
authority:
"https://login.microsoftonline.com/<MyTenantId>",
redirectUri: "/",
},
cache: {
cacheLocation: "sessionStorage",
storeAuthStateInCookie: false,
},
// other code
App.tsx
const msalInstance = new PublicClientApplication(msalConfig);
function App() {
return (
<MsalProvider instance={msalInstance}>
<BrowserRouter>
<Routes>
<Route path="/" element={<HomePage />} />
<Route path="/dealer/:accountNumber" element={<DealerContainer />} />
</Routes>
</BrowserRouter>
</MsalProvider>
);
然后在里面 HomePage.tsx:
const getCompanies = useCallback(async () => {
if (isAuthenticated) {
const silentRequest: SsoSilentRequest = {
scopes: ["<MyApiScope>"],
loginHint: instance.getActiveAccount()?.username,
};
const token = await instance.ssoSilent(silentRequest);
const companies = await getCompaniesAsync(token);
setCompaniesList(companies);
setFullCompaniesList(companies);
}
}, [instance, isAuthenticated]);
关于我在这里做错了什么的任何见解?谢谢!
从 Tiny Wang 的评论中获得了一些见解,我最终浏览了一些其他文档并进行了一些 Postman 测试
里面 HomePage.tsx:
const getCompanies = useCallback(async () => {
if (isAuthenticated) {
const account = instance.getAllAccounts()[0];
const silentRequest = {
scopes: ["api://<MyApiAppId>/access_user_data"],
account: account,
};
const token: AuthenticationResult = await instance.acquireTokenSilent(
silentRequest
);
const companies = await getCompaniesAsync(token.accessToken);
// rest of the code here
"AzureAd": {
"Instance": "https://login.microsoft.com",
"Domain": "<MyDomain>",
"TenantId": "<MyTenantId>",
"ClientId": "api://<MyApiAppId>",
"Audience": "<MyFrontEndAppId>",
"Scope": "api://<MyApiAppId>/access_user_data"
},
出于某种原因,ClientId 正在请求 URI 而不仅仅是 ID。