Microsoft graph calling/communication SDK not working with MediaSession - microsoft-graph-api

I am making calls to teams user using Graph Communication SDK with local machine.I am using ngork for making local machine endpoints public. I can make call to teams user without using MediaSession but when I use Media Session call is not reaching to teams user and it is not giving any error.Need help to find out issue.I am referring examples from this doc- https://github.com/microsoftgraph/microsoft-graph-comms-samples/tree/master/Samples/V1.0Samples/LocalMediaSamples
Working Call:
var mediaToPrefetch = new List<MediaInfo>();
var call = new Call()
{
Targets = new[] { target },
MediaConfig = new ServiceHostedMediaConfig { PreFetchMedia = mediaToPrefetch },
RequestedModalities = new List<Modality> { Modality.Audio, Modality.Video, Modality.VideoBasedScreenSharing },
TenantId = joinCallBody.TenantId,
};
var statefulCall = await this.Client.Calls().AddAsync(call, scenarioId: scenarioId).ConfigureAwait(false);
Non Working Call:
var mediaSession=this.CreateMediaSession();
var mediaToPrefetch = new List<MediaInfo>();
var call = new Call()
{
Targets = new[] { target },
MediaConfig = new ServiceHostedMediaConfig { PreFetchMedia = mediaToPrefetch },
RequestedModalities = new List<Modality> { Modality.Audio, Modality.Video, Modality.VideoBasedScreenSharing },
TenantId = joinCallBody.TenantId,
};
var statefulCall = await this.Client.Calls().AddAsync(call, scenarioId: scenarioId,mediaSession:mediaSession).ConfigureAwait(false);

Those samples refer to application-hosted media bots: https://learn.microsoft.com/en-us/microsoftteams/platform/bots/calls-and-meetings/requirements-considerations-application-hosted-media-bots
Did you follow all the steps to register the bot app? https://github.com/microsoftgraph/microsoft-graph-comms-samples/tree/master/Samples/V1.0Samples/LocalMediaSamples/PolicyRecordingBot#bot-registration
You need to explicitly add permissions to access media, and later to grant by an administrator of the azure account.
If you did all that, could you please share what kind of exception/error are you getting?

Related

How do I access Outlook365 mailbox using impersonation using .NET?

I'm using this code:
var cca = ConfidentialClientApplicationBuilder
.Create(clientId)
.WithClientSecret(clientSecret)
.WithTenantId(tenantId)
.Build();
var ewsScopes = new [] { "https://outlook.office365.com/.default" };
var authResult = await cca.AcquireTokenForClient(ewsScopes).ExecuteAsync(cancellationToken);
var service = new ExchangeService
{
Credentials = new OAuthCredentials(authResult.AccessToken),
Url = new Uri("https://outlook.office365.com/EWS/Exchange.asmx"),
ImpersonatedUserId = new ImpersonatedUserId(ConnectingIdType.SmtpAddress, "mailbox#user.com"),
TraceListener = new TraceListener(),
TraceEnabled = true,
TraceFlags = TraceFlags.All
};
Folder inbox = Folder.Bind(service, WellKnownFolderName.Inbox);
The code throws a ServiceRequestException (403) on the last line, and trace logs contains the error:
x-ms-diagnostics: 2000008;reason="The token contains not enough scope to make this call.";error_category="invalid_grant"
Do I need to expand the ewsScopes? Or is this because I'm lacking the correct permissions in Azure? Which roles/permissions do I need?
Check the token your using in
Credentials = new OAuthCredentials(authResult.AccessToken),
in jwt.io
What you should see in the roles is
If you don't have that role it means your application registration isn't correct (eg you have added the delegate permission instead of Application permission which is a common mistake).

The given token is invalid error in EWS OAuth authentication when using personal account

