Auth0 UWP client - don't show previously logged in user - c#

I am using the Auth0 client for UWP as described here: https://auth0.com/docs/quickstart/native/windows-uwp-csharp/01-login.
Everything is working fine, but for my application it is a security risk to show the previously logged in user screen when the Auth0 window appears, and I am wondering if there is a way to change this.
Edit: I've tried
// Create an instance of the Auth0 client
Auth0Client client = new Auth0Client(new Auth0ClientOptions
{
Domain = resources.GetString("Auth0Domain"),
ClientId = resources.GetString("Auth0ClientID"),
LoadProfile = false
});
IdentityModel.OidcClient.LoginResult loginResult = await client.LoginAsync();
// Access the logged in user's data
if (!loginResult.IsError)
{
...
}

You have to customize login page on Auth0 Dashboard navigating to Hosted Pages and enabling Customize Login Page and set rememberLastLogin: false in content.
Related links:
Custom Login Page(login required)

Related

Authentication/Authorization in ASP.NET Core using Enterprise SingleSignon page and Microsoft SignInManager

Presently I am working on an authentication issue in one of my ASP.NET Core(3.0) application.
To give some background, we have to use an Enterprise Single sign on page to authenticate the users. Once the user got authenticated it redirects back to our application along with user name in a HTTP header called "SM_USER". Then using that information we load corresponding Claim information from DB using Microsoft SignInManger. The application is working fine if the user is accessing the root but it couldn't able to access if they are trying to navigate a specific page directly, like http://website/Controller/Index.
I am suspecting that we may have implemented it wrongly so would like to know how should the below scenario to be implemented?
Our users first get authenticated using an enterprise Login Page(Single sign on) then redirected to our application. user information available on HTTP Headers and the corresponding claims information is available in our DB which we need to use for authorization purpose(we wanted to use Microrosoft SignInManger to load them).
I found the issue after researching it throughly so sharing here in case it useful for someone.
we observed whenever a user try to access a page if the user is not authenticated then it is redirecting Login page(Observed that decorating them with [Authorize] attribute is causing this), where We are using this Login page for local development purpose.
so when the user get redirected to login page and if the environment is not development then below code is executed on the Get method, which takes care of signing the user and creating UserPrincipal. Then after that we redirecting to the page the user requested.
if (!_signInManager.IsSignedIn(User))
{
string userName = HttpContext.Request.Headers["SM_USER"].ToString();
if (userName.Length > 0)
{
var user = await _userManager.FindByNameAsync(userName);
if (user != null)
{
var claimsPrincipal = await _signInManager.CreateUserPrincipalAsync(user);
await _signInManager.Context.SignInAsync(IdentityConstants.ApplicationScheme,
claimsPrincipal,
new AuthenticationProperties { IsPersistent = true });
if (string.IsNullOrEmpty(returnUrl)) //returnUrl is a parameter get passed by the system.
{
return RedirectToAction("<Action>", "<Controller>");
}
else
{
return Redirect(returnUrl);
}
}
}
}

Xamarin Forms - not receiving callback when authenticating using Touch ID for Apple Single Sign On

