Asp.Netcore Web app with Azure AD b2c redirect url - asp.net-core

Azure AD B2C is setup for authentication in Asp.netCore web app. The authentication process works perfectly. After authentication, the user needs to be redirected back the page where the login was initiated at.
the way the current flow happens:
This is the button <a class="btn btn-primary" asp-area="AzureADB2C" asp-controller="Account" asp-action="SignIn">Sign in</a>
PublicPage (has an sign-in/register button) on part of page that user need be authenticated to interact with -> signin button clicked -> redirected to Azure AD B2C -> user returned to IndexPage.
the way the needs to be:
PublicPage (has an sign-in/register button) on part of page that user need be authenticated to interact with -> signin button clicked -> redirected to Azure AD B2C -> user returned to PublicPage.
EDIT
#Jit_MSFT thanks for the suggestion, but I'm not exactly sure where to add those configurations.
services.AddAuthentication(AzureADB2CDefaults.AuthenticationScheme)
.AddAzureADB2C(options => {
Configuration.Bind("AzureAdB2C", options);
});
The settings above don't have those options. Also there are several page need to have that dynamic ability.
context.Properties.RedirectUri = "/xxxx;
this seems like i wold be locked into one page on the returnUrl

In your AccountController, please define the SignIn method as something like:
public async Task SignIn()
{
var redirectUri = ... // your redirect URI
await HttpContext.ChallengeAsync(AzureADB2CDefaults.AuthenticationScheme,
new AuthenticationProperties { RedirectUri = redirectUri });
}
You may also check other details and options in this answer
In addition, please check if, in Azure AD, you have to register your client app with a matching redirect URI (more details here) :)

Related

ServiceStack Authentication IsAuthenticated always false for users authenticated via facebook

Hi am trying to use OAuth authentication FacebookAuthProvider provided by servicestack
var AppSettings = appHost.AppSettings;
appHost.Plugins.Add(new AuthFeature(() => new CustomUserSession(),
new IAuthProvider[] {
new CredentialsAuthProvider(AppSettings),
new FacebookAuthProvider(AppSettings),
new GoogleAuthProvider(AppSettings)
}));
I have implement custom AuthEvents and I have access to authorized user data
but after RedirectUrl happens in endpoint session is empty and IsAuthenticated property is false
In the same time from Controller I can see that created session successfully saved in Cache
This scenario occurred only if user doesn't login in facebook in the browser yet, but for user that already logged in facebook, authentication works fine
What am I doing wrong ?
Thanks in advance!
Updates:
Scenario for repsoducing:
ensure that you didn't loged in facebook in browser (open facebook.com and log out if need)
run web app (project which created with template mvcauth)
try to login via facebook
3.1. for first attempt you will be redirected to https://www.facebook.com/login.php? page for specify your facebook account credentials
after first attempt you will be returned to web app page /Account/Login#s=1 but User.Identity.IsAuthenticated = false in AccountController.Login and you still unauthorized.
after second attempt you will finally successfully logged in
At the same time after first attempt Session with user data will be created and saved in Cache, it looks like after redirecting from page 'https://www.facebook.com/login.php' а new session being created without auth data, but for second attempt we successfully login, maybe the core of issue is redirection from 'https://www.facebook.com/login.php'
In order to be able to use ServiceStack.Auth in MVC and vice-versa you'll need to register the NetCoreIdentityAuthProvider which provides integration between ServiceStack Authenticated Sessions and ASP.NET Core's Claims Principal, e.g:
public void Configure(IAppHost appHost)
{
var AppSettings = appHost.AppSettings;
appHost.Plugins.Add(new AuthFeature(() => new CustomUserSession(),
new IAuthProvider[] {
new NetCoreIdentityAuthProvider(AppSettings), /* Use ServiceStack Auth in MVC */
new CredentialsAuthProvider(AppSettings), /* Sign In with Username / Password */
new FacebookAuthProvider(AppSettings),
new GoogleAuthProvider(AppSettings),
new MicrosoftGraphAuthProvider(AppSettings),
}));
appHost.Plugins.Add(new RegistrationFeature()); //Enable /register Service
//override the default registration validation with your own custom implementation
appHost.RegisterAs<CustomRegistrationValidator, IValidator<Register>>();
}

Custom User Flow not logging the user in, returns to AzureADB2C/Account/Error

