Webview2, SharePoint Online, and Azure AD Authetication - wpf

I have a WPF desktop using the WebView2 control, and it works quite nicely. The problem I am trying to solve is handling the authentication for users who find the repeated prompts when accessing our SharePoint Online (SPO) site within the WebView2 control annoying. I am not looking to access Graph API or the SPO API, just allow the user to navigate to our SPO site without login prompts. Our on-prem AD synchronizes with Azure AD.
A couple of applications I've developed:
An Office add-in using SSO with delegated permission and signed off by our admin so that users do not log in
A console app that has application permission to update all calendars in our organization via the EWS API, protected with Azure AD certificate authorization, although it initially used a secret
That said, how can I set up the app authorization so that my desktop WPF app can allow the users to access SPO without prompts?

According to your scenario, you can try the following things in your web view control such that you will no longer receive authentication prompts for Sharepoint online login.
• You trying to access SPO site within web view control, so you need to allow authentication for both the http clients, i.e., Windows store clients(classic)[System.Net.Http.HttpClient] and HTTP clients[Windows.Web.Http.HttpClient] connected to web view controls. You can do so by adding the new one in your code as below: -
var filter = new HttpBaseProtocolFilter();
filter.ServerCredential = new Windows.Security.Credentials.PasswordCredential("http://website","login","password");
Windows.Web.Http.HttpClient client2 = new
Windows.Web.Http.HttpClient(filter);
var response = await client2.GetAsync(new Uri("http://website"));
WebView.Source = new Uri("http://website");
• In this code, change the “login” and “password” to the credentials you want to use to login in the SPO site. Also, change the “http://website” to the SPO website and set the ‘enterpriseAuthentication’ parameter to off.
• Also, you can use the ‘’TodoListService” Service app for maintaining an in-memory collection of to-do-items for each authenticated user for login purposes.
Please refer the below links for more reference: -
providing domain/user credentials to webview control
https://learn.microsoft.com/en-us/previous-versions/windows/hh465283(v=win.10)?redirectedfrom=MSDN
https://learn.microsoft.com/en-us/samples/azure-samples/active-directory-dotnet-native-aspnetcore-v2/1-desktop-app-calls-web-api/
This way, hopefully the SPO site can be accessed through desktop WPF app without authentication prompts.
Thanking you,

Related

Office-Addin Single Sign On and API Scopes

The Office Addin for Excel provides the method:
OfficeRuntime.auth.getAccessToken(OfficeRuneTime.authOptions)
to call the Azure Active Directory, log in the user and gain access to the users profile. The method brings up a dialog box asking the users consent for the Office App to access their profile. The consent box also includes the grants to my Web App (Angular web site that runs in the Excel Taskpane) and includes the words "If you accept, will also have access to your user profile information"
All good. But my Web App communicates with my API, which requires an additional granting of consent for my API to access the users profile.
Is there any way to cause the dialog box invoked by 'getAcccessToken' to also grant permission to my API?
When I login using MSAL as a fallback method (not getAccessToken(), but using an excel dialog box with MSAL configured as per the various Microsoft Walkthoughts), the consent box DOES include both my WebApp and my WebAPI. And authentication works correctly.
I note that the Manifest file has a tag. I had hoped that adding the Scope to my API in here would cause the Office-Addin to request consent to it, but no banana, it does nothing.
Any Ideas?
I do note that getAccessToken() deliberately does not return an access token to MS Graph, with the Microsoft Documentation citing 'security concerns', and such access to Graph must be via Server Side Code using the On-Behalf-Of flow, perhaps similar reasoning does not permit me to gain consent to any API using getAccessToken(), but what then are these section in the manifest file for? I have really struggled to get SSO working with Office Addins, there are so many nuances and unexpected behaviours.
The getAccessToken method calls the Azure Active Directory V 2.0 endpoint to get an access token to your add-in's web application. That enables add-ins to identify users. Server-side code can use this token to access Microsoft Graph for the add-in's web application by using the "on behalf of" OAuth flow. This API requires a single sign-on configuration that bridges the add-in to an Azure application. Office users sign-in with Organizational Accounts and Microsoft Accounts. Microsoft Azure returns tokens intended for both user account types to access resources in the Microsoft Graph. Read more about that in the Microsoft identity platform and OAuth 2.0 On-Behalf-Of flow article.
In answer to my own question,
It is NOT possible to cause the dialog box invoked by 'getAcccessToken' to also grant permission to my API
I have written a lengthy response to this in my answer to this question
Office-Addin MSAL Single Sign In SSO: How to Refresh the Access Token?

