OWIN middleware: signout without redirecting to IdP when IdTokenHint is not available - owin

Is there anyway to signout using OWIN middleware without redirecting to IdP? Everytime i call Authentication.SignOut(), my MVC application is redirecting to IdP. It's fine if the identity token is available. However I don't want user to get stuck on IdentityServer's logout screen when identity token is gone without knowing how to come back to login screen.

It turns out i just handle LogoutRequest event on RedirectToIdentityProvider and use following lines of code to redirect user to front-channel logout page:
if (identityToken != null)
{
n.ProtocolMessage.IdTokenHint = identityToken;
}
else
{
n.HandleResponse();
n.Response.Redirect("/Account/FrontChannelLogout");
}

Related

React MSAL Library msal-react : Issue in logging out in B2C application

I am using msal-react in my single page B2C application to sign in. I used the loginRedirect() function to login.
const { instance } = useMsal();
let {idToken} = await instance.loginRedirect();
This is allowing me to login successfully.
After login when I check if the user is authenticated using the following function it is returning true.
import {useIsAuthenticated,} from "#azure/msal-react";
const isAuthenticated = useIsAuthenticated();
That means that the user is authenticated.
But when I use the logoutRedirect function to logout the user. it is properly getting redirected to the logout-redirect-uri. But, it is still persisting the session somehow. Again if I try to login it is not asking for the credentials. Instead, it is taking me to the screen when it will ask me to sent the token to my registered mobile number.
await instance.logoutRedirect();
Can anybody suggest a way to remove the entire session and ask the user to enter the credentials again after logging out?

Cancelling new user signup in Azure AD B2C redirects to sites home page, produces "AuthorizationFailed" error

I have a Blazor Hosted WASM application, and am using Azure AD-B2C to secure it. If a user who is not logged in tries to access any site on the page, they are directed to our b2c login page, as they should be, and if they supply a good username and password they are allowed to view the site. So far so good. However, if the user clicks on "Sign up now", and then cancels the signup process instead of providing a new username, password, and e-mail address, then they are redirected to the site's landing page (as if they had provided a good username and password), which fails to redirect them back to the b2c login page and produces a console message reading "info: Microsoft.AspNetCore.Authorization.DefaultAuthorizationService[2]
Authorization failed. These requirements were not met:
DenyAnonymousAuthorizationRequirement: Requires an authenticated user"
The documentation suggests that I access the app's manifest and set the allowPublicClient attribute to null or true to address this problem. I have done this, and the problem persists. Why isn't the user being redirected back to the B2C login page in this case, when they normally would be if they try to access any page on the site (including this landing page) in other cases?
When the user cancels and get redirected back to the landing page, it returns an specific error code in the url (eg: AADB2C90118) in the return redirect url (In some cases it only flashes quickly because Angular removes the query string after the redirect).
You need to listen to this and handle it. You can handle it manually by parsing the return url but if you use msal.js on client side you can listen to this and start the reset password flow.
this.broadcastService.subscribe("msal:loginFailure", (error) => {
console.warn("msal:loginFailure", error);
// Check for forgot password error
// Learn more about AAD error codes at https://learn.microsoft.com/en-us/azure/active-directory/develop/reference-aadsts-error-codes
if (error.errorMessage.indexOf("AADB2C90118") > -1) {
alreadyRedirecting = true;
this.msalAuthService.loginRedirect(
b2cPolicies.authorities.resetPassword
);
}
});
The above example is for when the user clicks on forgot password link and get redirected back, so you will need to find the error code that applies to you.

Set Redirect UrlAfter Login

I have Blazor Server hooked up with Azure B2C Cookie Auth.
services.AddAuthentication(AzureADB2CDefaults.CookieScheme)
.AddAzureADB2C(options => Configuration.Bind("AzureAdB2C", options));
services.Configure<CookieAuthenticationOptions>(
AzureADB2CDefaults.CookieScheme, options =>
{
options.Cookie.Name = "MyCookieName";
});
I'm mapping Controllers so I have Controller Endpoints to hit:
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
endpoints.MapBlazorHub();
endpoints.MapFallbackToPage("/_Host");
});
In my Blazor Server _Host I simply am using the built in Authorize attirbute:
#attribute [Microsoft.AspNetCore.Authorization.Authorize]
On load, if the user isn't Authorized, it will redirect to B2C Sign in without issue. I can then sign in and it directs me back to the App.
However, what I can't figure out is after login how to redirect to a specific controller/action endpoint prior something like: /api/auth/mynewuser This action would then do some verification and redirect back to "/" allowing the user to continue using the Blazor app.
Given my out of the box setup pretty much... how to achieve this?
edit
Code:
https://github.com/aherrick/BlazorServerB2C
Goal is to hit this endpoint after every login/sign up:
https://github.com/aherrick/BlazorServerB2C/blob/master/BlazorServerB2C/Controllers/AuthorizeController.cs
When you sign in using Azure AD B2C, the B2C service sends a token to the "redirect_uri" .You can mention the Redirect URL used in the authentication route to a specific controller/action endpoint dynamically. This helps the app to redirect to the controller when authentication is successful.
Also, You can easily handle user is logged in or not by implementing AuthorizeView component or [Authorize] attribute.
I looked into your code Authorizationcontroller and the newuser action which is under construction.
If you can trigger on the razor page, you can use the following:
#page "/YourPageName"
#inject NavigationManager NavigationManager
<h1>xxx</h1>
.
.
.
#code {
void MethodToTriggerUrl()
{
NavigationManager.NavigateTo("PageToRedirect");
}
}
Also, please refer MS Document.

