Azure AD Exception: Microsoft.AspNetCore.Authentication.RemoteAuthenticationHandler<TOptions>.HandleRequestAsync() - c#

I try add Azure AD auth. I alredy have a default auth with AccountController
When I try call https://localhost:44304/signin-oidc I get error
I try connect like:
services.AddMicrosoftIdentityWebAppAuthentication(Configuration);
or
services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApp(Configuration.GetSection("AzureAd"));
AzureAd implemented in appsettings, for test project it works.
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
endpoints.MapRazorPages();
});

When I try call https://localhost:44304/signin-oidc I get error
When you call above url by broswer directly, it should be Http GET request. This is the reason you are experiencing the phenomenon.
Step 1
Open F12 to monitor the Http request in the Network.
1. Under normal operation steps, the captured Http Request is of the post method.
call https://localhost:44304/signin-oidc by browser.
Related issue
Microsoft Account Authentication not working
#1012
CallbackPath is used for the middleware to receive the results of the remote auth. You do not need a route/controller/action for this path. Once it has processed the results and generated the sign-in identity/cookie, then it will redirect back to your app code, either to where it started or where you told it to return to in the initial challenge.
Recommendation: keep the default CallbackPath value /signin-microsoft and register https://localhost:50001/signin-microsoft in the MSA portal.

Related

Blazor Server with Microsoft Identity in IIS with virtual application

I've created a Blazor Server project using the standard Visual Studio 2022 template with authentication set to Microsoft Identity. It works locally without issue.
When I try to deploy it to the default website on an IIS server in a virtual application, it gives the following error:
Program.cs:
var builder = WebApplication.CreateBuilder(args);
var initialScopes = builder.Configuration["DownstreamApi:Scopes"]?.Split(' ') ??
builder.Configuration["MicrosoftGraph:Scopes"]?.Split(' ');
builder.Services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApp(builder.Configuration.GetSection("AzureAd"))
.EnableTokenAcquisitionToCallDownstreamApi(initialScopes)
.AddMicrosoftGraph(builder.Configuration.GetSection("MicrosoftGraph"))
.AddInMemoryTokenCaches();
builder.Services.AddControllersWithViews()
.AddMicrosoftIdentityUI();
builder.Services.AddAuthorization(options =>
{
// By default, all incoming requests will be authorized according to the default policy
options.FallbackPolicy = options.DefaultPolicy;
});
builder.Services.AddRazorPages();
builder.Services.AddServerSideBlazor()
.AddMicrosoftIdentityConsentHandler();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.MapControllers();
app.MapBlazorHub();
app.MapFallbackToPage("/_Host");
app.Run();
I think it is an issue with the return url, because the virtual application name is added to the address automatically. I have this url included in my app registration, but it still doesn't work.
I think after you see the error message page above, you may try to visit http://localhost or maybe you change the default home page url so http://localhost/the_word_you_covered and see if the user already signed in successfully.
I created a new Blazor server application with Microsoft Identity, then I fill the appsettings.json with tenant id, client id, and leave the CallbackPath as /signin-oidc by default. And in AAD, set redirect URL as https://localhost/signin-oidc. It worked well when test locally. After published to IIS, the sign in didn't work well so I comment the
builder.Services.AddAuthorization(options =>
{
// By default, all incoming requests will be authorized according to the default policy
options.FallbackPolicy = options.DefaultPolicy;
});
and content in the so that I can see more error issue.
if (!app.Environment.IsDevelopment()) { }
But after doing these steps, everything worked well except the sign in redirect back to http://localhost/signin-oidc. Pls note here we need to set the redirect URL as http in Azure AD portal because IIS uses HTTP by default. But since there's no page routing to signin-oidc.
=========================================
If what I said above is not the issue, I'm afraid you can create a self-signed certificate and bind it to the default website, then visiting https instead. Just now I tried again and it keep showing 500 error like screenshot below. Then I create self-signed certificate to use https then solved the 500 error.

Running custom C# middeware after authentication