I have created a User Flow in Azure AD B2C which is being used to register new users. When a new user registers they are being redirected to the AzureADB2C/Account/Error page of my site and they are not logged in. If I then use the sing_in_up policy link the user is then signed in without having to authenticate. I believe I am having an issue with reading the returned credentials after creating the account but I am not too sure.
Here is my link that is directing the user to the signup page:
<a class="btn btn-light mx-1" asp-controller="Account" asp-action="SignUp">
<strong>Sing Up Free</strong>
</a>
This is the controller method:
public IActionResult SignUp()
{
return this.Challenge(
new AuthenticationProperties { RedirectUri = "/" }, "B2C_1_sign_up");
}
This is my OpenIdConnectionOptions:
private Action<OpenIdConnectOptions> GetOpenIdSignUpOptions(string policy)
=> options =>
{
options.MetadataAddress =
"https://login.microsoftonline.com/[Domain].onmicrosoft.com/v2.0/.well-known/openid-configuration?p=" + policy;
options.ClientId = "[***]";
options.ResponseType = OpenIdConnectResponseType.IdToken;
options.SignedOutCallbackPath = "/signout/" + policy;
options.CallbackPath = "/signin-oidc";
options.SignedOutRedirectUri = "/";
};
Where [Domain] = the Azure AD B2C domain and [***] = the Azure AD B2C ClientId.
This is my service configuration:
services.AddAuthentication(AzureADB2CDefaults.AuthenticationScheme)
.AddAzureADB2C(options =>
Configuration.Bind("AzureAdB2C", options)
);
services.AddAuthentication(
options => options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme)
.AddOpenIdConnect("B2C_1_sign_up", GetOpenIdSignUpOptions("B2C_1_sign_up"))
.AddCookie();
The B2C_1_sign_up_in and custom B2C_1_sign_up policies are Identical with the exception of the B2C_1_sign_up_in containing the Unified sign up or sign in page. Any help troubleshooting this is greatly appreciated.
Here are few points to check:
Please ensure that you have tested the custom sign up policy from Azure AD B2C blade from the portal, Check if it working fine or not.
Make sure to configure CORS for the customized page and the location where you have stored.
Validate that you're ready by doing the following:
Go to the www.test-cors.org website, and then paste the URL in the
Remote URL box.
Click Send Request.
If you receive an error, make sure that your CORS settings are correct. You might also need to clear your browser cache or open an in-private browsing session by pressing Ctrl+Shift+P.
Also please make sure to change the base policy with right content definition.
Please refer this link for reference.

How to redirect to login page in ABP?