I have to get the contacts from Exchange server from any account, so we have used the code from below link.
https://learn.microsoft.com/en-us/exchange/client-developer/exchange-web-services/how-to-authenticate-an-ews-application-by-using-oauth
But it is not working for personal accounts, which is working fine for our organization account. So I have used AadAuthorityAudience property instead of TenantId and changed the scope from EWS.AccessAsUser.All to others. Now authentication got success but getting "The given token is invalid" error while using the token in ExchangeService.
var pcaOptions = new PublicClientApplicationOptions {
ClientId = "77xxxxxxxxxxx92324",
//TenantId = "7887xxxxxxxxxxxxx14",
RedirectUri = "https://login.live.com/oauth20_desktop.srf",
AadAuthorityAudience = AadAuthorityAudience.AzureAdAndPersonalMicrosoftAccount};
var pca = PublicClientApplicationBuilder.CreateWithApplicationOptions(pcaOptions).Build();
//var ewsScopes = new string[] { "https://outlook.office365.com/EWS.AccessAsUser.All" };
var ewsScopes = new string[] { "User.Read", "Contacts.ReadWrite.Shared" };
var authResult = await pca.AcquireTokenInteractive(ewsScopes).ExecuteAsync();
var ewsClient = new ExchangeService();
ewsClient.Url = new Uri("https://outlook.office365.com/EWS/Exchange.asmx");
//ewsClient.ImpersonatedUserId = new ImpersonatedUserId(ConnectingIdType.SmtpAddress, "araj#concord.net");
ewsClient.Credentials = new OAuthCredentials(authResult.AccessToken);
// Make an EWS call
var folders = ewsClient.FindFolders(WellKnownFolderName.MsgFolderRoot, new FolderView(10));
What am doing wrong here?
https://outlook.office365.com/EWS.AccessAsUser.All is the right scope to use. The scope is invalid for personal accounts since they're not supported by EWS.

Upload file on Google drive

I am trying to upload an image on google drive using webapi. I copied the following chunk from Google drive doc but I am getting an error.
Here is the code:
var clientSecret = ConfigurationManager.AppSettings["GoogleDriveClientSecret"];
var credential = GoogleWebAuthorizationBroker.AuthorizeAsync(new ClientSecrets { ClientId = clientId, ClientSecret = clientSecret },
scopes, Environment.UserName, CancellationToken.None).Result;
var service = new DriveService(new BaseClientService.Initializer() { HttpClientInitializer = credential });
var folderId = "0B2bBiMQICgHCMlp6OUxuSHNaZFU";
var fileMetadata = new File()
{
Name = "photo.jpg",
Parents = new List<string>
{
folderId
}
};
FilesResource.CreateMediaUpload request;
using (var stream = new System.IO.FileStream("files/photo.jpg",
System.IO.FileMode.Open))
{
request = service.Files.Create(
fileMetadata, stream, "image/jpeg");
request.Fields = "id";
request.Upload();
}
var file = request.ResponseBody;
Now I am getting 2 errors in this code. First "Cannot resolve symbol Upload" at request.Upload() and second "Cannot resolve symbol ResponseBody" at request.ResponseBody
Any help?
You may refer with this related thread. The adding the attribute Inherits="Library.Account.RootVerifyUsers". Based from this reference, Visual Studio can often get confused about things like this. It is recommended to close Visual Studio and reopen it. Also, closing all open instances of VS may be required.

Google API Calender v3 Event Insert via Service Account using Asp.Net MVC

