I have a MVC3 application, which has it's own authentication( when user providers username and password, it will redirect to landing page), Now the users are migrated to AzureB2C, so they have an accounts in the AzureB2C. I have setup the AzureADB2C account. Now once user logged into AzureB2C, user will be displayed with sceen, if user clicks on a button, I have to redirect him my MVC3 application and by-pass the authentication.
MVC3 application is used Form's Authentication and Session, Please suggest me how do I need to start ?
In MVC3 application, I have tried like this https://github.com/Azure-Samples/active-directory-b2c-dotnet-webapp-and-webapi/blob/main/TaskWebApp/App_Start/Startup.Auth.cs
[assembly: OwinStartup(typeof(WebApp_OpenIDConnect_DotNet_B2C.Startup))]
namespace WebApp_OpenIDConnect_DotNet_B2C
{
public partial class Startup
{
public void Configuration(IAppBuilder app)
{
ConfigureAuth(app);
}
}
}
public partial class Startup
{
// App config settings
private static string clientId = ConfigurationManager.AppSettings["ida:ClientId"];
private static string aadInstance = ConfigurationManager.AppSettings["ida:AadInstance"];
private static string tenant = ConfigurationManager.AppSettings["ida:Tenant"];
private static string redirectUri = ConfigurationManager.AppSettings["ida:RedirectUri"];
// B2C policy identifiers
public static string SignUpPolicyId = ConfigurationManager.AppSettings["ida:SignUpPolicyId"];
public static string SignInPolicyId = ConfigurationManager.AppSettings["ida:SignInPolicyId"];
public static string ProfilePolicyId = ConfigurationManager.AppSettings["ida:UserProfilePolicyId"];
public void ConfigureAuth(IAppBuilder app)
{
app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);
app.UseCookieAuthentication(new CookieAuthenticationOptions());
//// Configure OpenID Connect middleware for each policy
//app.UseOpenIdConnectAuthentication(CreateOptionsFromPolicy(SignUpPolicyId));
//app.UseOpenIdConnectAuthentication(CreateOptionsFromPolicy(ProfilePolicyId));
app.UseOpenIdConnectAuthentication(CreateOptionsFromPolicy(SignInPolicyId));
}
// Used for avoiding yellow-screen-of-death
private Task AuthenticationFailed(AuthenticationFailedNotification<OpenIdConnectMessage, OpenIdConnectAuthenticationOptions> notification)
{
notification.HandleResponse();
if (notification.Exception.Message == "access_denied")
{
notification.Response.Redirect("/");
}
else
{
notification.Response.Redirect("/Home/Error?message=" + notification.Exception.Message);
}
return Task.FromResult(0);
}
private OpenIdConnectAuthenticationOptions CreateOptionsFromPolicy(string policy)
{
System.Net.ServicePointManager.SecurityProtocol |= SecurityProtocolType.Tls12;
//https://fabrikamb2c.b2clogin.com/tfp/{0}/{1}
var aadinstance = $"https://{tenantName}/{tenantName}/B2C_1A_SIGNUP_SIGNIN_EPP";
var metadata = $"{aadinstance}/v2.0/.well-known/openid-configuration";
return new OpenIdConnectAuthenticationOptions
{
// For each policy, give OWIN the policy-specific metadata address, and
// set the authentication type to the id of the policy
//MetadataAddress = String.Format(aadInstance, tenant, policy),
//MetadataAddress = aadInstance,
MetadataAddress = metadata,
AuthenticationType = policy,
// These are standard OpenID Connect parameters, with values pulled from web.config
ClientId = clientId,
RedirectUri = redirectUri,
PostLogoutRedirectUri = redirectUri,
Notifications = new OpenIdConnectAuthenticationNotifications
{
//AuthenticationFailed = AuthenticationFailed,
RedirectToIdentityProvider = OnRedirectToIdentityProvider,
AuthorizationCodeReceived = OnAuthorizationCodeReceived,
AuthenticationFailed = OnAuthenticationFailed,
},
Scope = "openid profile offline_access",
//Scope= Microsoft.IdentityModel.Protocols.OpenIdConnectScopes.OpenIdProfile,
ResponseType = "id_token",
//ResponseType = "code",
// This piece is optional - it is used for displaying the user's name in the navigation bar.
TokenValidationParameters = new TokenValidationParameters
{
NameClaimType = "name",
},
CookieManager = new SystemWebCookieManager()
};
}
private Task OnRedirectToIdentityProvider(RedirectToIdentityProviderNotification<OpenIdConnectMessage, OpenIdConnectAuthenticationOptions> notification)
{
var policy = notification.OwinContext.Get<string>("Policy");
if (!string.IsNullOrEmpty(policy) && !policy.Equals(Globals.DefaultPolicy))
{
notification.ProtocolMessage.Scope = OPID.OpenIdConnectScope.OpenId;
notification.ProtocolMessage.ResponseType = OPID.OpenIdConnectResponseType.IdToken;
notification.ProtocolMessage.IssuerAddress = notification.ProtocolMessage.IssuerAddress.ToLower().Replace(Globals.DefaultPolicy.ToLower(), policy.ToLower());
}
return Task.FromResult(0);
}
private Task OnAuthenticationFailed(AuthenticationFailedNotification<OpenIdConnectMessage, OpenIdConnectAuthenticationOptions> notification)
{
notification.HandleResponse();
// Handle the error code that Azure AD B2C throws when trying to reset a password from the login page
// because password reset is not supported by a "sign-up or sign-in policy"
if (notification.ProtocolMessage.ErrorDescription != null && notification.ProtocolMessage.ErrorDescription.Contains("AADB2C90118"))
{
// If the user clicked the reset password link, redirect to the reset password route
notification.Response.Redirect("/Account/ResetPassword");
}
else if (notification.Exception.Message == "access_denied")
{
notification.Response.Redirect("/");
}
else
{
notification.Response.Redirect("/Home/Error?message=" + notification.Exception.Message);
}
return Task.FromResult(0);
}
private async Task OnAuthorizationCodeReceived(AuthorizationCodeReceivedNotification notification)
{
try
{
/*
The `MSALPerUserMemoryTokenCache` is created and hooked in the `UserTokenCache` used by `IConfidentialClientApplication`.
At this point, if you inspect `ClaimsPrinciple.Current` you will notice that the Identity is still unauthenticated and it has no claims,
but `MSALPerUserMemoryTokenCache` needs the claims to work properly. Because of this sync problem, we are using the constructor that
receives `ClaimsPrincipal` as argument and we are getting the claims from the object `AuthorizationCodeReceivedNotification context`.
This object contains the property `AuthenticationTicket.Identity`, which is a `ClaimsIdentity`, created from the token received from
Azure AD and has a full set of claims.
*/
IConfidentialClientApplication confidentialClient = MsalAppBuilder.BuildConfidentialClientApplication();
// Upon successful sign in, get & cache a token using MSAL
AuthenticationResult result = await confidentialClient.AcquireTokenByAuthorizationCode(Globals.Scopes, notification.Code).ExecuteAsync();
}
catch (Exception ex)
{
//throw new HttpResponseException(new HttpResponseMessage
//{
// StatusCode = HttpStatusCode.BadRequest,
// ReasonPhrase = $"Unable to get authorization code {ex.Message}."
//});
}
}
}
public static class MsalAppBuilder
{
/// <summary>
/// Shared method to create an IConfidentialClientApplication from configuration and attach the application's token cache implementation
/// </summary>
public static IConfidentialClientApplication BuildConfidentialClientApplication()
{
IConfidentialClientApplication clientapp = ConfidentialClientApplicationBuilder.Create(Globals.ClientId)
.WithClientSecret(Globals.ClientSecret)
.WithRedirectUri(Globals.RedirectUri)
.WithB2CAuthority(Globals.B2CAuthority)
.Build();
// Important: for simplicity, this sample showcases an in-memory cache
// For eviction policies and for using a distribued cache see:
// https://learn.microsoft.com/en-us/azure/active-directory/develop/msal-net-token-cache-serialization?tabs=aspnet
//Add an in-memory token cache with options
//clientapp.AddInMemoryTokenCache();
return clientapp;
}
I have added redirectURI(is http://localhost:43067/accountb2c in AzureB2C and checked both code and access token checkboxes.
In MVC3 application, created accountb2c and added index action. // To execute a policy, you simply need to trigger an OWIN challenge. // You can indicate which policy to use by specifying the policy id as the AuthenticationType
HttpContext.GetOwinContext().Authentication.Challenge(
new AuthenticationProperties() { RedirectUri = "/" }, Startup.SignInPolicyId);