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>
);

,然后在首页。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。

最新更新