Azure Ad B2B authentication retrieve data from external user CRM - azure

We want to build a web app through which Dynamics crm customer's can login. Once they login we would like to show them their CRM's instance contact list. We have implemented Azure B2B Authentication and hosted app but I don't know how to retrieve data from logged in customer's crm .
https://github.com/Azure-Samples/active-directory-aspnetcore-webapp-openidconnect-v2/blob/master/2-WebApp-graph-user/2-3-Multi-Tenant/README.md#about-this-sample
Any help appreciated.

Take a look at CRM connection string examples. You can prompt logged in user for authentication. It creates a new connection to Common Data Service using the current logged in user via OAuth.
I wanted to connect to CRM to work with solutions for a project, so I used to CRM SDK for that by referring to PowerApps samples repo. And my project authenticates user using Azure B2B, and I wanted the same user to connect to CRM. So I used On-Behalf-Of flow.
I first got access token after authenticating user for the AD app. Then I used this token to get another token using UserAssertion for the target org (Ex: https://org12345.crm.dynamics.com/). You'll need to add Dynamics CRM permission like this Registering AD App. Now once I have the token for my target org, I use it like this to connect to CRM:
Uri serviceUrlDestination = new Uri(orgUrl + #"/xrmservices/2011/organization.svc/web?SdkClientVersion=8.2");
OrganizationWebProxyClient sdkServiceDestination = new OrganizationWebProxyClient(serviceUrlDestination, false);
sdkServiceDestination.HeaderToken = AccessToken;
CrmServiceClient serviceClient = new CrmServiceClient(sdkServiceDestination);
I don't know how to retrieve contact list of the logged in user as I used this for mainly for solutions, but once you are connected to CRM from the logged in user's context, I think you should be able to do other operations as well.

Related

How to get the Teams User Id for Teams Interop Using Azure Communication Services

I have created a Microsoft Teams Meeting from the Microsoft Teams Client
e.g of meeting link: https://teams.microsoft.com/l/meetup-join/....
Note: I am already able to join a call using the external users taking reference from this
Create and manage access tokens for Teams external users
use the tokens in CallComposite Component
Now,
I am trying to start a Teams Call from/within our website for the link mentioned above. I already have an authorized Microsoft OAuth User and got the accessToken and refresh token.
I've retrieved the Azure Communication Services access token following this post. However, I cannot retrieve an Azure Communication Services User Id.
Just for quick testing, I am testing the credentials on the following page.
I've also raised a Microsoft support ticket here
The answer really depends on your scenario.
Create and manage access tokens for Teams external users
This article describes how you can create and manage identities that can connect a Teams call and when they do, they appear as "external users"
Quickstart: Set up and manage access tokens for Teams users
This article describes how a Teams user can use their AAD identity to get an ACS token (and therefore can use ACS to join calls)
In this case, there is no ACS identity associated with the Teams user and the ID is the oid (Object ID) claim of the AAD identity. (so there is no Azure Communication Services User Id)
You say you've retrieved the ACS access token already so you must have the oid at your disposal.
If you're looking for a way to convert the oid claim to MicrosoftTeamsUserIdentifier and back, check out this article.

MSAL PublicClientApplicationBuilder with AzureAD external user cannot access SharePoint

We have a Windows Application using MSAL with PublicClientApplicationBuilder to access SharePoint with the delegated permissions of the logged on user.
When our code is used with a login of a user who was invited as an external user in another AzureAD and his user is added to the members of a SharePoint site collection, we get an access token which results in HTTP 401. Using a user from the other AzureAD directly to log in does work. It is just with external user, we fail to get access.
When the user logs into SharePoint in the browser, using his external user login, he can access the other tenants SharePoint. So his external user account has permissions on that site collection, but it works only in the browser, not from our MSAL client.
Some details:
We created the app registration as multi tenant app in our AzureAD with the needed read and write permissions from the SharePoint delegated permission list.
An admin of the other AzureAD consented the delegated permissions for all users and we did the same in our AzureAD. So no matter which user tries to login and use the app will find consented permissions.
We use this code to get a public client app:
var clientAppId = "our-app-clientID";
var redirectUri = "https://login.microsoftonline.com/common/oauth2/nativeclient";
_clientApp = PublicClientApplicationBuilder.Create(clientAppId)
.WithRedirectUri(redirectUri)
.WithLogging(Log, LogLevel.Verbose, false)
// .WithTenantId("we tried our and the other tenants ID")
.Build();
The commented line .WithTenantId was just added while we tried to find a solution.
We can see that it makes a difference for the token content. Without that line or with our tenantId we see the users "oid" is the objectId from the user in our AzureAD.
When we use the tenantId of the other AzureAD, we get the oid of the external user object in that other AzureAD.
So we had hopes that the latter call would succeed, but it fails as well, this time with HTTP 403. So the user token seems to get a bit further, but still not to the SharePoint site collection.
Any idea if this scenario is possible?
Would be nice, if possible and best if we would not have to call WithTenantId because otherwise we would some need to lookup the correct tenantId on the client machine - not sure where to get it from, except asking an admin from the other tenant and putting the value in some app config file or the Windows registry.
• The issue most probably according to your description suggests that the scopes might not be added correctly to the ‘Sharepoint API’ because since you are accessing the sharepoint site from a public client using MSAL authentication, the scopes/permissions to access the sharepoint site from a public client in Azure AD needs to be added and extended to service the requests from external user accounts also.
To do so, you need to add scopes/permissions to Sharepoint API through the Azure portal as when you are calling SharePoint APIs outside of the Microsoft Graph, you call ‘/_api/web/lists’ and it will retrieve all the lists. Thus, if your public client app performs this action using the Microsoft Graph API permissions then you will get an access denied error message as you are encountering HTTP 403 error.
• Thus, in your case, to access the sharepoint sites, you will need to add the scopes ‘AllSites.Read’ and ‘Sites.ReadWrite.All’ to the Sharepoint API for your public client app as the scope for ‘Sites.Read’ in the Microsoft Graph API isn’t enough for it. Also, ensure to add the ‘https://<domain>.sharepoint.com/AllSites.Write’ and ‘https://<yoursite>.sharepoint.com/Sites.ReadWrite.All’ scopes also to the Sharepoint API for that public client app.
To access the Sharepoint API through public client, you use AAD auth for which Microsoft recommends using a certificate rather than a secret. For more information regarding this, kindly use the below documentation link: -
https://learn.microsoft.com/en-us/azure/active-directory/develop/msal-authentication-flows#client-credentials
• Also, ensure that ‘https://microsoft.sharepoint-df.com/Sites.Search.All’ and ‘https://yourtenant.sharepoint.com/Sites.Search.All’ are also added as scope in your application as Sharepoint online site might reject the token because of invalid audience.
For more information regarding the scope modification, kindly refer the below link for more details: -
https://github.com/AzureAD/microsoft-authentication-library-for-js/issues/400

Create a custom API to use Microsoft Graph to send emails

I want to develop a custom ASP.NET Web API which can be used to send out emails as a user using the Microsoft Graph API. I think this will be a Multi-tenant application. Below are few ideas I have and some questions:
I have a working ASP.NET MVC web application where different users can login using their unique credentials provided by us.
I have an "Email Setup" section in my web app. Every user will navigate to this section one-time and be redirected to the "https://login.microsoftonline.com/common/oauth2/v2.0/authorize?client_id={{client_id}}&response_type=code&redirect_uri={{redirect_uri}}&response_mode=query&scope=offline_access%20user.read%20mail.read&state=12345"
On the consent screen user will sign in using their Microsoft Office 365 credentials and provide consent to my app.
On providing consent, user will be redirected back to my web app and I will get Access token for the code returned and store the access token in a SQL database.
User navigates to a page to send email, fills in the To, Subject, Body, Attachments etc. and clicks on the "Send" button.
On send button, my ASP.NET web app will call our custom Web API to send the email. The API will have an endpoint that knows the user and will get appropriate access token from the SQL database to send email on that user's behalf.
Questions:
Do I need to register an Azure App with type "Multi-tenant" since I want to support users from different tenants?
What kind of scopes/permissions will be required in order to "Send Email" as the user?
Do I need Delegated/Application permissions on the Azure side?
How can I ensure that the email that is sent, also gets saved to that user's "Sent Items" folder on Outlook?
According to the sending email graph api, we can see it provides the Application api permission, that means you can create an azure ad application and assign the Mail.Send permission to this api and using client credential flow to generate access token to call this api, so it's not necessary to creating a multi-tenant azure ad application via this way.
And certainly, if you insist on auth code flow to generate access token to using delegate permission to call the api, you should creating a multi-tenant application so that users from different tenant can generate access token through this azure ad application.

Dynamics crm 365 get azure adal authorization code

I have a scenario is one where the user has signed into CRM and triggers some functionality that calls a third party API to retrieve data that is not in CRM.
This API is a registered application in the Same Azure Active Directory as where the CRM resides. CRM single sign on is enabled.
I am trying to find an example of C# code which retrieves the authorization code via a CRM plugin. So far, I have managed to retrieve the token using a client secret as described in this article:
Retrieving token without the ADAL client library
I have implemented a basic call with the parameters defined in this article:
Requesting an Authorization code
But I need to pass the user session to make it work. It currently throws an error
A silent sign-in request was sent but no user is signed in. The cookies used to represent the user's session were not sent in the request to Azure AD. This can happen if the user is using Internet Explorer or Edge, and the web app sending the silent sign-in request is in different IE security zone than the Azure AD endpoint (login.microsoftonline.com).
Any help appreciated.
AFAIK, it is not suitable to interact with Azure AD using the Oauth code grant flow in the Microsoft Dynamics 365 plug-in since it required users interaction. And it is not able to send the session in the Microsoft Dynamics 365 plug-in to authenticate using ADAL library.
If you only want to access the Microsoft Dynamics 365 organization service in the CRM plug-in, there is no need to use the ADAL library to authenticate again.
It is only required that plug-in code create an instance of the service through the ServiceProvider.GetService method.
// Obtain the organization service reference.
IOrganizationServiceFactory serviceFactory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
IOrganizationService service = serviceFactory.CreateOrganizationService(context.UserId);
More detail about context of Microsoft Dynamics 365 Plug-in development, please refer the link below:
Understand the data context passed to a plug-in

Microsoft Dynamics CRM OAuth Integration

I need to integrate my web application (multi-tenant SaaS product) into my users' Dynamics CRM so it can pull their data.
I have learnt that Azure Active Directory apps can take care of such integrations (OAuth) but I cannot figure out how my users can grant my app access to their Dynamics CRM data.
Apparently, every user of mine should create an Azure AD app (with access to their Dynamics CRM account) and then my Azure AD app should be authorised to make requests on behalf of their AD app.
I have no idea how I can make this process work.
Any advice would be much appreciated.
For Dynamics CRM versions 2016 and 365, data can be accessed via the Web API.
When using the Web API by sending, for example, an HTTP GET request, a request header must be present in the format: { 'Authorization': 'Bearer' + token } where token is an OAuth 2 Bearer Token.
To obtain a token, I'd suggest using the Azure AD authentication Library (ADAL).
To authenticate with Dynamics CRM via ADAL, you'll have to register your web application under Azure Active Directory along with Dynamics CRM. Registering your app will give you a client ID which is required by the OAuth 2.0 authorisation flow. This post is very useful.
If your app will have administrative privilege, then it will have access to other user's data. There are several things you should make sure of when configuring OAuth, check this:
http://phuocle.net/crm/dynamics-365-online-s2s-authentication-full-explain.aspx
so to highlight the most important things from my perspective:
you should have a special user for handling that
this user should not have any license assigned - so you have to sign a license for him, a take it back after done configuring him
user should have a custom role (can be role copied from System Administrator)

Resources