1

I am struggling to get user information from Azure AD, with Microsof Graph with a .NET Core API. I tried a couple tutorials but I got stuck on several issues.

Microsoft Graph Connect Sample for ASP.NET Core 3.1 https://learn.microsoft.com/en-us/samples/microsoftgraph/aspnetcore-connect-sample/microsoft-graph-connect-sample-for-aspnet-core-31/)

This tutorial look promising, but it turns out it requires a multi tenant Azure Application - but mine is Single Tenant.

Call MS Graph APIs from ASP.NET Core 3.1 (https://github.com/cmatskas/aspnetcorewithgraph/blob/master/WebApplication1/Startup.cs)

This tutorial look interesting but it uses two NuGet packages in preview mode. And when I try the code (see my startup.cs) it throws issues saying

"The MetadataAddress or Authority must use HTTPS unless disabled for development by setting RequireHttpsMetadata=false."

I tried set it to false in my addJwTBearer option, but the issue remains.

Any chance you guys know of a good tutorial for my case, or what is wrong with my startup file?

Startup.cs

public void ConfigureServices(IServiceCollection services)
    {            
        // APISettings
        services.Configure<APISettings>(Configuration.GetSection("APISettings"));
        services.Configure<AppSettings>(Configuration.GetSection("AppSettings"));
        // Add our Config object so it can be injected
        //services.Configure<MyConfig>(Configuration.GetSection("MyConfig"));
        AppConstants.AppUserRoles = new AppUserRoles();
        AppConstants.AppUserRoles.AdminDatabaseID = Configuration.GetSection("AppSettings").GetSection("AppUserRoles").GetValue<int>("AdministratorDatabaseID");
        AppConstants.AppUserRoles.UserDatabaseID = Configuration.GetSection("AppSettings").GetSection("AppUserRoles").GetValue<int>("UserDatabaseID");
        AppConstants.AppUserRoles.ManagerDatabaseID = Configuration.GetSection("AppSettings").GetSection("AppUserRoles").GetValue<int>("ManagerDatabaseID");

        // Repositories            
        services.AddTransient<IUserRepository, UserRepository>();
        services.AddTransient<ITimeLogRepository, TimeLogRepository>();
        services.AddTransient<IReportRepository, ReportRepository>();
        services.AddTransient<ICalendarRepository, CalendarRepository>();

        // Models
        services.AddTransient<CreateTimeLogResponse>();

        // Services
        services.AddTransient<IHttpContextAccessor, HttpContextAccessor>();
        services.AddTransient<IDatabase, Database>();
        services.AddTransient<ISessionService, SessionService>();
        services.AddTransient<IIdentityClaimService, IdentityClaimService>();
        services.AddTransient<IUserService, UserService>();
        services.AddTransient<TimeLogService>();
        services.AddTransient<ReportsService>();
        services.AddTransient<ICalendarService, CalendarService>();            

        // AutoMapper
        services.AddAutoMapper(typeof(Startup));

        // Were only using API.
        services
            .AddControllers().AddJsonOptions(options =>
            {
                options.JsonSerializerOptions.Converters.Add(new DateTimeConverter());
                options.JsonSerializerOptions.PropertyNamingPolicy = JsonNamingPolicy.CamelCase;
                options.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter());
            });

        // Azure AD Authentication
        services
            .AddAuthentication(sharedOptions =>
            {
                sharedOptions.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
                sharedOptions.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
            })                
            .AddJwtBearer(options =>
            {
                var authSettings = Configuration.GetSection("AzureAd").Get<AzureAdOptions>();

                options.Audience = authSettings.ClientId;
                options.Authority = authSettings.Authority;
                options.RequireHttpsMetadata = false;
            });

        // MS Graph.                        
        services.AddSignIn(Configuration);
        services.AddWebAppCallsProtectedWebApi(Configuration, new string[] { "user.read" })
           .AddInMemoryTokenCaches(); // Or .AddDistributedTokenCaches(); depending on which token cache provider from Microsoft.Identity.Web you would like to use.
        services.AddGraphService(Configuration);

        // In production, the React files will be served from this directory
        services.AddSpaStaticFiles(configuration =>
        {
            configuration.RootPath = "ClientApp/build";
        });

        services.AddDistributedMemoryCache();

        services.AddSession(options =>
        {
            // Set a short timeout for easy testing.
            options.IdleTimeout = TimeSpan.FromMinutes(1);
            options.Cookie.HttpOnly = true;
            // Make the session cookie essential
            options.Cookie.IsEssential = true;
        });
    }

1 Answer 1

1

Microsoft Graph Connect Sample for ASP.NET Core 3.1 should work with single tenant applications.

Update GraphAuthProvider.cs line 28 to:

    .WithAuthority(AzureCloudInstance.AzurePublic, AadAuthorityAudience.AzureAdMyOrg)
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks, I am one step further to solve the issue! The site loads, but complain the access-token is missing, when calling _app.GetAccountAsync(userId). Maybe the service.AddDistributedMemoryCache() cache it somehow.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.