Graph authentication methods

Luan'i Jackson 20 Reputation points
2023-04-28T22:28:40.64+00:00

I'm new to Microsoft Graph, and Azure in general. I am able to follow this Quick Start guide (https://learn.microsoft.com/en-us/azure/active-directory/develop/web-app-quickstart?tabs=windows&pivots=devlang-aspnet-core) to create a new project and access Microsoft Graph to return user information.

In the Quick Start, the authentication is configured using this in startup.cs:

services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
                .AddMicrosoftIdentityWebApp(Configuration.GetSection("AzureAd"))
                    .EnableTokenAcquisitionToCallDownstreamApi(initialScopes)
                        .AddMicrosoftGraph(Configuration.GetSection("DownstreamApi"))
                        .AddInMemoryTokenCaches();

However, I need to use Microsoft Graph in an on-premise MVC web app that uses windows authentication. Its authentication is configured in middleware like:

builder.Services.AddAuthentication(NegotiateDefaults.AuthenticationScheme)
   .AddNegotiate();

My initial attempt to combine both has resulted in error

InvalidOperationException: IDW10503: Cannot determine the cloud Instance. The provided authentication scheme was ''. Microsoft.Identity.Web inferred 'Negotiate' as the authentication scheme. Available authentication schemes are 'Negotiate,Cookies,OpenIdConnect'. See https://aka.ms/id-web/authSchemes

How do I modify my middleware so I can can call Microsoft Graph from a web app that uses windows authentication?

Or, is this a futile attempt, that I should just create another project that uses OpenIDConnect?

ASP.NET Core
ASP.NET Core
A set of technologies in the .NET Framework for building web applications and XML web services.
4,682 questions
Microsoft Graph
Microsoft Graph
A Microsoft programmability model that exposes REST APIs and client libraries to access data on Microsoft 365 services.
12,555 questions
ASP.NET
ASP.NET
A set of technologies in the .NET Framework for building web applications and XML web services.
3,541 questions
0 comments No comments
{count} votes

3 answers

