Forum Discussion
leon_guo
Jul 12, 2023Copper Contributor
Microsoft Graph API AxiosError: Request failed 404 and Resource Could Not be Discovered
We are calling:
GET all events in my calendar from https://developer.microsoft.com/en-us/graph/graph-explorer
https://graph.microsoft.com/v1.0/me/events?$select=subject,body,bodyPreview,organizer,attendees,start,end,location
We granted:
Calendar.Read, Calendars.ReadBasic, Calendars.ReadWrite
The code:
window.ipc.sendMessage("msalLogin");
window.ipc.callFor("access-storage", "get", "msal.account").then(console.log)window.ipc.callFor("msalGraphApi", "/me/events?$select=subject,bodyPreview,organizer,attendees,start,end,location").then(console.log)
Logs in, gets the access token, and then calls the api. First two steps work, step three fails.
Not sure what is going on, tried everything. Can you please help me diagnose and resolve this? Thanks!
1 Reply
- leon_guoCopper Contributor/* eslint-disable no-return-await */
import {
Configuration,
LogLevel,
PublicClientApplication,
AccountInfo,
AuthenticationResult,
SilentFlowRequest,
} from '@azure/msal-node';
import { MsalInfo } from '../constants';
import { Axios } from 'axios';
import * as AxiosPack from './axios';
export default class MsalProvider {
scopes: string[] = [
'user.read',
'profile',
'teamsactivity.read',
'reports.read.all',
'user.read.all',
'group.read.all',
'onlinemeetingartifact.read.all',
];
private account: AccountInfo | undefined = undefined;
private readonly axios;
private readonly msalPublicClient: PublicClientApplication;
constructor(
private redirectUri: string = MsalInfo.REDIRECT_URI,
private readonly config: Configuration = {
auth: {
clientId: process.env.MSAL_CLIENT_ID as string,
authority:
process.env.MSAL_AUTHORITY_URL ?? MsalInfo.COMMON_AUTHORITY_URL,
clientSecret: process.env.MSAL_CLIENT_SECRET ?? undefined,
},
cache: undefined,
system: {
loggerOptions: {
loggerCallback: (lvl, msg, containsPi) => {
// TODO
},
piiLoggingEnabled: false,
logLevel: LogLevel.Warning,
},
},
}
) {
this.msalPublicClient = new PublicClientApplication(this.config);
this.axios = AxiosPack.msal();
}
public setScopes(data: string[]) {
this.scopes = data;
return this;
}
public setRedirectUri(uri: string) {
this.redirectUri = uri;
}
public async logout() {
if (this.account) {
await this.msalPublicClient.getTokenCache().removeAccount(this.account);
this.account = undefined;
}
}
public async getAuthUrl(
redirectUri: string = this.redirectUri,
scopes: string[] = this.scopes
) {
return await this.msalPublicClient.getAuthCodeUrl({
scopes,
redirectUri,
prompt: MsalInfo.promptType.SELECT_ACCOUNT.toString(),
});
}
public async getTokenByCode(
authCode: string,
redirectUri: string = this.redirectUri,
scopes: string[] = this.scopes
) {
const result = await this.msalPublicClient.acquireTokenByCode({
scopes,
redirectUri,
code: authCode ?? '',
});
this.setAccountFromResponse(result);
return result;
}
public async getAccessToken(
returnString: boolean = false,
scopes: string[] = this.scopes
) {
const account = this.account || (await this.getAccount());
if (account) {
const authResponse = await this.getTokenSilent({
account,
scopes,
forceRefresh: false,
});
if (authResponse && authResponse !== null) {
if (returnString) return authResponse.accessToken;
return authResponse;
}
}
}
public async getTokenSilent(
tokenRequest: SilentFlowRequest
😞 Promise<AuthenticationResult | null | undefined> {
try {
return await this.msalPublicClient.acquireTokenSilent(tokenRequest);
} catch (error) {
return null;
}
}
public async setAccountFromResponse(response: AuthenticationResult) {
if (response) {
this.account = response?.account || undefined;
} else {
this.account = await this.getAccount();
}
return this.account;
}
public async getAccount() {
const cache = this.msalPublicClient.getTokenCache();
const currentAccounts = await cache?.getAllAccounts();
if (currentAccounts && currentAccounts?.length! >= 1) {
return currentAccounts[0];
}
return undefined;
}
async getEndpoint<T extends unknown>(
token: string,
resource: string
😞 Promise<T> {
try {
const response = await this.axios(token).get<T>(resource);
return response.data;
} catch (error) {
const err: { data: { error: unknown } } = error as {
data: { error: unknown };
};
console.error(err.data);
throw error;
}
}
}