App Registration not showing as Cloud App on AAD Conditional Access

I'm creating an app registration for Azure AD using my admin account (specifically for Mobile and desktop applications authentication). I intend to create an AAD Conditional Access that will be applied to the created app registration. For some reason the App Registration is not visible on the cloud app selection when I am trying to select it.
Screenshot - Conditional Access > Policy > Cloud apps or actions > Select apps
P.S. It showed on the cloud apps when I tried adding a "Web" platform on the app registration, but still CA is not applied when trying to login using the App Registration. Am I missing anything? Thanks in advance.
Screenshot - AAD - Sign-Ins
Please note that the CA policy is applied when a client calls a service. It's not applied directly to a client (public/native) application.
See the Note tip here.
Since Conditional Access policy sets the requirements for accessing a
service you are not able to apply it to a client (public/native)
application. Other words the policy is not set directly on a client
(public/native) application, but is applied when a client calls a
service. For example, a policy set on SharePoint service applies to
the clients calling SharePoint. A policy set on Exchange applies to
the attempt to access the email using Outlook client. That is why
client (public/native) applications are not available for selection in
the Cloud Apps picker and Conditional Access option is not available
in the application settings for the client (public/native) application
registered in your tenant.
It also explains why CA is not applied when you tried to login using the App Registration -- you didn't call a service.

Authentication flow Service to Service Microsoft Graph and Bookings API

I am building a custom mobile application that has a client, custom backend server (I'm building) and interacts with numerous other api's. One of these api's is Microsoft bookings.
The problem I'm facing is I need to be authenticated via server to server, with a shared client secret. I'm aware of the numerous docs from MS but have yet to find a solution. I'm wondering if Server to server is even possible with Bookings.
I am able to get an access_token server to server with these permissions. (I have granted 'all permissions' to this app in Azure AD already).
"roles": [
"Calls.JoinGroupCall.All",
"OnlineMeetings.Read.All",
"OnlineMeetings.ReadWrite.All",
"Application.ReadWrite.OwnedBy",
"Calendars.Read",
"People.Read.All",
"Application.ReadWrite.All",
"Calls.InitiateGroupCall.All",
"Directory.ReadWrite.All",
"Calls.JoinGroupCallAsGuest.All",
"Sites.Read.All",
"Sites.ReadWrite.All",
"Sites.Manage.All",
"Files.ReadWrite.All",
"Directory.Read.All",
"User.Read.All",
"Calendars.ReadWrite",
"Mail.Send",
"ProgramControl.Read.All",
"ProgramControl.ReadWrite.All",
"Calls.Initiate.All"
],
Those are the permissions from the decoded token. When I go to make calls to the Bookings api I receive 401.
I can however use this token to access different graph endpoints no problem.
I will note, that I am able to make successful calls to the bookings api through Graph Explorer with my account, not related to this 'Application in Azure AD'.
Does this resource in Azure AD need a bookings License?
Is this even possible S2S?
Are there any other ways to bypass this without user credentials?
Thanks.
So I spent over a week trying to solve this problem due to the MS doc nightmare. I'm only posting to help others!
Bookings doesn't support service to service yet. So if you wan't to implement this without a user physically signing in, IE. If you have a dedicated booking admin account credentials you have to hard code the clients credentials.
I found my answer here https://stackoverflow.com/a/49814924/9105626
Microsoft Bookings API doesn't seem to support "Application Permissions" so far.
Only permissions available are "Delegated Permissions", which means your token has to be acquired with the context of a signed-in user.
Here are two Microsoft documentation sources that I came across:
Microsoft Graph Permissions Reference - Please look at the "Bookings Permissions" section.
Microsoft Bookings Samples
I know you mention Server to Server authentication using a client secret. AFAIK, that case will NOT work directly, because clientId and clientSecret only provide an application's identity (which can't be assigned any permissions because there are no relevant application permissions available for this API).
Just in case you can have some User context involved, here is code from bookings samples link above, to acquire the token in a Native application using ADAL
var authenticationContext = new AuthenticationContext("https://login.microsoftonline.com/common/");
var authenticationResult = await authenticationContext.AcquireTokenAsync(
"https://graph.microsoft.com/",
clientApplication_ClientId,
clientApplication_RedirectUri,
new PlatformParameters(PromptBehavior.RefreshSession));
// The results of this call are sent as the Authorization header of each HTTPS request to Graph.
var authorizationHeader = authenticationResult.CreateAuthorizationHeader();
Suggestions on ways to make this scenario work
On Behalf Of Flow
Your mobile application client could prompt a user for credentials to act on Behalf of the user and call your backend web API, which in turn calls the downstream API like Bookings API. This is called Service to Service Calls on behalf of the User
Here is a code sample which shows exactly this with a native application (WPF) and an SPA. In your case, just replace the WPF application with your mobile client application for understanding purposes and rest of the scenario becomes very similar.
Calling a downstream web API from a web API using Azure AD
ROPC Grant (Not Recommended)
Resource Owner Password Credentials grant can help as your application will have end user password available to it, but it has multiple issues and any security guidance will discourage you from using it.
ROPC opens up security risks, doesn't follow best practices and has functionality issues as well. ROPC doesn't work with MFA enabled users as well as federated authentication users.
For all practical purposes, you should avoid ROPC as long as possible. You can find the same recommendation in ADAL documentation itself and multiple other documentations from Microsoft or even generally about OAuth 2.0.