Sort by: Most helpful
  1. Luan'i Jackson 20 Reputation points
    2023-04-28T23:27:03.8833333+00:00

    OK. I think I've just answered my own question, kind of. Since our on-premise AD sync up to Azure AD, I can just use the OpenIDConnect and remove the one for Windows authentication.

    If someone has an answer as to how to use Windows Authentication and still call Microsoft Graph, please post it. Thank you.


  2. Antonio 250 Reputation points Microsoft Vendor
    2023-05-02T12:18:04.3033333+00:00

    Hi Luan'i Jackson,

    Thanks for posting on the Q&A forum. As mentioned in the error message IDW10503 refers to specifying the authentication scheme used to retrieve the token (In section the appsettings.json). You can use the openid2 or B2C authentication scheme in startup.cs (see below).

    Specify the authentication scheme

    services.AddAuthentication() // No default scheme
            .AddMicrosoftIdentityWebApp(Configuration.GetSection("AzureAd"), "openid2")
                .EnableTokenAcquisitionToCallDownstreamApi(Configuration.GetValue<string>("DownstreamApi:Scopes")?.Split(' '))
                    .AddMicrosoftGraph(Configuration.GetSection("DownstreamApi"))
                    .AddInMemoryTokenCaches();
    
    services.AddAuthentication() // No default scheme either
            .AddMicrosoftIdentityWebApp(Configuration.GetSection("AzureAdB2C"), "B2C", "cookiesB2C")
                .EnableTokenAcquisitionToCallDownstreamApi(Configuration.GetValue<string>("DownstreamB2CApi:Scopes")?.Split(' '))
                    .AddDownstreamWebApi("DownstreamB2CApi", Configuration.GetSection("DownstreamB2CApi"));
    

    Since web app part is generating the token (not AAD). the authentication scheme should be OpenIdConnect

    Calling ITokenAcquisition.GetAccessTokenForUserAsync throws IDW10503 error

    For consideration see AAD to authentication Office 365 users with a synced on-premise AD/user accounts & additional info about authentication Vs authorization. (See below for an example implementation)

    Note that this example project requires to use a local database file to store authentication configuration data.

    Developing ASP.NET Apps with Azure Active Directory

    Authentication vs. Authorization

    User's image


  3. Konstantinos Passadis 19,276 Reputation points MVP
    2023-05-02T15:48:10.2366667+00:00

    Hello

    The error message you received suggests that Microsoft.Identity.Web was not able to determine the cloud instance for your app. This can happen if the AzureAd section in your configuration is missing the Instance key, which is used to specify the Azure AD authority.

    To use Microsoft.Identity.Web with Windows Authentication in an on-premise MVC web app, you can follow these steps:

    Add the Microsoft.Identity.Web NuGet package to your project.

    Update the authentication middleware in your Startup.cs to use AddMicrosoftIdentityWebApi instead of AddNegotiate:

    services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)

    **.AddMicrosoftIdentityWebApi(Configuration.GetSection("AzureAd"));**
    

    Note that we are using JwtBearerDefaults.AuthenticationScheme instead of NegotiateDefaults.AuthenticationScheme, since we will be using a JWT bearer token to authenticate requests to Microsoft Graph.

    1. Configure your app to use Windows Authentication by adding the following code to your ConfigureServices method:

    services.AddAuthentication(NegotiateDefaults.AuthenticationScheme)

    **.AddNegotiate();**
    

    services.AddAuthorization();

    services.AddControllers();

    1. In your Configure method, add the following middleware to enable Windows Authentication:

    app.UseAuthentication();

    app.UseAuthorization();

    1. Update your app's configuration to include the necessary settings for Microsoft.Identity.WebApi, including the Instance key:

    "AzureAd": {

    "Instance": "https://login.microsoftonline.com/",

    "Domain": "<your-tenant-name>.onmicrosoft.com",

    "TenantId": "<your-tenant-id>",

    "ClientId": "<your-client-id>",

    "CallbackPath": "/signin-oidc"

    },

    "DownstreamApi": {

    "BaseUrl": "https://graph.microsoft.com/v1.0",

    "Scopes": "User.Read.All"

    }

    Note that the Instance value should be set to https://login.microsoftonline.com/ followed by your Azure AD tenant ID or domain name.

    1. Finally, you can use the AddMicrosoftIdentityWebApi extension method to configure token acquisition and Microsoft Graph access for your app. Here's an example:

    services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)

    **.AddMicrosoftIdentityWebApi(Configuration.GetSection("AzureAd"));**
    

    services.Configure<JwtBearerOptions>(JwtBearerDefaults.AuthenticationScheme, options =>

    {

    **options.TokenValidationParameters.ValidAudiences = new[] { "https://graph.microsoft.com" };**
    
    **options.TokenValidationParameters.NameClaimType = "name";**
    

    });

    services.AddHttpClient();

    services.AddTransient<GraphServiceClient>(sp =>

    {

    **var httpClient = sp.GetRequiredService<HttpClient>();**
    
    **var graphOptions = Configuration.GetSection("DownstreamApi").Get<DownstreamApiOptions>();**
    
    **var tokenAcquisitionOptions = new TokenAcquisitionOptions();**
    
    **var tokenAcquisition = sp.GetRequiredService<ITokenAcquisition>();**
    
    **var accessToken = tokenAcquisition.GetAccessTokenForUserAsync(graphOptions.Scopes.Split(' '), user: null).Result;**
    
    **httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);**
    
    **return new GraphServiceClient(httpClient);**
    

    });

    This code registers an instance of the Microsoft Graph SDK's GraphServiceClient as a transient service, using an HttpClient instance configured with an access token obtained using the ITokenAcquisition service. Note that the TokenValidationParameters are set to specify the audience and name claim type for the JWT bearer token.

    I hope this helps !

    If it does kindly mark the answer as Accepted and upvote or send us additional feedback !

    Regards


Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.