In my Program.cs I have
app.UseRouting();
app.UseCors();
app.UseAuthentication();
app.UseMiddleware<MyCustomMiddleware>();
app.UseAuthorization();
app.UseEndpoints(cfg =>
{
cfg.MapControllers();
cfg.MapFallbackToController("Get", "Branding");
});
with the expectation that my custom middleware would run after authentication and therefore I would have a claims identity to play with.
But when my MyCustomMiddleware.Invoke is called the _next is AuthorizationMiddleware as expeted, but the context.User is not authenticated and has no claims.
However, the context.User is authenticated and has claims after _next.Invoke(context) returns.
So it looks like the middleware is running out of order.
What could be wrong?!
I believe that the behaviour you are seeing is correct if the AuthenticationMiddleware has yet to complete authenticating the user. Depending on your selected authentication scheme, the AuthenticationMiddleware may have returned back a HTTP 401 Challenge response to the client, or a HTTP 301 redirect to send the user to the authentication provider's login page if using OAuth. Check the context.Response inside of your middleware to be sure that this is in fact what is happening.
If the AuthenticationMiddleware hasn't short circuited the middleware, the unauthenticated request will still be passed on to the subsequently registered middleware before the response is sent back to the client.
Typically, its recommended that the AuthorizationMiddleware is ordered immediately after the AuthenticationMiddleware (see: ASP.NET Core Fundamentals Built-in Middleware), so that the user is properly authenticated and claims have been added. Because you have chosen to put a middleware in between, you are seeing the in-between process that ASP.NET core is following to authenticate and provide claims for the user.

Specify RedirectURI under openidconnect options - Azure AD, .NET6 C#

I have an azure Active Directory and have my app registered under it.
Under the RedirectURIs in the portal, i have specified this http://custom_domain/signin-oidc.
Under my startup.cs, i have these codes.
services.Configure<OpenIdConnectOptions>(AzureADDefaults.OpenIdScheme, options =>
{
options.Authority = options.Authority + "/v2.0";
options.TokenValidationParameters.ValidateIssuer = false;
});
All the information specified under the app settings is correct (ClientID, TenantID, etc)
When deployed to my Azure App Service, the redirect URI changes to the app service original url name instead of the custom domain.
Inspected the login page when my app was executed:
https://login.microsoftonline.com/5910deee------/oauth2/v2.0/authorize?client_id=2782------&redirect_uri=https%3A%2F%2F**WRONG REDIRECT URI WHICH WAS NOT SPECIFIED UNDER THE AZURE PORTAL AD REDIRECT URI**%3A44345%2Fsignin-oidc&response_type=id_token&scope=openid%20profile&response_mode=form_post&nonce=6379148910548699......
How can I specify the redirect uri in my codes, or have the MS login page redirect to my custom domain uri? Specifying under the PORTAL -> AD -> Authentication -> Redirect URIs does not work.
Below are the workaround you can follow to resolve the above issue;
Make sure that you have provided the redirect uri same as on our Azure AD application(Authentication >..Redirect Uri) in your appsettings.json file.
As stated by #Tinywang, If you have multiple redirect uri in your application please remove those and keep the same which you want to redirect after log-in.
i m getting the error "The path in 'value' must start with '/'. " when
i follow as per the image you shared. The value is /signin-oidc
initially
So if you have done with all the above steps , Please make sure that your redirect uri must be begin with https and not http as you have mentioned in the question it is http://custom_domain/signin-oidc which is not valid.
For example you can set something like:- https://contoso.com/abc/response-oidc.
Program.cs should look like this:-
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApp(builder.Configuration.GetSection("AzureAd"));
builder.Services.AddAuthorization(options =>
{
// By default, all incoming requests will be authorized according to the default policy.
options.FallbackPolicy = options.DefaultPolicy;
});
builder.Services.AddRazorPages()
.AddMicrosoftIdentityUI();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.MapRazorPages();
app.MapControllers();
app.Run();
And in appsettings.json
{
"AzureAd": {
"Instance": "https://login.microsoftonline.com/",
"Domain": "[ e.g. contoso.onmicrosoft.com]",
"TenantId": "00000-00000-0000000",
"ClientId": "11111111-222222-333",
"CallbackPath": "/signin-oidc",
"SignedOutCallbackPath ": "/signout-callback-oidc"
},
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"AllowedHosts": "*"
}
NOTE:- Make sure that you have enabled SSL value to true in Visual studio .
For complete setup and more information please refer the below Links:-
MICROSOFT DOCUMENTATION|Supported redirect uri and Configuration file.
Blog| Create an ASP.NET Web Application (.NET Framework – Web Forms or MVC) using Azure AD Authentication .
SO THREAD suggested by #diegosasw

Azure AD role not showing in Auth or ID token for guest user

