I am trying to integrate AD B2C in a hosted Blazor WASM application.
I need to intercept the creation of new user in order to populate some entries in the database and also redirect the user to a configuration page.
Some previous posts suggest of hooking an event handler to the authentication configuration, as in
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApi(JwtBearerOptions =>
{
JwtBearerOptions.Events ??= new JwtBearerEvents();
JwtBearerOptions.Events.OnTokenValidated += OnTokenValidatedCallbackFunc;
},
configureMicrosoftIdentityOptions =>
{
Configuration.Bind("AzureAdB2C", configureMicrosoftIdentityOptions);
});
However the event is not triggered. The only event that seems to be triggered is OnMessageReceived. However, that is not useful in my case because I need to access the claims, and the Principal does not seems to be defined if I examine the MessageReceivedContext (Principal is always null).
Any help is greatly appreciated! Thank you in advance.
Related
Working on a Razor Page web application and trying to let it authenticate users against Azure b2c. I have configured the following code.
builder.Services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApp(builder.Configuration.GetSection("AzureAdB2C"));
builder.Services.AddAuthorization(options =>
{
options.FallbackPolicy = options.DefaultPolicy;
});
builder.Services.AddRazorPages(options =>
{
options.Conventions.AllowAnonymousToPage("/Index");
}).AddMicrosoftIdentityUI();
But I keep getting the error that the application is not configured for implicit flow.
Message contains error: 'unauthorized_client', error_description: 'AADB2C90057: The provided application is not configured to allow the 'OAuth' Implicit flow.
But when I configure it as a SPA application (see screenshot) it works.
But a Razor Page Webapplication is not a SPA. What am I missing here? Is it still safe?
When I use the following code it makes no difference :-(
services.AddMicrosoftIdentityWebAppAuthentication(Configuration, Constants.AzureAdB2C);
Within App Manifest:
"oauth2AllowImplicitFlow": true
I downloaded the Azure examples for daemon app, and have a bearer token at the end of the debug code. The thing that I'm stuck on is calling the Web API with this token to Authenticate. This is in .NET Core 2.2
public void ConfigureServices(IServiceCollection services)
{
// This is required to be instantiated before the OpenIdConnectOptions starts getting configured.
// By default, the claims mapping will map claim names in the old format to accommodate older SAML applications.
// 'http://schemas.microsoft.com/ws/2008/06/identity/claims/role' instead of 'roles'
// This flag ensures that the ClaimsIdentity claims collection will be built from the claims in the token
JwtSecurityTokenHandler.DefaultMapInboundClaims = false;
services.AddProtectWebApiWithMicrosoftIdentityPlatformV2(Configuration);
services.Configure<JwtBearerOptions>(AzureADDefaults.JwtBearerAuthenticationScheme, options =>
{
//options.TokenValidationParameters.RoleClaimType = "roles";
});
//// Creating policies that wraps the authorization requirements
services.AddAuthorization(options =>
{
options.AddPolicy("AdminUsers", policy => policy.RequireRole("AdminUsers"));
});
services.AddControllers();
}
[HttpGet]
[Authorize]
public IActionResult Get()
{
return Ok(TodoStore.Values);
}
I took the roles out and just made it available to everyone, not sure if I need to put Group authorization on here for it to work. I can't get it to work out of the box. I'm thinking of modifying some of these to make it work. We only need to authenticate, then use their email to get roles base on which application they are in.
Thanks in advance.
Please refer this Microsoft documentation
For daemon apps, the web APIs that you call need to be pre-approved.
There's no incremental consent with daemon apps. (There's no user
interaction.) The tenant admin needs to provide consent in advance for
the application and all the API permissions.
and there is a GitHub sample for daemon application which consume Web Api and if you are trying to verify app roles in the APIs called by a Daemon apps please go through this documentation
We have a SaaS web app and our clients are requiring SSO authentication for each of them. We are using AzureADB2C and it works great, but now are looking at adding SSO.
I put in the SSO setup into the B2C tenet and it works great, but really messed up our login screen with a "MyCompanySSO" button to log in with, on our customer-facing login screen.
So now my idea is to have a separate user flow that handles each SSO setup. Starting with us. We'd go to MyCompany.OurSaaSApp.us and that'd forward them directly to the user flow endpoint and prompt them to login with their SSO account (AzureAD).
This all seems to try to work, but I'm getting these errors within the AzureADB2C middleware:
Microsoft.AspNetCore.Authentication.OpenIdConnect.OpenIdConnectHandler:Warning: .AspNetCore.Correlation. state property not found.
Microsoft.AspNetCore.Authentication.OpenIdConnect.OpenIdConnectHandler:Information: Error from RemoteAuthentication: Correlation failed..
Then I get pumped out onto a error page and the login fails.
So 2 things...
1.) Am I going in the right direction knowing what we're wanting to accomplish
2.) What do we need to do to resolve this?
Thanks everyone for the help, it's been greatly appreciated.
(note:)
Just to reiterate. The SSO works properly when the custom identity provider is attached to the existing SignUpOrIn UserFlow I have configured in the app. I'm only getting this error when I try to use another UserFlow that I want to use specifically for this SSO.
I'm not sure about that specific error, although "state" parameter is a parameter that your app sends in the request that will be returned in the token for correlation purposes.
Using and different policy for each federation sounds like the right approach, but if you are doing from a single instance of your app, you'll need to modify the OIDC protocol message with the correct authority (ie policy) on redirect.
In your OIDC middleware configuration, set up a handler for the RedirectToIdentityProvider notification. Then handle it with something like:
private Task OnRedirectToIdentityProvider(RedirectToIdentityProviderNotification<OpenIdConnectMessage, OpenIdConnectAuthenticationOptions> notification)
{
//var policy = notification.OwinContext.Get<string>("Policy");
var tenantSegment = notification.Request.Path.Value.Split(new char [] { '/'}, StringSplitOptions.RemoveEmptyEntries)[0];
if (!string.IsNullOrEmpty(tenantSegment) && !tenantSegment.Equals(DefaultPolicy))
{
notification.ProtocolMessage.IssuerAddress = notification.ProtocolMessage.IssuerAddress.ToLower().Replace(DefaultPolicy.ToLower(), $"B2C_1A_{tenantSegment.ToLower()}_SignUpSignInPolicy");
}
return Task.FromResult(0);
}
If you need to inject anything else tenant-related, that would be the place to do it.
I have an MVC Core 2.1 application, and am using Azure AD B2C (2.1.1) as the identity provider.
I want to call a function when a user signs in and signs out, and am guessing I need to put this in the middleware.
In the previous version of the AD B2C, there was a function:
app.UseOpenIdConnectAuthentication(options);
which had options that made notification functions available:
Notifications = new OpenIdConnectAuthenticationNotifications
{
AuthenticationFailed = this.AuthenticationFailed,
RedirectToIdentityProvider = this.OnRedirectToIdentityProvider
}
The app.UseOpenIdConnectAuthentication(options); function is now marked as obsolete.
I could put in a middleware call like this:
app.Use((context, next) =>
{
if(/*context handler referrer includes "B2C_1_SignUpPolicy"*/)
{
// User has signed-in
}
return next.Invoke();
}
… but this would be called for every request and cannot be adapted to also call a function when the user signs out.
So do I set up notifications in the app.UseAuthentication(); version?
I've created a code sample at GitHub for an ASP.NET Core 2.1 web application that authenticates an end user against Azure AD B2C using the ASP.NET Core 2.1 authentication middleware for Azure AD B2C, acquires an access token using MSAL.NET, and accesses a web API using this access token.
It acquires the access token by handling the OpenIdConnectOptions.Events.OnAuthorizationCodeReceived event.
You might be able to develop the similar code to handle another OpenIdConnectOptions.Events event.
I am using the following bits against my Azure AD to authenticate with ASP.NET Core.
https://azure.microsoft.com/en-us/resources/samples/active-directory-dotnet-webapp-openidconnect-aspnetcore/
https://github.com/Azure-Samples/active-directory-dotnet-webapp-openidconnect-aspnetcore
I have the basic login/auth working after creating an Azure AD app. User can login/logout.
My question is given this, what's the best way when a user Auth's to log to a DB? I thought about making the redirect URL to an endpoint, saving, then just redirecting back to "Home" but is that ideal?
Also, is it possible to retrieve a bearer token via this approach? Or does this require another type of call or extending "scope"? So that for example I could retrieve the authenticated users Manager.
https://graph.microsoft.com/v1.0/me/manager
My question is given this, what's the best way when a user Auth's to log to a DB? I thought about making the redirect URL to an endpoint, saving, then just redirecting back to "Home" but is that ideal?
This way only able to log those who already sign-in your app successfully. It is not able to log those users who are attempt to sign-in your app but enter the wrong password.
Azure AD already provide lots of report to gain visibility into the integrity and security of your organization’s directory.( refer here)
And if you are using the Azure AD Premium, you can review the sign-in activities via the Azure new portal below:
And if you want to store the sign-in activity in your web app, you can write the custom code after the token is verified. Here is the code for your reference:
// Configure the OWIN pipeline to use OpenID Connect auth.
app.UseOpenIdConnectAuthentication(new OpenIdConnectOptions
{
ClientId = Configuration["AzureAD:ClientId"],
Authority = String.Format(Configuration["AzureAd:AadInstance"], Configuration["AzureAd:Tenant"]),
ResponseType = OpenIdConnectResponseType.IdToken,
PostLogoutRedirectUri = Configuration["AzureAd:PostLogoutRedirectUri"],
Events = new OpenIdConnectEvents
{
OnRemoteFailure = OnAuthenticationFailed,
OnTokenValidated = context => {
//write the custom code to store users login-in
return Task.FromResult(0); }
},
});
Also, is it possible to retrieve a bearer token via this approach?
Yes. We can get the token after receive the authorization code. You can refer the code sample here to acquire the token from asp.net core app.