Closed grumpykiwi closed 2 years ago
Hi @grumpykiwi , since we only got JavaScript version of microsoft/teamsfx sdk, so we including webpack to wrapper it and using JSRuntime to trigger it in Blazor.
The webpack source code is in JS/src/index.js, you could add your code such as 'added Groups.Read.All to scopes inside index,.js GetToken() method'.
Then under JS folder , run 'npm install' and 'npm run build' to webpack the code and refresh the webpack file (wwwroot/teamsfx.js).
Finally you could using JSRuntime trigger the func you just updated in TeamsFx.cs.
await jsRuntime.InvokeAsync
Hi
I modified index.js as follows:
var scope = ["User.Read, Presence.Read.All, Group.Read.All, Directory.Read.All, Domain.Read.All, email, GroupMember.Read.All, Mail.Send, offline_access, openid, People.Read.All, profile, TeamMember.Read.All, User.ReadWrite.All"];
Changed in both popupLoginPage() and getToken(). Did the npm stuff, re-ran and get an error on this line of code inside GetUserProfilePhoto()
var photoStream = await graphClient.Me.Photo.Content.Request().GetAsync();
Error is:
{"Consent failed for the scope User.Read, Presence.Read.All, Group.Read.All, Directory.Read.All, Domain.Read.All, email, GroupMember.Read.All, Mail.Send, offline_access, openid, People.Read.All, profile, TeamMember.Read.All, User.ReadWrite.All with error: FailedToOpenWindow\nErrorWithCode.ConsentFailed: Consent failed for the scope User.Read, Presence.Read.All, Group.Read.All, Directory.Read.All, Domain.Read.All, email, GroupMember.Read.All, Mail.Send, offline_access, openid, People.Read.All, profile, TeamMember.Read.All, User.ReadWrite.All with error: FailedToOpenWindow\n at Object.failureCallback (webpack://TeamsFx/./node_modules/@microsoft/teamsfx/dist-esm/src/credential/teamsUserCredential.browser.js?:125:36)\n at m (webpack://TeamsFx/./node_modules/@microsoft/teams-js/dist/MicrosoftTeams.min.js?:1:16239)\n at u (webpack://TeamsFx/./node_modules/@microsoft/teams-js/dist/MicrosoftTeams.min.js?:1:15495)\n at Object.e.authenticate (webpack://TeamsFx/./node_modules/@microsoft/teams-js/dist/MicrosoftTeams.min.js?:1:17717)\n at eval (webpack://TeamsFx/./node_modules/@microsoft/teamsfx/dist-esm/src/credential/teamsUserCredential.browser.js?:102:85)\n at Object.g [as initialize] (webpack://TeamsFx/./node_modules/@microsoft/teams-js/dist/MicrosoftTeams.min.js?:1:36899)\n at eval (webpack://TeamsFx/./node_modules/@microsoft/teamsfx/dist-esm/src/credential/teamsUserCredential.browser.js?:101:66)\n at new Promise (
I tried defining the scopes differently but that didnt work either.
var scope = [ "User.Read", "Presence.Read.All", "Group.Read.All", "Directory.Read.All", "Domain.Read.All", "email", "GroupMember.Read.All", "Mail.Send", "offline_access", "openid", "People.Read.All", "profile", "TeamMember.Read.All", "User.ReadWrite.All"
I have attached a PDF that shows permissions granted to the app. I dont see anything amiss in the list.
Ideas?
Thanks for your help. Cheers
@SLdragon Could you please help to look at this error? Thanks.
@grumpykiwi , from your error message, it said "FailedToOpenWindow", did your browser block the popup window? You can take a look in the in the address bar in the browser
This is the method that is called when clicking on the Authenticate button. There are a couple of lines that I added for testing, but most of it was generated by the Teams Toolkit Visual Studio template.
` private async Task GetUserProfilePhoto() { try { IsLoading = true; IsEmployeesLoaded = false;
var graphClient = teamsfx.GetGraphServiceClient();
var photoStream = await graphClient.Me.Photo.Content.Request().GetAsync();
var presence = await graphClient.Me.Presence.Request().GetAsync();
var profile = await graphClient.Me.Request().GetAsync();
var helper = new Data.GraphHelper(graphClient);
// Employees = await helper.GetEmployeeData();
var emps = await graphClient.Groups[GroupId].Members
.Request()
.GetAsync();
if (photoStream != null)
{
// Copy the photo stream to a memory stream
// to get the bytes out of it
var memoryStream = new MemoryStream();
photoStream.CopyTo(memoryStream);
var photoBytes = memoryStream.ToArray();
// Generate a data URI for the photo
UserPhotoUri = $"data:image/png;base64,{Convert.ToBase64String(photoBytes)}";
}
Title = profile.JobTitle;
Status = string.Format("{0} - {1}", presence.Activity, presence.Availability);
Email = profile.Mail;
}
catch (Exception ex)
{
e = ex;
Console.WriteLine(ex.ToString());
}
finally
{
IsLoading = false;
// Uncomment this when get group permission issue sorted
// IsEmployeesLoaded = true;
}
}
`
The line that fails is var photoStream = await graphClient.Me.Photo.Content.Request().GetAsync(); which was generated from the toolkit. Error was captured by inserting the catch
This happens inside Team desktop client. I hit F5 from VS to start and it automatically runs in Teams. I dont see any attempts from Teams to open a window and no messages about a blocked popup.
Sorry about the code formatting. Thing has a mind of its own
Hi, @grumpykiwi , could you share a minimal sample of this issue, so we can take a look and investigate the root cause, thanks!
Sample attached. I have removed App Id, Tenant ID and Client Id for security purposes.
Line 140 of tab.razor is where the exception happens. Code execution goes straight to the catch at line 167 where you can see the failed to open window, which is being generated by the toolkit code as far as I can tell.
The customized scopes are in index.js. As you can see I tried 2 different ways to define them. Maybe it is just looking for a different format? I have not found any documentation or hints on a Google search about it, so am guessing.
I had to remove all of the node modules folders in order to make the zip file small enough to attach.
Let me know what else you need,
Thanks
Thanks, we will have a try
Hi, @grumpykiwi , I have one quick question:
When you click the Auth button, did you see the login page in the browser like this?
If you do not see this login window, and did you see this block icon in your browser?
I went into the site settings and allowed popups and notifications for teams.microsoft.com.
The popup appears very briefly but then disappears and I end up with a bunch of 400 errors in the console like this:
Microsoft.TeamsFx.SimpleAuth.Components.Auth.Exceptions.AadUiRequiredException: AADSTS65001: The user or administrator has not consented to use the application with ID '4d902334-ba4f-4830-8525-c884b050ccf2' named ' PC Teams Status.Core'. Send an interactive authorization request for this user and resource. Trace ID: 4e46b3c1-dcc5-47bf-a819-ad32de230a01 Correlation ID: d0f7d60e-bb59-46d9-98bf-94ad82e11c78 Timestamp: 2021-06-23 13:03:28Z ---> MSAL.NetCore.4.30.0.0.MsalUiRequiredException: ErrorCode: invalid_grant Microsoft.Identity.Client.MsalUiRequiredException: AADSTS65001: The user or administrator has not consented to use the application with ID '4d902334-ba4f-4830-8525-c884b050ccf2' named ' PC Teams Status.Core'. Send an interactive authorization request for this user and resource. Trace ID: 4e46b3c1-dcc5-47bf-a819-ad32de230a01 Correlation ID: d0f7d60e-bb59-46d9-98bf-94ad82e11c78 Timestamp: 2021-06-23 13:03:28Z at Microsoft.Identity.Client.Internal.Requests.RequestBase.HandleTokenRefreshError(MsalServiceException e, MsalAccessTokenCacheItem cachedAccessTokenItem) at Microsoft.Identity.Client.Internal.Requests.OnBehalfOfRequest.ExecuteAsync(CancellationToken cancellationToken) at Microsoft.Identity.Client.Internal.Requests.RequestBase.RunAsync(CancellationToken cancellationToken) at Microsoft.Identity.Client.ApiConfig.Executors.ConfidentialClientExecutor.ExecuteAsync(AcquireTokenCommonParameters commonParameters, AcquireTokenOnBehalfOfParameters onBehalfOfParameters, CancellationToken cancellationToken) at Microsoft.TeamsFx.SimpleAuth.Components.Auth.AuthHandler.AcquireTokenBySsoTokenOnBehalfOf(String ssoToken, String[] scopes) StatusCode: 400 ResponseBody: {"error":"invalid_grant","error_description":"AADSTS65001: The user or administrator has not consented to use the application with ID '4d902334-ba4f-4830-8525-c884b050ccf2' named ' PC Teams Status.Core'. Send an interactive authorization request for this user and resource.\r\nTrace ID: 4e46b3c1-dcc5-47bf-a819-ad32de230a01\r\nCorrelation ID: d0f7d60e-bb59-46d9-98bf-94ad82e11c78\r\nTimestamp: 2021-06-23 13:03:28Z","error_codes":[65001],"timestamp":"2021-06-23 13:03:28Z","trace_id":"4e46b3c1-dcc5-47bf-a819-ad32de230a01","correlation_id":"d0f7d60e-bb59-46d9-98bf-94ad82e11c78","suberror":"consent_required"} Headers: Cache-Control: no-store, no-cache Pragma: no-cache Strict-Transport-Security: max-age=31536000; includeSubDomains X-Content-Type-Options: nosniff P3P: CP="DSP CUR OTPi IND OTRi ONL FIN" client-request-id: d0f7d60e-bb59-46d9-98bf-94ad82e11c78 x-ms-request-id: 4e46b3c1-dcc5-47bf-a819-ad32de230a01 x-ms-ests-server: 2.1.11829.4 - WUS2 ProdSlices x-ms-clitelem: 1,65001,0,, Set-Cookie: fpc=Al1H_D3TVA5JlKKm0o8rjXyL3WreAgAAAPonZdgOAAAAb3TSjhMAAAD7J2XYDgAAAA; expires=Fri, 23-Jul-2021 13:03:28 GMT; path=/; secure; HttpOnly; SameSite=None, x-ms-gateway-slice=estsfd; path=/; secure; httponly, stsservicecookie=estsfd; path=/; secure; samesite=none; httponly Date: Wed, 23 Jun 2021 13:03:28 GMT
--- End of inner exception stack trace ---
at Microsoft.TeamsFx.SimpleAuth.Components.Auth.AuthHandler.AcquireTokenBySsoTokenOnBehalfOf(String ssoToken, String[] scopes)
at Microsoft.TeamsFx.SimpleAuth.Controllers.AuthController.AcquireAccessTokenBySsoToken(PostTokenRequestBody body)
at Microsoft.TeamsFx.SimpleAuth.Controllers.AuthController.PostToken(PostTokenRequestBody body)
at Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor.TaskOfIActionResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.
The capture from AD App Registration clearly shows (to me) that the app has all the permissions it needs.
Am I missing something here ? Since the popup appears so briefly, I never get the chance to approve additional permissions.
Also, is there a trick to get this app to run in the desktop client instead of the browser?
Thanks
I captured what happens. Hope it helps
Update. I created 2 brand new Visual Studio solutions from the Teams FX templates.
@microsoft/teamsfx@0.1.2 : Error - Failed to get access token from authentication server: The AAD configuration in server is invalid.
This leads me to speculate there is something awry with the app registration for 4d902334-ba4f-4830-8525-c884b050ccf2.
In the meantime I will keep plugging away with template 1, adding 1 UI piece at a time, test and repeat. That way if and when it breaks I will know what broke it.. Not necessarily why of course. I shall report back my findings.
Thanks for all your help
Maybe there is a cache issue when you try to consent the permission,
You can follow the steps to see whether it can solve your problem:
Login to this website: https://myapplications.microsoft.com/
Find your AAD application, click manage your application:
The operation may take some time to take effect. You can restart your application after 1~2 hours, if the login page show the button which you can approve the permission you've requested, then it works.
Thanks. Did that. Will check in the morning. Almost midnight here. Cheers
Mark
Ran the app this AM. Prompted me 2x for the additional permissions then failed. Log from dev tools is attached.
Beginning to wonder if there is a configuration problem in Azure with that app registration. Probably something quite dumb on my part teams.microsoft.com-1624543244493.log
@grumpykiwi , from your error message "The AAD configuration in server is invalid" means that the client id or client secret is not valid.
If you're copy configuration from other project, this may introduce problem. AFIK client secret is stored in other place, maybe your client secret is not valid
You can refer this for more information about where is the secret: https://docs.microsoft.com/en-us/aspnet/core/security/app-secrets?view=aspnetcore-5.0&tabs=windows#secret-manager
I deleted all previous secrets from the app registration in Azure and created a new one. Copied the value using the button provided into the appsettings.json file and re-ran it. Same error.
I then commented out the client secret line from the JSON file. No change
I just created a brand new Teams Project in VS2019. Did the SSO option under project and ran it. No issue.
I think there is something wrong in the app config somewhere. A difference between the project and Azure App registration. I will try and figure it out over the weekend. I have a working solution I can work with, but would like to sort this out so I can document and hopefully help someone else out that faces the same error.
I cloned from github a version of a teams app I had created. At the time of commit, I had added some custom scopes:
User.Read Presence.Read.All Group.Read.All GroupMember.Read.All
The app ran fine on 6/23 when committing. Now, it fails with:
Failed to get access token from authentication server: The AAD configuration in server is invalid.
This is from dev tools
I have not knowingly changed anything in the app config in any portal, yet it has stopped working. Is there some kind of behind the scenes daemon working on the app registrations in Azure that is corrupting the app entry?
I am baffled.
You can check whether your app secret is correct.
From your .csproj file, find the secret id:
Then open the settings file in your system: %APPDATA%\Microsoft\UserSecrets\
Make sure that the "CLIENT_SECRET" in secret json file is align with your current AAD settings
I think I figured it out. I have 2 apps created with the toolkit. MyTeamsApp3 and MyTeamsApp5.
Both have this entry in the csproj file:
`
<UserSecretsId>ac2ac231-0188-4f79-bd70-ebcc17700631</UserSecretsId>
`
I opened the secrets.json file in VS Code and see this:
{ "CLIENT_SECRET": "4f1~93u6-XXXXXXXXXXXX" }
I poked around the Azure App registration portal and found this:
What this shows explains what I am seeing.
When I create a 2nd project, the
This to me is a bug. The toolkit should generate a random GUID for the folder name on project creation, and place the secrets.json file in there. This would avoid the previous project being over-written.
In summary: The latest toolkit generated project is the only one that is going to work. All previous projects will break with an invalid client secret due to the over-writing.
I was able to work around the issue by doing the following:
Hope this helps someone else. This was quite a rabbit hole of a problem. Lots of time spent in Dev Tools and Fiddler to capture what was being sent back and forth so I could nail down the source of the issue.
@grumpykiwi , thank you very much, seems this is a bug for our VS extension, I will inform our team members who working on the extension of this issue.
@grumpykiwi Thanks a lot about report this bug, We have fixed it and it will take affect in next release.
Glad to contribute. You might want to document the work around in the release for others that may have experienced the same problem but didn’t see this bug report.
Thanks
Mark
The new version of VS Teams Toolkit is availbale now in marketplace, we have fixed the bug in this release, please upgrade and try it.
Thanks Jerry. Will download in the morning
Mark
Close this bug since it has been fixed in the latest version. Feel free to reopen the issue if you find the issue again.
Describe the bug Added code to return a list of users in a specific AD group. Added Groups.Read.All to scopes inside index,.js GetToken() method. On execute receive Insufficient privileges to complete the operation.
To Reproduce Steps to reproduce the behavior:
Set a breakpoint on this line
`blazor.server.js:21 [2021-06-19T01:16:06.352Z] Error: Status Code: Forbidden Microsoft.Graph.ServiceException: Code: Authorization_RequestDenied Message: Insufficient privileges to complete the operation. Inner error: AdditionalData: date: 2021-06-19T01:16:06 request-id: 6fbf179b-be6c-4523-830d-a6629a7ee248 client-request-id: 6fbf179b-be6c-4523-830d-a6629a7ee248 ClientRequestId: 6fbf179b-be6c-4523-830d-a6629a7ee248
at Microsoft.Graph.HttpProvider.SendAsync(HttpRequestMessage request, HttpCompletionOption completionOption, CancellationToken cancellationToken) at Microsoft.Graph.BaseRequest.SendRequestAsync(Object serializableObject, CancellationToken cancellationToken, HttpCompletionOption completionOption) at Microsoft.Graph.BaseRequest.SendAsync[T](Object serializableObject, CancellationToken cancellationToken, HttpCompletionOption completionOption) at Microsoft.Graph.GroupMembersCollectionWithReferencesRequest.GetAsync(CancellationToken cancellationToken) at TeamsStatus.Core.Pages.Tab.GetUserProfilePhoto() in D:\projects\TeamsStatus.Core\TeamsStatus.Core\Pages\Tab.razor:line 142 at Microsoft.AspNetCore.Components.ComponentBase.CallStateHasChangedOnAsyncCompletion(Task task) at Microsoft.AspNetCore.Components.RenderTree.Renderer.GetErrorHandledTask(Task taskToHandle)`
Expected behavior The emps var to be populated with a list of users in the specified AD group
VS Code Extension Information (please complete the following information):
CLI Information (please complete the following information):
Additional context Add any other context about the problem here.