The Graph Client Authentication Providers allows for each authentication to the graph endpoint implementing a variety of OAUTH2 flows. I will demonstrate the use of this library in c# code based on this GitHub. Previously, you had to build your own Authentication Provider ( see my creation of the client credentials provider in a vb.net application here ) . This library will allow you to use the following flows:
- Confidential Client Providers
- Authorization code
- Client Credentials
- On behalf of
- Public Client Providers
- Device Code
- Integrated windows authentication
- Interactive Authentication ( This blog demonstrates this flow )
The GitHub readme does show all those basic flow implementations.
Note: The library is in preview release only and is subject to change without notice.
I used the same app registration I created demonstrating how to use MSAL here.
Start a new c# console application and install the following Nuget Packages.
Nuget Packages
- Microsoft.Graph – Also installs:
- Microsoft.Graph.Core
- Newtonsoft.Json
- System.Buffers
- System.Diagnostics.DiagnosticSource
- System.Memory
- System.Numerics.Vectors
- System.Runtime.CompilerServices.Unsafe
- System.ValueTuple
- Microsoft.Graph.Auth ( Preview Version – you
must check the “Include Prerelease” box to find ) – Also installs:
- System.Security.Principal
- Microsoft.identity.Client
I only have one code file – Program.cs ( the default code file for a console app ). Here is the code:
using Microsoft.Graph; using Microsoft.Graph.Auth; using Microsoft.Identity.Client; using System; using System.Threading.Tasks; namespace GraphClient { class Program { static String client_id = "{client_id}"; static String tenant_id = "{tenant_id}"; static String[] scopes = { "https://graph.microsoft.com/.default" }; static IPublicClientApplication _pca = null; private static IPublicClientApplication Pca { get { if(_pca == null ) { _pca = PublicClientApplicationBuilder .Create( client_id ) .WithTenantId( tenant_id ) .Build(); } return _pca; } } static InteractiveAuthenticationProvider _authProvider = null; private static InteractiveAuthenticationProvider AuthProvider { get { if(_authProvider == null ) { _authProvider = new InteractiveAuthenticationProvider( Pca, scopes ); } return _authProvider; } } static GraphServiceClient _graphClient = null; private static GraphServiceClient GraphClient { get { if(_graphClient == null ) { _graphClient = new GraphServiceClient( AuthProvider ); } return _graphClient; } } static void Main(string[] args) { Get_Me().Wait(); Console.WriteLine( $"\nPress any key to close..." ); Console.ReadKey(); } static async Task Get_Me() { User user = null; user = await GraphClient.Me.Request().GetAsync(); Console.WriteLine( $"Display Name = {user.DisplayName}\nEmail = {user.Mail}" ); } } }
To implement one of the other flows, you may be modifying the Client type ( line 15 in the code file above ) based on whether or not it is a confidential client or a public client ( see list at the beginning of this post ) and the property for it just below, and line 39 ( code file above) where we are setting the auth provider as well as the underlying member for that. So, for example, a confidential client using the client credentials flow would look like this in the same code file:
static String client_id = "{client_id}"; static String tenant_id = "{tenant_id}"; static String client_secret = "{client_secret}"; static String[] scopes = { "https://graph.microsoft.com/.default" }; static IConfidentialClientApplication _pca = null; private static IConfidentialClientApplication Pca { get { if(_pca == null ) { _pca = ConfidentialClientApplicationBuilder .Create( client_id ) .WithTenantId( tenant_id ) .WithClientSecret( client_secret ) .Build(); } return _pca; } } static ClientCredentialProvider _authProvider = null; private static ClientCredentialProvider AuthProvider { get { if(_authProvider == null ) { _authProvider = new ClientCredentialProvider( Pca ); } return _authProvider; } }
When I run this code, with the alternate client type I get: Message: /me request is only valid with delegated authentication flow. Which I think makes sense because you don’t have a user you have the application.
That is correct. I have another blog post explaining this: https://blogs.aaddevsup.xyz/2021/08/microsoft-graph-why-you-cannot-call-the-me-endpoint-with-a-token-acquired-via-the-client-credentials-grant-flow/