I have been trying to insert a Google calendar event via Google service account that was created for an app in my dev console, but I am continually getting a helpless 404 response back on the Execute method. In the overview of the dev console I can see that the app is getting requests because there are instances of errors on the calendar.events.insert method. There is no information on what is failing. I need this process to use the Service account process instead of OAuth2 so as to not require authentication each time a calendar event needs to be created.
I have set up the service account, given the app a name, have the p12 file referenced in the project. I've also, gone into a personal calendar and have shared with the service account email address. Also, beyond the scope of this ticket, I have created a secondary app, through an administration account and have granted domain wide access to the service account only to receive the same helpless 404 error that this is now giving.
Error Message: Google.Apis.Requests.RequestError
Not Found [404]
Errors [Message[Not Found] Location[ - ] Reason[notFound] Domain[global]
Any help identifying a disconnect or error would be greatly appreciated.
var URL = #"https://www.googleapis.com/calendar/v3/calendars/testcalendarID.com/events";
string serviceAccountEmail = "createdserviceaccountemailaq#developer.gserviceaccount.com";
var path = Path.Combine(HttpRuntime.AppDomainAppPath, "Files/myFile.p12");
var certificate = new X509Certificate2(path, "notasecret",
X509KeyStorageFlags.Exportable);
ServiceAccountCredential credential = new ServiceAccountCredential(
new ServiceAccountCredential.Initializer(serviceAccountEmail)
{
Scopes = new[] { Google.Apis.Calendar.v3.CalendarService.Scope.Calendar },
}.FromCertificate(certificate));
BaseClientService.Initializer initializer = new
BaseClientService.Initializer()
{
HttpClientInitializer = credential,
ApplicationName = "Test App"
};
Google.Apis.Calendar.v3.CalendarService calservice = new Google.Apis.Calendar.v3.CalendarService(initializer);
string timezone = System.TimeZone.CurrentTimeZone.StandardName;
var calendarEvent = new Event()
{
Reminders = new Event.RemindersData()
{
UseDefault = true
},
Summary = title,
Description = description,
Location = location,
Start = new EventDateTime()
{
//DateTimeRaw = "2014-12-24T10:00:00.000-07:00",
DateTime = startDateTime,
TimeZone = "America/Phoenix"
},
End = new EventDateTime()
{
//DateTimeRaw = "2014-12-24T11:00:00.000-08:00",
DateTime = endDateTime,
TimeZone = "America/Phoenix"
},
Attendees = new List<EventAttendee>()
{
new EventAttendee()
{
DisplayName = "Joe Shmo",
Email = "joeshmoemail#email.com",
Organizer = false,
Resource = false
}
}
};
var insertevent = calservice.Events.Insert(calendarEvent, URL);
var requestedInsert = insertevent.Execute();
I had the same problem. The solution was to add an email client, whose calendar event you want to send.
Credential = new ServiceAccountCredential(
new ServiceAccountCredential.Initializer(serviceAccountEmail)
{
Scopes = Scopes,
User = "example_client_email#gmail.com"
}.FromCertificate(certificate));
So I found out that for this to work, You need to make sure that you access the google.Admin account for referencing the service account Client ID of the app you created.
Another thing that helps is making sure the timezone is in the following format "America/Phoenix"
I have now successfully created events through the service account WITHOUT authentication.

logging in with different user / resource owner

i am trying to write a tool that creates entries in the google calendar.
after following the google docs and creating an client-identifier/secret in the api console, i managed to put together a client that authenticates correctly and shows my registered google calendars. right now for me it looks like my google-account is somehow tied to my client-identifier/secret. what i want to know is: how can i change the auth process so that it is possible for an other user of this tool to enter his google-id and get access to his calendars?
EDIT: in other words (used in the RFC): I want make the resource owner-part editable while leaving the client-part unchanged. but my example, although working, ties together client and resource owner.
here is my app that works fine so far:
public void Connect()
{
var provider = new NativeApplicationClient(GoogleAuthenticationServer.Description);
provider.ClientIdentifier = "123456123456.apps.googleusercontent.com";
provider.ClientSecret = "nASdjKlhnaxEkasDhhdfLklr";
var auth = new OAuth2Authenticator<NativeApplicationClient>(provider, GetAuthorization);
var service = new CalendarService(auth);
//Events instances = service.Events.Instances("primary", "recurringEventId").Fetch();
var list = service.CalendarList.List().Fetch();
foreach (var itm in list.Items)
Console.WriteLine(itm.Summary);
}
private static readonly byte[] AditionalEntropy = { 1, 2, 3, 4, 5 };
private static IAuthorizationState GetAuthorization(NativeApplicationClient arg)
{
var state = new AuthorizationState(new[] { CalendarService.Scopes.Calendar.GetStringValue() });
state.Callback = new Uri(NativeApplicationClient.OutOfBandCallbackUrl);
var refreshToken = LoadRefreshToken();
if (!String.IsNullOrWhiteSpace(refreshToken))
{
state.RefreshToken = refreshToken;
if (arg.RefreshToken(state))
return state;
}
var authUri = arg.RequestUserAuthorization(state);
// Request authorization from the user (by opening a browser window):
Process.Start(authUri.ToString());
var frm = new FormAuthCodeInput();
frm.ShowDialog();
// Retrieve the access token by using the authorization code:
var auth = arg.ProcessUserAuthorization(frm.txtAuthCode.Text, state);
StoreRefreshToken(state);
return auth;
}
private static string LoadRefreshToken()
{
try
{
return Encoding.Unicode.GetString(ProtectedData.Unprotect(Convert.FromBase64String(Properties.Settings.Default.RefreshToken), AditionalEntropy, DataProtectionScope.CurrentUser));
}
catch
{
return null;
}
}
private static void StoreRefreshToken(IAuthorizationState state)
{
Properties.Settings.Default.RefreshToken = Convert.ToBase64String(ProtectedData.Protect(Encoding.Unicode.GetBytes(state.RefreshToken), AditionalEntropy, DataProtectionScope.CurrentUser));
Properties.Settings.Default.Save();
}
Prompt the user to enter their ClientIdentifier and ClientSecret, then pass these values to your Connect method.
i solved the problem myself.
the problem was, that i'm usually always connected to google and because i did't log out from google before my app redirected to google to get the access-token, google automatically generated the access-token for my account - skipping the part where an input-form appears where anyone could enter his/her user-credentials to let google generate an access-token for his/her account.

Resources