I'm trying to implement Apple Single Sign On for my app using Xamarin Forms. The flow is that when a user tries to login, the OidcClient webview opens up redirecting to Identity Server, where the user can select to login using email address/password or social logins (Eg ; Apple). When logging in through Apple, you can login using Touch ID or apple ID/password. When logging in through apple ID, all is working as expected. User is authenticated in Identity Server, and the app receives the callback and the user can login.
But when using Touch ID to login to Apple, user is still authenticated correctly on the Identity Server side, but the app/Oidc webview doesn't receive a callback. So the webview stays open. I can click the cancel button in the webview and I'll go back to the login screen, where if I click login again, the webview doesn't open up again, I'm just automatically logged into the app.
I have looked at the Xamarin Forms sample to implement Oidc client (Link) and have implemented accordingly, the issue still remains.
I'm using ;
Xamarin Forms 4.3
OidcClient 3.1.2
I'm setting the OidcClientOptions as below :
var browser = DependencyService.Get<IBrowser>();
var options = new OidcClientOptions
{
Authority = AppSettings.Authority,
ClientId = Constants.CLIENT_ID,
Scope = Constants.SCOPE,
RedirectUri = {PACKAGE_NAME}://callback,
Browser = browser,
ClientSecret = Constants.CLIENT_SECRET,
ResponseMode = OidcClientOptions.AuthorizeResponseMode.Redirect,
Flow = OidcClientOptions.AuthenticationFlow.Hybrid
};
var client = new OidcClient(options);
var loginRequest = new LoginRequest();```
LoginResult login = await client.LoginAsync(loginRequest);
Would be great if someone can help with this.

Forgot Password in ADB2C - (AADB2C90118), How to run a specific user flow?

Problem
I am trying to handle the 'Reset password' user-flow in my application. Upon clicking the 'Forgot Password' link, the OnRemoteFailure OpenId event is successfully triggered, successfully redirecting to the specified url 'Home/ResetPassword', but instead or redirecting to the ADB2C reset password screen, it's redirecting back to the sign-in/sign-up page.
Background
The sign-up/sign-in policy works successfully but as per Microsoft docs: https://learn.microsoft.com/en-us/azure/active-directory-b2c/active-directory-b2c-reference-policies:
" A sign-up or sign-in user flow with local accounts includes a Forgot password? link on the first page of the experience. Clicking this link doesn't automatically trigger a password reset user flow.
Instead, the error code AADB2C90118 is returned to your application. Your application needs to handle this error code by running a specific user flow that resets the password. To see an example, take a look at a simple ASP.NET sample that demonstrates the linking of user flows. "
Active Directory B2C Settings
UserFlows
Code
OpenIdEvent
protected virtual Task OnRemoteFailure(RemoteFailureContext context)
{
context.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 (context.Failure is OpenIdConnectProtocolException && context.Failure.Message.Contains("AADB2C90118"))
{
// If the user clicked the reset password link, redirect to the reset password route
context.Response.Redirect("/Home/ResetPassword");
}
else if (context.Failure is OpenIdConnectProtocolException && context.Failure.Message.Contains("access_denied"))
{
context.Response.Redirect("/");
}
else
{
context.Response.Redirect("/Home/Error?message=" + WebUtility.UrlEncode(context.Failure.Message));
}
return Task.FromResult(0);
}
HomeController
public IActionResult ResetPassword()
{
var redirectUrl = Url.Action(nameof(HomeController.Index), "Home");
var properties = new AuthenticationProperties { RedirectUri = redirectUrl };
properties.Items[AzureADB2COptionsExtended.PolicyAuthenticationProperty] = _adb2cOptions.ResetPasswordPolicyId;
return Challenge(properties, AzureADB2CDefaults.AuthenticationScheme);
}
A lot of examples I found use OWIN... There is very limited documentation on ASP.Net Core 2.2 w/ ADB2C.
The Sign-up-sign-in policy now has built-in support for password resets without a second "password-reset" user flow. It is quite confusing with all the documentation and samples out there but this is the latest docs and it works for us!
https://learn.microsoft.com/en-us/azure/active-directory-b2c/force-password-reset?pivots=b2c-user-flow
Normally, the ResetPassword flow you configured in your appsettings.json is called automatically when using the Microsoft.Identity.Web package. In your case B2C_1_SSPR. That means you must define a custom user flow with this Id.
(I guess SSPR = self-service password reset)
The only thing you need in this default case is call the following in your Startup:
services.AddMicrosoftIdentityWebAppAuthentication(Configuration, "ActiveDirectoryB2C");
This works like a charm.
However, you decided to deal with all this stuff by yourself and not to use the Microsft.Identity.Web library for all processing.
In this case you are able to handle Password-reset by yourself.
But let's have a look at the Microsft.Identity.Web. They integrated an AccountController that handles the processing of the B2C custom flows (in this case the ResetPassword action).
The exception handling for AADB2C90118 can be found in the source code of the Identity package:
if (isOidcProtocolException && message.Contains(ErrorCodes.B2CForgottenPassword))
{
// If the user clicked the reset password link, redirect to the reset password route
context.Response.Redirect($"{context.Request.PathBase}/MicrosoftIdentity/Account/ResetPassword/{SchemeName}");
}
Answer that was posted in the question:
For anyone else having the same or similar issue, make sure to keep an eye out on the OpenIdConnectEvents. We have been experimenting with ADB2C/OpenID and had test code. This code was obviously invalid.
protected virtual Task OnRedirectToIdentityProvider(RedirectContext context)
{
string policy = "";
context.Properties.Items.TryGetValue(AzureADB2COptionsExtended.PolicyAuthenticationProperty, out policy);
if (!string.IsNullOrEmpty(policy) && !policy.ToLower().Equals(_adb2cOptions.DefaultPolicy.ToLower()))
{
context.ProtocolMessage.Scope = OpenIdConnectScope.OpenId;
context.ProtocolMessage.ResponseType = OpenIdConnectResponseType.IdToken;
context.ProtocolMessage.IssuerAddress = context.ProtocolMessage.IssuerAddress.ToLower().Replace(_adb2cOptions.DefaultPolicy.ToLower(), policy.ToLower());
}
return Task.FromResult(0);
}
See the latest "Self-Service Password Reset" policy (custom or non-custom) from Microsoft docs.
From the doc:
"The new password reset experience is now part of the sign-up or sign-in policy. When the user selects the Forgot your password? link, they are immediately sent to the Forgot Password experience. Your application no longer needs to handle the AADB2C90118 error code, and you don't need a separate policy for password reset."

Authentication against local AD in the Angular application

I've been developing an Angular app with .NET Core backend (services). The task is to enable an integrated authentication, i.e. make it work with the local user seamlessly, so I login to my (connected to a local AD) machine once and the web application lets me in without the necessity to login a second time. We've been working with Identity Server 4 and intended to implement this scenario using it.
There is a little documentation on the official website concerning the Windows Authentication (e.g. against Active directory): http://docs.identityserver.io/en/latest/topics/windows.html but it doesn't explain much. As per my info, to make this scenario work the browser utilizes either Kerberos or NTLM. Neither of them is mentioned in the IS4 docs. I'm lacking the understanding of how the local credentials are getting picked up and how IS4 'knows' the user belongs to AD? How I can make sure only the users from a specific domain have access to my app?
I found some working stuff here https://github.com/damienbod/AspNetCoreWindowsAuth but questions remain the same. Even though I was able to get to the app with my local account I don't understand the flow.
I expect the user utilizing the app in the local network to log-in to the app without entering the login/password (once he's already logged in to the Windows). Is this something achievable?
Identity Server is intended to serve as an Identity Provider, if you need to talk with your AD you should see the Federation Gateway architecture they propose using the IAuthenticationSchemeProvider. Where Identity Server acts as an endpoint and talks with your AD.
This is the link:
http://docs.identityserver.io/en/latest/topics/federation_gateway.html
You have the control to programmatically reach your AD and pass the correct credentials to get the authentication. That step should be done in your Identity Server. After you get authenticated you should get redirected to your application again.
About your last question, the answer is yes, if you have your website hosted on an intranet and you have the access to your AD, you don't need to capture your credentials as user input, you can programmatically reach the AD as I said.
Bellow is the code I use to connect with my active directory
On the ExternalController class, you get when you use IdentityServer, you have this:(I don't remember at the top of my head how much I changed from the original code, but you should get the idea)
/// <summary>
/// initiate roundtrip to external authentication provider
/// </summary>
[HttpGet]
public async Task<IActionResult> Challenge(string provider, string returnUrl)
{
if (string.IsNullOrEmpty(returnUrl)) returnUrl = "~/";
// validate returnUrl - either it is a valid OIDC URL or back to a local page
if (Url.IsLocalUrl(returnUrl) == false && _interaction.IsValidReturnUrl(returnUrl) == false)
{
// user might have clicked on a malicious link - should be logged
throw new Exception("invalid return URL");
}
if (AccountOptions.WindowsAuthenticationSchemeName == provider)
{
// windows authentication needs special handling
return await ProcessWindowsLoginAsync(returnUrl);
}
else
{
// start challenge and roundtrip the return URL and scheme
var props = new AuthenticationProperties
{
RedirectUri = Url.Action(nameof(Callback)),
Items =
{
{ "returnUrl", returnUrl },
{ "scheme", provider },
}
};
return Challenge(props, provider);
}
}
private async Task<IActionResult> ProcessWindowsLoginAsync(string returnUrl)
{
// see if windows auth has already been requested and succeeded
var result = await HttpContext.AuthenticateAsync(AccountOptions.WindowsAuthenticationSchemeName);
if (result?.Principal is WindowsPrincipal wp)
{
// we will issue the external cookie and then redirect the
// user back to the external callback, in essence, testing windows
// auth the same as any other external authentication mechanism
var props = new AuthenticationProperties()
{
RedirectUri = Url.Action("Callback"),
Items =
{
{ "returnUrl", returnUrl },
{ "scheme", AccountOptions.WindowsAuthenticationSchemeName },
}
};
var id = new ClaimsIdentity(AccountOptions.WindowsAuthenticationSchemeName);
id.AddClaim(new Claim(JwtClaimTypes.Subject, wp.Identity.Name));
id.AddClaim(new Claim(JwtClaimTypes.Name, wp.Identity.Name));
// add the groups as claims -- be careful if the number of groups is too large
if (AccountOptions.IncludeWindowsGroups)
{
var wi = wp.Identity as WindowsIdentity;
var groups = wi.Groups.Translate(typeof(NTAccount));
var roles = groups.Select(x => new Claim(JwtClaimTypes.Role, x.Value));
id.AddClaims(roles);
}
await HttpContext.SignInAsync(
IdentityServer4.IdentityServerConstants.ExternalCookieAuthenticationScheme,
new ClaimsPrincipal(id),
props);
return Redirect(props.RedirectUri);
}
else
{
// trigger windows auth
// since windows auth don't support the redirect uri,
// this URL is re-triggered when we call challenge
return Challenge(AccountOptions.WindowsAuthenticationSchemeName);
}
}
If you want to use Azure AD, I would recommend you to read this article:
https://damienbod.com/2019/05/17/updating-microsoft-account-logins-in-asp-net-core-with-openid-connect-and-azure-active-directory/
Not sure if it's what you want, but I would use the Active Directory Federation Services to configure an OAuth2 endpoint and obtain the user token in the .Net Core Web App.
Isn't NTLM authentication support limited on non Microsoft browsers?
OAuth2 have the advantage of using only standard technologies.
One way to do it is to have 2 instances of the app deployed.
The first one is configured to use Windows Authentication and the other one uses IS4.
ex:
yoursite.internal.com
yoursite.com
Your local DNS should redirect traffic internally from yoursite.com to yoursite.internal.com
yoursite.internal.com will be the one configured to use AD authentication. You should have a flag in your appsettings.json to indicate if this instance is a AD auth or IS4 auth.
The downside of this solution is that you have to deploy 2 instances

IdentityServer3 How to redirect user from MVC Client application with signin=

I'm new to OAuth 2.0 and IdentityServer3 but have a pretty good grasp on the inner workings and have an up and running implementation and client(s) using various Flows (implicit and etc...)
This maybe a noobie question but I've managed to configure a working IdentityServer3 implementation and working MVC Client using (Implicit Flow).
To force the user to the IdentityServer3 login page (which I've customized in a template), the client has to click the Login link within the Client and ActionResult within the Client has an [Authorize] attribute, which redirects the user to the IdentityServer login page (because it requires Authorization).
Is this the correct implementation? Also, I'd like to redirect the user to a separate Register page, but without adding an [Authorize] attribute to the Register action (which will redirect to the login page FIRST and it then the user has to click the "Register Link" which I customized through the use of templates) in the Client I can't seem to accomplish this.
How can I separate the Login logic from the Registration logic?
Any help would be awesome!
Thanks,
Don't set the [Authorize]-Attribute over your Register Page.
Because as you said correctly it would redirect to the login first.
It needs to be publicly available. To integrate a "Register"-Link in the Login-View you can use the following property in the IdentityServerOptions:
Startup.cs [Excerpt from IdentityServer-Configuration]
IdentityServerOptions options = new IdentityServerOptions
{
AuthenticationOptions = new AuthenticationOptions {
LoginPageLinks = new List<LoginPageLink> {
new LoginPageLink { Href = "https://example.com/register", Text = "Register" },
new LoginPageLink { Href = "https://example.com/forgot-password", Text = "Forgot your password?"}
}
}
};
This will add the Links below the Login Form on the login-page of the identityserver.
Again mind that these links need to be public (without authorization)

Categories