Accessing Office Graph apis with Sharepoint Online login?

We've been running an Angular app in a custom masterpage during the last year, using the Sharepoint REST api to retrieve user properties, data from lists etc., which has been working fine. As the application is hosted on Sharepoint Online, accessing the page requires a login thus making the request digest available so further authentication is not necessary.
Now however, we want to start using some of the functionality in the Microsoft Graph API. From what I can gather this requires OAuth2 authentication against the Azure Active Directory, involving among other things a redirect to the AAD login page.
Does this mean I have to:
1) Login via the organizations (standard Microsoft) login page to access the Sharepoint Online site.
2) Redirect to the Azure AD login page and back again?
Or can I leverage the login that the user already did when logging into Sharepoint Online?
Sorry if the question is a bit vague, we are all still very new to this.
When registering your application on Azure AD you will give the app access to Files/Sharepoint REST api and Microsoft Graph API. See this picture the app has access to several apis (Exchange, Graph and AD) you must add sharepoint APIs in your case.
Regarding the authentication, I am afraid that the Sharepoint model does not provide a token that will enable you to request the Graph API see this. You will have two authentications, one to access the Sharepoint site, as you said, and the other "within" the sharepoint iframed add-in to log into your AAD's registered app. This will be an OAUTH process through login.microsoft.com. Have a look at my Outlook add-in Keluro Mail Team on the Office store, I think it is similar to what you want to achieve.
You can use the same token from graph.microsoft.com. I have a sample using Asp.Net Core 1.0 and the.Net ADAL but the same authentication flow is used when using ASP.NET 4.6. Just make your auth request against ms graph on startup then acquire access token to auth against SharePoint.
https://github.com/edrohler/com.ericrohler
Hope this helps.

Security model - SharePoint 2010 Silverlight web part calling WCF service

I have an interesting situation that I haven't been able to crack. Here is the environment that my Silverlight application runs in.
We have a SharePoint 2010 intranet that is the main host for the application. On a web part page, we have a Silverlight web part that contains the application. We use the Client Object Model to deduce who the logged in SharePoint user is. The users of this application access the SharePoint site OUTSIDE of the AD domain that they use to login; meaning they have an AD account, but their computers are part of various domains. The Silverlight application makes calls to a WCF service over https via SOAP protocol.
The question is, how do I secure the services so that the only valid requestor is the Silverlight application when being called from inside the context of a logged in SharePoint user?
Each end-user has an AD account that is created for them. The SharePoint site is an extranet that requires each user to login using their AD credentials. However, no end-user is accessing a site from a computer that is part of the domain.
I've attempted using Windows Authentication, but we have a requirement that the user must not be prompted to login (to the web services) after they have already logged into SharePoint. I've attempted using the Client Object Model to "pass" authentication/credentials to the service, but no luck there.
We have to disable Anonymous Authentication before we go to live, so I've got to figure out a way to secure the services but not make the users login a 2nd time inside the application.
out of the box you cant, silverlight cant delegate to any external service for security reasons. What you can do is to secure your WCF channel via some other method (certificate based for example) and send through the current username manually. On the SharePoint end you can then impersonate the user.
It will be quite a fiddly thing to get going though :)

Resources