I am creating a POC for a razor app to make calls to a local phone number using Azure/Teams/Graph or whatever mechanism. My app authenticates right, but for any reason when it tries to start the call, it gives me a forbidden. the user has admin privilege of the account, and I don't know if the problem is related to the kind of Azure account or maybe there's something bad in my implementation.
In my front, this is the code.
@model CallRequest
<form asp-controller="Home" asp-action="CreateOnlineMeeting" method="post">
<div class="form-group">
<label for="PhoneNumber">Phone</label>
<input type="text" class="form-control" id="PhoneNumber" name="PhoneNumber" value="+18499999999" />
</div>
<div class="form-group">
<label for="DurationInMinutes">Duration</label>
<input type="number" class="form-control" id="DurationInMinutes" name="DurationInMinutes" value="30" />
</div>
<div class="form-group">
<label for="DisplayName">Name</label>
<input type="text" class="form-control" id="DisplayName" name="DisplayName" value="User Name From the other people" />
</div>
</form>
<button id="callButton" onclick="initiateCall()">Call</button>
<script src="https://alcdn.msauth.net/browser/2.22.1/js/msal-browser.min.js" integrity="sha384-nCTmWvEOevLDR1A0WzHvi1PbktdL8pPPACO2UYs9NPp+TCEz0hE0c8JmMxRlNSjh" crossorigin="anonymous"></script>
<script>
const msalConfig = {
auth: {
clientId: "CLIENTAPPID",
authority: "https://login.microsoftonline.com/TENANTID",
redirectUri: window.location.href,
},
cache: {
cacheLocation: "sessionStorage",
storeAuthStateInCookie: false,
},
};
const msalInstance = new msal.PublicClientApplication(msalConfig);
async function getTokenWithClientCredentials() {
const response = await fetch('/Home/GetToken', {
method: 'POST',
});
if (response.ok) {
return await response.text();
} else {
throw new Error('Error getting the token');
}
}
//async function signInAndGetToken() {
// const loginRequest = {
// scopes: ["https://graph.microsoft.com/.default"],
// };
// try {
// const silentRequest = {
// ...loginRequest,
// account: msalInstance.getActiveAccount(),
// };
// const silentResult = await msalInstance.acquireTokenSilent(silentRequest);
// return silentResult.accessToken;
// } catch (error) {
// if (error instanceof msal.InteractionRequiredAuthError) {
// const interactiveResult = await msalInstance.acquireTokenPopup(loginRequest);
// return interactiveResult.accessToken;
// }
// else {
// console.error("Error to get the token:", error);
// throw error;
// }
// }
//}
async function getMicrophonePermission() {
try {
const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
stream.getTracks().forEach(track => track.stop());
return true;
} catch (error) {
console.error("Error to get mic permissions:", error);
return false;
}
}
async function signIn() {
const loginRequest = {
scopes: ["openid", "profile", "https://graph.microsoft.com/.default"],
};
try {
const loginResponse = await msalInstance.loginPopup(loginRequest);
const account = msalInstance.getAccountByHomeId(loginResponse.account.homeAccountId);
msalInstance.setActiveAccount(account);
} catch (error) {
console.error("Error during login:", error);
}
}
// async function signIn() {
// const loginRequest = {
// scopes: ["openid", "profile", "https://graph.microsoft.com/.default"],
// };
// try {
// const loginResponse = await msalInstance.loginPopup(loginRequest);
// const account = msalInstance.getAccountByHomeId(loginResponse.account.homeAccountId);
// msalInstance.setActiveAccount(account);
// } catch (error) {
// console.error("Error during login:", error);
// }
//}
async function getUserId(token) {
const response = await fetch('https://graph.microsoft.com/v1.0/me', {
method: 'GET',
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json',
},
});
if (response.ok) {
const userData = await response.json();
return userData.id;
} else {
const errorDetails = await response.text();
console.error("Error to get user Id", response.statusText, errorDetails);
throw new Error('Error to get user Id');
}
}
async function initiateCall() {
const hasMicrophonePermission = await getMicrophonePermission();
if (!hasMicrophonePermission) {
console.error("We can´t access to mic");
return;
}
try {
// const token = await signInAndGetToken();
const token = await getTokenWithClientCredentials();
console.log(token);
const userId = 'FIXEDUSERID';// await getUserId(token);
const phoneNumber = '+1PHONENUMBER'; // document.getElementById("PhoneNumber").value;
const callRequest = {
"@@odata.type": "#microsoft.graph.call",
"callbackUri": "https://callback.example.com",
"targets": [
{
"@@odata.type": "#microsoft.graph.invitationParticipantInfo",
"identity": {
"@@odata.type": "#microsoft.graph.identitySet",
"phone": {
"@@odata.type": "#microsoft.graph.phoneNumberIdentity",
"id": phoneNumber.replace(/\D/g, ''),
},
},
},
],
"requestedModalities": ["audio"],
"mediaConfig": {
"@@odata.type": "#microsoft.graph.serviceHostedMediaConfig",
},
"meetingInfo": {
"@@odata.type": "#microsoft.graph.organizerMeetingInfo",
"organizer": {
"@@odata.type": "#microsoft.graph.identitySet",
"user": {
"@@odata.type": "#microsoft.graph.identity",
"id": userId,
},
},
},
};
const response = await fetch("https://graph.microsoft.com/v1.0/communications/calls", {
method: "POST",
headers: {
"Authorization": `Bearer ${token}`,
"Content-Type": "application/json",
},
body: JSON.stringify(callRequest),
});
if (response.ok) {
const call = await response.json();
console.log("Call Started:", call);
} else {
const errorDetails = await response.text();
console.error("Error to Start the call:", response.statusText, errorDetails);
}
} catch (error) {
console.error("Error to start the call:", error);
}
}
</script>
and in the back I have this
[HttpPost]
public async Task<string> GetToken()
{
string clientId = "AppCLIENTID";
string clientSecret = "APPSECRET";
string tenantId = "TENANTID";
string scope = "https://graph.microsoft.com/.default";
using (HttpClient client = new HttpClient())
{
var requestBody = new FormUrlEncodedContent(new[]
{
new KeyValuePair<string, string>("grant_type", "client_credentials"),
new KeyValuePair<string, string>("client_id", clientId),
new KeyValuePair<string, string>("client_secret", clientSecret),
new KeyValuePair<string, string>("scope", scope),
});
HttpResponseMessage response = await client.PostAsync($"https://login.microsoftonline.com/{tenantId}/oauth2/v2.0/token", requestBody);
if (response.IsSuccessStatusCode)
{
string jsonResponse = await response.Content.ReadAsStringAsync();
JObject json = JObject.Parse(jsonResponse);
return json["access_token"].ToString();
}
else
{
throw new Exception("Error to get the token");
}
}
}
This is all the privilege than have the app.
from Issue creating a call in Microsoft Graph
No comments:
Post a Comment