I feel like this question has been asked several times before but I'm not getting clued in or finding out what I need to know.
I have an Azure AD with two tenants. Tenant 1 has all our users in it. Tenant 2 is meant for external users making inbound api calls - we are in the proof of concept stage right now.
All works great when I set up new users in tenant 2. The users are created, the app is created, the scopes for the api are defined and finally using the enterprise app, roles are created with local users assigned to the roles. The .Net Core app is decorated with [Authenticate Roles("Read, Write"], etc. The scopes are then validated using the HttpContext.VerifyUserHasAnyAcceptedScope(scopeRequiredByApi); inside each controller method. As I said, it all works great with users who have been defined as local users in Tenant 2.
If it helps, we are using Postman to test with.
However, if I modify the login call to simply use the guest user, which an existing user in the Azure AD client 1 tenant I see the following behavior. The user is Authenticate and a user_token as well as an id_token is returned. Calling the existing PUT and POST API methods always returns a 403 Forbidden. I had read that a guest id should use the auth_token so that is what I have done but to no avail.
If anyone has any advice on where I should look, if I am overlooking something simple or if there is a config value I'm not making I'd love to hear it. I realize I'm low on actual code snippets but there really aren't any. The API works just fine and the Postman call work great for local users. It's simply the guest users that aren't getting assigned to a "proper" role.
EDIT - the appsettings.json file relevant bits:
"AzureAd": {
"Instance": "https://login.microsoftonline.com/",
"ClientId": "xxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxxx",
"Domain": "tenant01.onmicrosoft.com", // the domain for tenant 1
"TenantId": "common"
},
And the startup.cs file:
public void ConfigureServices(IServiceCollection services)
{
services.AddMicrosoftIdentityWebApiAuthentication(Configuration);
services.AddControllers();
// some other code...
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseHttpsRedirection();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
The auth token for the guest user does show the scope but the role is missing. The id token for the guest user simply shows the standard user claims - Name, preferred_username, the issuing tenant, etc.
I'm missing something that's probably not terribly difficult to set up but I've no idea what to do from here.
We figured this out. No changes were made to the code or the json file. The URL used to call the authentication was modified. The URL that was changed from:
https://login.microsoftonline.com/oauth2/v2.0/token
TO this url
https://login.microsoftonline.com/< tenantid >/oauth2/v2.0/token
This change caused the role to appear in the id_token. I had read that the id_token needed to be used but I was not aware of the change that needed to be made to the url to include the tenant id.

Azure AD SSO: .Net Core 2.1 Single Sign On Based On Organization's Office 365 Username&Password

I have created an ASP.NET Core 2.1 MVC web application and I have used a simple login form to authenticate the users. Now We have decided to remove the login form and use a single sign-on option with my Organization's Office 365 user credentials or my office’s outlook username & password and followed the following Microsoft website but I could not choose the right SSO one.
This web app is a MVP (minimum viable product) project so we just don't want to use our own authentication & authorization process and only my organization people going to use this app so we have decided to use the Organization's Azure AD SSO. I am not using SAML or WS-Federation protocols in my web app but I just wanted to implement the SSO for my project.
I searched many sites on the internet, a few websites explained "No code is required to configure SSO but only Azure AD configurations" and some other websites explained with some piece of code also. So now I am totally confused that how should I achieve the SSO for my simple web application.
Hosted environment: Azure App Service
Application users: only organization users (internal web app)
My Startup.cs code:
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.Configure<CookiePolicyOptions>(options =>
{
// This lambda determines whether user consent for non-essential cookies is needed for a given request.
options.CheckConsentNeeded = context => true;
options.MinimumSameSitePolicy = SameSiteMode.None;
});
services.AddSession(options =>
{
options.Cookie.IsEssential = true;
});
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
//Fetching Connection string from APPSETTINGS.JSON
var ConnectionString = Configuration.GetConnectionString("MbkDbConstr");
//Entity Framework
services.AddDbContext<ShardingDbContext>(options => options.UseSqlServer(ConnectionString));
//Automapper Configuration
AutoMapperConfiguration.Configure();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseCookiePolicy();
app.UseSession();
app.UseAuthentication();
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller:required}/{action}/{id?}",
defaults: new { controller = "UserAccount", action = "UserLogin" });
});
}
}
Note: I have configured the app.UseAuthentication() & other functions but authentication part not used inside my projects.
If you want to Authenticate your users with App Services, refer the document to see how to enable AAD Authentication in app services.
Generally for any web application, you can configure App Registration in Azure AD. You can configure claim attribute as well in order to use SSO feature. Refer the document for how to configure app registration in Azure AD.

Categories