I download the .NET Core sample from ASP.NET Boilerplate website,
change the DB connection string, update DB,
run Web Api, show the Swagger successfully,
add a Home/Index View, change Home/Index action to return the View, not Swagger,
run again, show home page successfully,
then add a Home.Account Controller and Home.Account View, login page.
Add AbpMvcAuthentication attribute on Home/Index, what I want is when access Home, redirect to login page.
When I go to the Home, it shows an empty page, not Home, nor login page. It seems authenticate failed, but did not redirect to login page.
My question is: how to let AbpMvcAuthentication know which page to redirect when authenticate failed?
There is no login page for the *.Web.Host project, where the redirect to Swagger is.
You should change your Startup Project to *.Web.Mvc instead:
If you just want to login, consider using Swagger authentication helpers from the browser console:
abp.swagger.login();
To answer your question, you can re-enable authentication redirect by reverting commit 92b6270:
// What it was (and what you want)
services.AddAuthentication()
.AddJwtBearer(options =>
// What it is
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = "JwtBearer";
options.DefaultChallengeScheme = "JwtBearer";
}).AddJwtBearer("JwtBearer", options =>
Startup.cs:
app.UseAuthentication();
app.UseJwtTokenMiddleware(); // Add this back
app.UseAbpRequestLocalization();
To be clear, this redirects to a blank page since there is no login page for the *.Web.Host project.
This is the opposite of the expected behaviour in ABP 401 response from API instead of redirect.
Also, you can configure login path for redirect:
You can configure that in Startup.cs:
IdentityRegistrar.Register(services);
AuthConfigurer.Configure(services, _appConfiguration);
// Add this line:
services.ConfigureApplicationCookie(options => options.LoginPath = "/Admin/Login");
Related docs: https://learn.microsoft.com/en-us/aspnet/core/migration/1x-to-2x/identity-2x

Implement Different Login Page for each role in asp.net-core 2

I want to implement different login page for each user based in its role in asp net core . I can set login path but its static for any roles.
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
.AddCookie(options =>
{
options.LoginPath = "Account/Login/";
options.AccessDeniedPath = "Account/Forbidden/";
});
so when i call action that authorize(role="Admin") redirect to admin login page. and when call action that authorize(role="User") redirect to User login page
I add two different Authentication scheme in start up ConfigureServices like this
services.AddAuthentication(options =>
{
options.DefaultScheme = "UserAuth";
})
.AddCookie("UserAuth", options =>
{
options.LoginPath = "/Account/Login/";
options.AccessDeniedPath = "/Account/AccessDenied/";
})
.AddCookie("AdminAuth", options =>
{
options.LoginPath = "/Admin/Account/Login/";
options.AccessDeniedPath = "/Admin/Account/AccessDenied/";
});
When authorize with admin role controller i choose admin scheme
[Authorize(Roles = "Administrator", AuthenticationSchemes = "AdminAuth")]
When authorize with user role controller i choose user scheme
[Authorize(Roles = "User", AuthenticationSchemes = "UserAuth")]
You can review this link How do I setup multiple Authentication schemes in ASP.NET Core 2.0?
Sorry, not possible. The role of a user is not known until the user has authenticated. So you can't tell which login page to serve until they have already logged in, and they can't log in until you have served a login page, so the idea simply doesn't work.
The best you can do is offer a single login page that allows the user to select their role before signing on (e.g. with radio buttons, a dropdown list, or links that take the user to separate login pages). If you like, you can set a cookie to persist the user's selection so that they will only see the appropriate role-specific page the next time they sign on.
If you wish to redirect to a different login page based on some piece of data other than user context (e.g. if you want to redirect to different login pages depending on what URL the user was originally requesting) you can always write a custom authorize attribute and override the HandleUnauthorizedRequest method. Then you can redirect anywhere you want.

Supporting Individual User Accounts AND Organizational Accounts in MVC5 / ASP.Net Identity 2

I've created an ASP.Net MVC5 application, in which I have configured (and have working fine) Individual User Accounts via Google, Facebook, etc.
What I'd like to do is also support authentication against Azure Active Directory (Organizational Accounts). This would be for internal staff to be able to logon to the app as administrators.
All existing information/guides/documentation I've found typically deals with using one or the other. How would I enable them both together?
If there needs to be a separate logon form for each type of user, that would not be an issue.
EDIT:
I was looking at the Application configuration within Azure Active Directory portal, and notice that they define an "OAUTH 2.0 AUTHORIZATION ENDPOINT". Can MVC5 be configured within Startup.Auth.cs to use this?
I managed to implement this by doing the following:
First, adding a reference to the Microsoft.Owin.Security.OpenIdConnect Nuget package.
Second, configuring it in my Startup.Auth.cs:
app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
{
ClientId = "From the Azure Portal (see below)",
Authority = "https://login.windows.net/<domain>.onmicrosoft.com",
Notifications = new OpenIdConnectAuthenticationNotifications
{
RedirectToIdentityProvider = (ctx) =>
{
if (ctx.Request.Path.Value.EndsWith("ExternalLogin"))
{
string appBasePathUrl = ctx.Request.Scheme + "://" + ctx.Request.Host + ctx.Request.PathBase;
ctx.ProtocolMessage.RedirectUri = appBasePathUrl + "/";
ctx.ProtocolMessage.PostLogoutRedirectUri = appBasePathUrl;
}
else
{
ctx.State = NotificationResultState.Skipped;
ctx.HandleResponse();
}
return Task.FromResult(0);
}
},
Description = new AuthenticationDescription
{
AuthenticationType = "OpenIdConnect",
Caption = "SomeNameHere"
}
});
Third, I setup the application in the Azure Portal (classic):
Fourth, I added a separate logon page for admin users:
#using (Html.BeginForm("ExternalLogin", "Home"))
{
#Html.AntiForgeryToken()
<div class="ui basic segment">
<div class="ui list">
<div class="item">
<button type="submit" name="provider" value="OpenIdConnect" class="left floated huge ui button social">
<i class="windows icon"></i>
<span>My Org Name</span>
</button>
</div>
</div>
</div>
}
Fifth, the ExternalLogin action doesn't need to change - we just let OWIN middleware redirect us to the external login page. The flow would then direct the user back to the ExternalLoginCallback action.
Finally, in the ExternalLoginCallback action, I check the incoming claims to determine that the login was via Azure AD, and instead of calling into ASP.NET Identity, I construct my own ClaimsIdentity, which has all my (application specific) claim information which my application recognises as an admin user.
Now, admin users navigate to https://example.com/admin, click the login button, are redirected to the Azure AD login, and windup back at the application as an admin user.
Your best bet would be to leverage Azue AD Access Control Services (ACS) and setup the Identity Providers to include Azure AD, Facebook, et al. See the documentation here: http://azure.microsoft.com/en-us/documentation/articles/active-directory-dotnet-how-to-use-access-control/
ACS can indeed be used, however as you have already implemented Google/Facebook signin I recommend that you directly integrate with Azure AD instead of going through an intermediate STS like ACS/thinktecture.
If your app' signin experience involves the user clicking on "Signin with Google/Signin with Facebook" stickers - you can add "Signin with your company' account." (there's even a recommended branding style: http://msdn.microsoft.com/en-us/library/azure/dn132598.aspx
If you app performs realm discovery and forwards the user to the appropriate IdP (employing a text box saying something like "Enter your email address to sign in") - then you could add matching for your company name email addresses and forward those users to AAD.
In both cases, your application will issue an SSO request to SSO endpoint of AAD: https://login.windows.net/{company domain name/id}/{wsfed/saml/oauth2}. If you're using .Net, WSFed, this should see you through: http://msdn.microsoft.com/en-us/library/azure/dn151789.aspx. Look for the code:
SignInRequestMessage sirm = FederatedAuthentication.WSFederationAuthenticationModule.CreateSignInRequest("", HttpContext.Request.RawUrl, false);
result = Redirect(sirm.RequestUrl.ToString());
There's also an OpenIdConnect sample here: http://msdn.microsoft.com/en-us/library/azure/dn151789.aspx