Azure Custom Policies KMSI - Password Reset and Cancel Sign up redirect to authentication response url

I use this example for a B2C web app/web api authentication/authorisation. I also use Local Account custom policies and KMSI.
The issue I have is that when a user clicks forgot pwd or cancel sign up the web app redirects to the authentication redirect url (in my case xxx/azurewebsites.net/api/UserAccess) without authenticating :
The B2C example (although it was setup for User Flows and I'm using Custom Policies) already handles error exceptions when a user clicks "forgot password" - I use this same code. However my web app picks up error AADB2C90118 (click forgot password) but OnAuthenticationFailed redirects it to the authentication response url without performing authentication.
Below is Fiddler showing my webapp behaviour: click on forgot password->picks up the error->redirects to authentication response URL without authentication:
And here MSFT's example: click on forgot password->picks up error->redirects back to authentication:
Below my Start.Auth OnAuthenticationFailed, I added error AADB2C90091 to cater when the user clicks to Sign up and cancels.:
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");
notification.Response.Redirect("/");
}
else if (notification.ProtocolMessage.ErrorDescription != null && notification.ProtocolMessage.ErrorDescription.Contains("AADB2C90091"))
{
// If the user clicked the Cancel for reset password or sign up link, redirect to login page
notification.Response.Redirect("/Account/SignUpSignIn");
}
else if (notification.Exception.Message == "access_denied")
{
notification.Response.Redirect("/");
}
else
{
notification.Response.Redirect("/Home/Error?message=" + notification.Exception.Message);
}
return Task.FromResult(0);
}
In using Custom Policies and KSMI tutorial standard files with the changes explained in the tutorial; I'm not sure if these changes would have an impact on this issue I'm finding. I attach link to xml files https://drive.google.com/drive/folders/1E9SRLaicM74YmxDxNL1_rfx4NPvX-ADJ?usp=sharing

Dynamic Redirect after Successful Login in Azure B2C

I am developing a Single Page Application using .NET Core V2 and am using Azure B2C Authentication.
My Startup.cs has the following:
services.AddAuthentication(sharedOptions =>
{
sharedOptions.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddAzureAdB2CBearer(options => Configuration.Bind("AzureAdB2C", options));
public static AuthenticationBuilder AddAzureAdB2CBearer(this AuthenticationBuilder builder)
=> builder.AddAzureAdB2CBearer(_ => { });
public static AuthenticationBuilder AddAzureAdB2CBearer(this AuthenticationBuilder builder, Action<AzureAdB2COptions> configureOptions)
{
builder.Services.Configure(configureOptions);
builder.Services.AddSingleton<IConfigureOptions<JwtBearerOptions>, ConfigureAzureOptions>();
builder.Services.AddScoped<IClaimsTransformation, ClaimsTransformer>();
builder.AddJwtBearer();
return builder;
}
I have a Signin Endpoint which redirects to the B2C Login Page
ie.
https://login.microsoftonline.com/{mydomain}/oauth2/v2.0/authorize?p={mysigninpolicy}&client_id={3}&nonce=defaultNonce&redirect_uri={myredirecturl}&scope=openid&response_type=id_token&response_mode=form_post&prompt=login
I have created a callback endpoint of myredirecturl which checks for any error message from B2C Sign in and grabs the Bearer token.
I have set up an Azure SignIn Policy with the myredirecturl specified.
All of my controllers are then protected with [Authorize] attributes to prevent access unless signed in.
This all works fine. But I would like the following to happen:
1) If I am logged off and I enter https://mydomain/somecontroller/somemethod
2) I would like to be taken to the SignIn page (this happens now)
3) After succesful sign in I want to be redirected automatically to
https://mydomain/somecontroller/somemethod
This does not happen now, I can only be taken to the home page because there is no way I can find to pass with ReplyUrl as a query string parameter to the SignIn Endpoint and then retrieve it from the B2C Callback.
I want my redirecturl to be whatever was submitted from the browser.
If I was using standard Identity Authentication I could do:
mydomain/account/login?redirecturl=mydomain/controller/method
Found the answer:
If you include a &state={some value} parameter in the call to B2C login ie.
https://login.microsoftonline.com/{mydomain}/oauth2/v2.0/authorize?p={mysigninpolicy}&client_id={3}&nonce=defaultNonce&redirect_uri={myredirecturl}&scope=openid&response_type=id_token&response_mode=form_post&prompt=login&state=myvalue
the endpoint that B2C calls in the redirect_uri also includes this value, so you can use this to redirect the user after successful login.

Resources