Hi Paul Smith,
Thanks for reaching out.
You need to follow the following steps:
- Go to corresponding app registration.
- Go To Manage Blade - Authentication tab.
- Click upon Add a platform and select Mobile and desktop application (Since VSTO com add-in is a desktop app)
- In Redirect URIs Add a URI and set it to following and check the checkbox https://login.microsoftonline.com/common/oauth2/nativeclient
- Save your changes.
Now coming towards the code part.
You can use the following code to get the User authenticated and create corresponding GraphServiceClient object in order to call Graph API from your VSTO add-in.
private const string CLIENT_ID = "";
private const string TENANT_ID = "";
private const string AUTHORITY = "https://login.microsoftonline.com/" + TENANT_ID;
private const string REDIRECT_URI ="https://login.microsoftonline.com/common/oauth2/nativeclient";
private static AuthenticationResult AuthResult;
private static IPublicClientAppliction PublicClientApp;
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls| SecurityProtocolType.Tls11| SecurityProtocolType.Tls12| SecurityProtocolType.Ssl3;
//Intilializing public client app
PublicClientApp = PublicClientApplicationBuilder.Create(CLIENT_ID)WithAuthority(AUTHORITY)
.WithRedirectUri(REDIRECT_URI).
WithLogging((level, message, containsPii) =>
{ Debug.WriteLine($"MSAL: {level} {message} "); }
, LogLevel.Warning, enablePiiLogging: false, enableDefaultPlatformLogging: true)
.Build();
//Authenticating the user and fetching the token. First attempt to aquire the token silently if it fails open the authentication pop up. try {
try
{
IEnumerable<IAccount> accounts = await PublicClientApp.GetAccountsAsync().ConfigureAwait(true);
IAccount firstAccount = accounts.FirstOrDefault();
AuthResult = await PublicClientApp.AcquireTokenSilent(scopes, firstAccount)
.ExecuteAsync();
}
catch (MsalUiRequiredException ex){
// A MsalUiRequiredException happened on AcquireTokenSilentAsync. This indicates you need to call AcquireTokenAsync to acquire a token
try
{
AuthResult = await PublicClientApp.AcquireTokenInteractive(scopes)
.WithPrompt(Prompt.SelectAccount)
.ExecuteAsync()
.ConfigureAwait(false);
}
catch (Exception exc)
{
//log the exception;
}
}
//Creating the Graph service client object
GraphServiceClient graphServiceClient =
new GraphServiceClient(new DelegateAuthenticationProvider(async (requestMessage) =>
{
// It's good practice to not do work on the UI thread, so use ConfigureAwait(false) whenever possible.
IEnumerable<IAccount> accounts = await PublicClientApp.GetAccountsAsync().ConfigureAwait(true);
IAccount firstAccount = accounts.FirstOrDefault();
AuthResult = await PublicClientApp.AcquireTokenSilent(scopes, firstAccount)
.ExecuteAsync();
// Add the access token in the Authorization header of the API request.
requestMessage.Headers.Authorization =
new AuthenticationHeaderValue("Bearer", AuthResult.AccessToken);
})
);
//Making the Graph Call
User user = graphServiceClient.me.Request().GetAsync();
In case you need any help regarding this code and also anything related to Token management fell free to comment.
If the answer is helpful, please click "Accept Answer" and kindly upvote it. If you have extra questions about this answer, please click "Comment".