Multiple login pages for different claims - asp.net-core

Here is my situation.
To do some actions on the web site user should be authenticated. Different actions require different claims. For example, to make an order user is authenticated by phone number only, to view the purchase history user should be authenticated by phone number and password, and to change the phone number user should be authenticated using two-factor authentication.
I create a login page for each of the authentication methods and when user is authenticated I give her a set of claims depending on the authentication method.
I add [Authorize(Policy="CanCreateOrder")] to the CreateOrder action method. The policy has the logic what claims required to authorize user. In case user is not authorized I want to redirect the user to the appropriate login page.
The question is how I could specify the url where user should be redirected for authentication?
Looking at CookieAuthenticationMiddleware I could not see how to to specify login page depending on what claims required. Documentation suggests to set LoginPath property at the configuration time, but in my case login url depends on what claims I need to authorize the user.

You can use different authentication scheme for each different claim:
app.UseCookieAuthentication(new CookieAuthenticationOptions()
{
AuthenticationScheme = "Phone",
LoginPath = "<phone - path>"
....
}
app.UseCookieAuthentication(new CookieAuthenticationOptions()
{
AuthenticationScheme = "Password",
LoginPath = "<password - path>"
....
}
app.UseCookieAuthentication(new CookieAuthenticationOptions()
{
AuthenticationScheme = "TwoFactor",
LoginPath = "<twofactor - path>",
....
}
And then usage:
[Authorize(Policy="CanCreateOrder", ActiveAuthenticationSchemes = "Phone")]
Also you can use multiple scheme:
[Authorize(Policy="CanCreateOrder", ActiveAuthenticationSchemes = "Phone,TwoFactor")]
See https://docs.asp.net/en/latest/security/authorization/limitingidentitybyscheme.html

From aspnet core 2, use can use the attribute for the controller, action o razor page you need to configure:
[Authorize(Policy="CanCreateOrder")]
Configure your policy with the authenticationscheme
public void ConfigureServices(IServiceCollection services)
{
...
services.AddAuthorization(options =>
{
options.AddPolicy("CanCreateOrder",
authBuilder =>
{
authBuilder.AddAuthenticationSchemes("Management_Scheme");
authBuilder.RequireClaim("Manager");
});
});
...
}
and multiple cookie authentication configuration depending on the authentication scheme:
public void ConfigureServices(IServiceCollection services)
{
...
services
.AddAuthentication()
.AddCookie("Public_Scheme" , options =>
{
options.LoginPath = "/login";
options.LogoutPath = "/logout";
})
.AddCookie("Management_Scheme",options =>
{
options.LoginPath = "/management/login";
options.LogoutPath = "/management/logout";
});
...
}
This extensions must be used inside ConfigureServices method and not Configure.
Take into account that configuring the authentiucation scheme inside the policy is not mandatory, it can be can addes to the authorization attribute wherever needed:
[Authorize("CanCreateOrders",AuthenticationSchemes = "ManagementScheme")]
You can see more about migrating in to 2.0 in this article.

This Is Perfect, The method I use for two different login authorizations
services.AddAuthentication(options =>
{
options.RequireAuthenticatedSignIn = false;
}).
AddCookie("CustomSchema1",
options =>
{
options.Cookie.Name = "CustomCookieName1";
options.LoginPath = "/login";
options.ExpireTimeSpan = TimeSpan.FromDays(10);
options.SlidingExpiration = true;
}).AddCookie("CustomSchema2", options =>
{
options.Cookie.Name = "CustomCookieName2";
options.LoginPath = "/writer/login";
options.ExpireTimeSpan = TimeSpan.FromDays(10);
options.SlidingExpiration = true;
});

Related

Blazor login path for multiple authentication schemes (AAD and AB2C)

I want to use Azure AD and Azure B2C in one application. I registered both authentication schemes which works fine.
Now I want to allow the user to decide which scheme should be used by clicking a "login with AD" or "login with B2C" button. Clicking on one of the buttons should redirect the user to the correct login.
I'm able to do this for AD by using the link MicrosoftIdentity/Account/SignIn. To do this, it's necessary to use services.AddControllersWithViews().AddMicrosoftIdentityUI()
So, how do I get a link like above for B2C?
Here is my code:
public static void AddAzureADAuthenticationApp(this IServiceCollection services, IConfigurationSection configuration)
{
services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApp(options =>
{
configuration.Bind(options);
options.Events.OnTokenValidated = async context =>
{
await AuthorizationHelper.ValidateAADAppToken(context);
};
})
.EnableTokenAcquisitionToCallDownstreamApi().AddInMemoryTokenCaches();
services.AddControllersWithViews(options =>
{
var policy = new AuthorizationPolicyBuilder(OpenIdConnectDefaults.AuthenticationScheme)
.RequireAuthenticatedUser()
.AddRequirements(new AzureADAuthorizationRequirement()).Build();
options.Filters.Add(new AuthorizeFilter(policy));
})
.AddMicrosoftIdentityUI();
services.AddAuthorization(config =>
{
var policy = new AuthorizationPolicyBuilder(OpenIdConnectDefaults.AuthenticationScheme)
.RequireAuthenticatedUser()
.AddRequirements(new AzureADAuthorizationRequirement()).Build();
config.AddPolicy(Constants.PolicyInternalUsers, policy);
});
}
public static void AddAzureB2CAuthenticationApp(this IServiceCollection services, IConfigurationSection configuration, bool RequireAccountNum = false)
{
services.AddAuthentication()
.AddMicrosoftIdentityWebApp(options =>
{
configuration.Bind(options);
options.SignInScheme = Constants.B2CAuthenticationScheme;
options.ResponseType = "code id_token";
options.Scope.Clear();
options.Scope.Add("https://graph.microsoft.com/openid");
options.Events.OnTokenValidated = async context =>
{
await AuthorizationHelper.ValidateB2CAppToken(context, RequireAccountNum);
};
}, openIdConnectScheme: Constants.B2CAuthenticationScheme, cookieScheme: Constants.B2CCookieScheme)
.EnableTokenAcquisitionToCallDownstreamApi().AddInMemoryTokenCaches();
services.AddControllersWithViews(options =>
{
var policy = new AuthorizationPolicyBuilder(FischerLib.Extensions.Constants.B2CAuthenticationScheme)
.RequireAuthenticatedUser()
.AddRequirements(new AzureB2CAuthorizationRequirement(RequireAccountNum)).Build();
options.Filters.Add(new AuthorizeFilter(policy));
})
.AddMicrosoftIdentityUI();
services.AddAuthorization(config =>
{
var policy = new AuthorizationPolicyBuilder(FischerLib.Extensions.Constants.B2CAuthenticationScheme)
.RequireAuthenticatedUser()
.AddRequirements(new AzureB2CAuthorizationRequirement(RequireAccountNum)).Build();
config.AddPolicy(Constants.PolicyExternalUsers, policy);
});
}
At the moment I'm using two controller which have authorize attributes restricted to the scheme. Accessing these controller redirects the user to the login.
But this is not the way which I want to use. After the code above is part of a library and I would like to avoid having to ad the controller in every project.
I know that there is a property LoginPath if I use a different scheme like cookies but I can't set this property in AddMicrosoftIdentityWebApp(...)
Thank you very much!
Markus
Please check this blog on Building a Web Application that Supports both Azure AD and Azure AD B2C - MikaBerglund.com
which works on how to enable switching between Azure AD and Azure AD
B2C just by changing the configuration i.e;app settings.json file
where authority , clientId changes.
The controller actions need to route to selected auth schemes when required.
The way you have added controller seems to be the way.
You can raise a support request for the same.
Reference:
github ref

.net 5 Authentication Cookie not set

I have a Umbraco 9 .Net 5 AspNet Core project.
I'm trying to set an auth cookie. I've followed microsofts guide and got it working in a seperate project but when trying to implement it in my Umbraco project it fails. I'm not sure why but I guess the Umbraco 9 Configuration has a part in it.
I've got as far as getting User.Identity.IsAuthenticated = true in the same controller as I sign in but as soon as I redirect to another controller the Authentication status is false.
I also try to set the LoginPath option when configure the cookie but it still redirect to the default path (/Account/Login) so something here is no working either
My StartUp.cs looks like following
public void ConfigureServices(IServiceCollection services)
{
services.AddUmbraco(mEnvironment, mConfig)
.AddBackOffice()
.AddWebsite()
.AddComposers()
.Build();
services.AddDistributedMemoryCache();
//services.AddSession(options =>
//{
// options.IdleTimeout = TimeSpan.FromSeconds(10);
// options.Cookie.HttpOnly = true;
// options.Cookie.IsEssential = true;
//});
services.AddControllersWithViews();
services.AddRazorPages();
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme).AddCookie(options =>
{
options.LoginPath = "/portal/"; //not working, still redirects to default
});
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseAuthentication();
app.UseAuthorization();
//umbraco setup
app.UseUmbraco()
.WithMiddleware(u =>
{
u.UseBackOffice();
u.UseWebsite();
})
.WithEndpoints(u =>
{
u.UseInstallerEndpoints();
u.UseBackOfficeEndpoints();
u.UseWebsiteEndpoints();
});
//app.UseSession();
}
My Login controller action looks like follows:
public async Task<ActionResult> Login()
{
var claimsIdentity = new ClaimsIdentity(new List<Claim>
{
new Claim(UserClaimProperties.UserRole, MemberRole, ClaimValueTypes.String)
}, CookieAuthenticationDefaults.AuthenticationScheme);
var authProps = new AuthenticationProperties
{
ExpiresUtc = DateTime.UtcNow.AddMinutes(20),
IsPersistent = true,
AllowRefresh = true,
RedirectUri = "/"
};
await HttpContext.SignInAsync(
//CookieAuthenticationDefaults.AuthenticationScheme, //from MS-example but isAuth will be false using this
new ClaimsPrincipal(claimsIdentity),
authProps);
var isAuthenticated = User.Identity.IsAuthenticated;
return Redirect("/myview/");
}
If I set the Auth Scheme to "Cookies" in SignInAsync like it is in the microsoft example isAuthenticated will be false but without this I'll at least get it true here.
When redirected to the next action the User.Identity.IsAuthenticated is false.
Any suggestions why that is or why my LoginPath configuration wont work?
Edit: I don't want to create Umbraco members for each user that logs in. I just want to sign in a user to the context and be able to validate that the user is signed in by myself in my controllers.
Edit 2: I've try to catch the sign in event and got a breakpoint in that even. In my demo app(without umbraco) I'll get to the breakpoint in the one with Umbraco this breakpoint is never hit so. Is this because Umbraco probably override this or hijack the event?
Not sure why but after testing different Authentication schemes I got an error that the schemes I tested was not registered and I got a list of already registered schemes.
I thought that by doing this
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme).AddCookie(options =>
{
options.LoginPath = "/portal/"; //not working, still redirects to default
});
I've registered the "Cookies" scheme.
One of the schemes listed as registered was "Identity.Application" and by using that one I could get the User identity from the context in my redirect controller.

The mandatory 'code_challenge' parameter is missing with OpenIddict

I have an identity server running asp.net core 5, with openiddict 3.1.1
I'm having trouble where I'm getting the error from openiddict:
error:invalid_request
error_description:The mandatory 'code_challenge' parameter is missing.
error_uri:https://documentation.openiddict.com/errors/ID2029
in some scenarios, but not all. My identity server has a startup.cs of:
services.AddDbContext<IdentityContext>(options =>
{
options.UseSqlServer(dbConnectionString, x => x.UseNetTopologySuite());
// Register the entity sets needed by OpenIddict.
// Note: use the generic overload if you need
// to replace the default OpenIddict entities.
options.UseOpenIddict<Guid>();
});
services.AddTransient<IPasswordHasher<ApplicationUser>, CustomPasswordHasher>();
services.AddTransient<IOptions<IdentityOptions>, CustomOptions>();
services.AddScoped<SignInManager<ApplicationUser>, CustomSignInManager>();
services.AddIdentity<ApplicationUser, ApplicationRole>()
.AddEntityFrameworkStores<IdentityContext>()
//.AddDefaultUI()
.AddDefaultTokenProviders();
services.AddOpenIddict()
// Register the OpenIddict core components.
.AddCore(options =>
{
// Configure OpenIddict to use the Entity Framework Core stores and models.
// Note: call ReplaceDefaultEntities() to replace the default entities.
options.UseEntityFrameworkCore()
.UseDbContext<IdentityContext>()
.ReplaceDefaultEntities<Guid>();
})
// Register the OpenIddict server components.
.AddServer(options =>
{
// Enable the authorization, device, logout, token, userinfo and verification endpoints.
options.SetAuthorizationEndpointUris("/connect/authorize")
.SetLogoutEndpointUris("/connect/signout")
.SetTokenEndpointUris("/connect/token");
// Enable the client credentials flow.
options
.AllowAuthorizationCodeFlow().RequireProofKeyForCodeExchange()
.AllowRefreshTokenFlow();
// Encryption and signing of tokens
options
.AddEphemeralEncryptionKey()
.AddEphemeralSigningKey()
.DisableAccessTokenEncryption(); //TODO: not a huge deal as long as we're not hiding anything bad here.
// Expose all the supported claims in the discovery document.
options.RegisterClaims(Configuration.GetSection("OpenIddict:Claims").Get<string[]>());
// Expose all the supported scopes in the discovery document.
options.RegisterScopes(Configuration.GetSection("OpenIddict:Scopes").Get<string[]>());
// Register the ASP.NET Core host and configure the ASP.NET Core-specific options.
options.UseAspNetCore()
.EnableStatusCodePagesIntegration()
.EnableAuthorizationEndpointPassthrough()
.EnableAuthorizationRequestCaching()
.EnableLogoutEndpointPassthrough()
.EnableVerificationEndpointPassthrough()
.EnableTokenEndpointPassthrough();
})
// Register the OpenIddict validation components.
.AddValidation(options =>
{
// Import the configuration from the local OpenIddict server instance.
options.UseLocalServer();
// Register the ASP.NET Core host.
options.UseAspNetCore();
// Enable authorization entry validation, which is required to be able
// to reject access tokens retrieved from a revoked authorization code.
options.EnableAuthorizationEntryValidation();
});
with an OpenIDWorker of:
public async Task StartAsync(CancellationToken cancellationToken)
{
using IServiceScope scope = _serviceProvider.CreateScope();
IdentityContext context = scope.ServiceProvider.GetRequiredService<IdentityContext>();
await RegisterApplicationsAsync(scope.ServiceProvider, _configuration);
static async Task RegisterApplicationsAsync(IServiceProvider provider, IConfiguration configuration)
{
IOpenIddictApplicationManager manager = provider.GetRequiredService<IOpenIddictApplicationManager>();
string clientID = configuration.GetSection("OpenIddict:ClientId").Get<string>();
string clientSecretString = "blahblahblah";
if (await manager.FindByClientIdAsync(clientID) is null)
{
await manager.CreateAsync(new OpenIddictApplicationDescriptor
{
ClientId = clientID,
ClientSecret = clientSecretString,
ConsentType = ConsentTypes.Explicit,
DisplayName = configuration.GetSection("OpenIddict:DisplayName").Get<string>(),
PostLogoutRedirectUris =
{
new Uri("https://localhost:44330/signout-callback-oidc")
},
RedirectUris =
{
new Uri("https://localhost:44330/signin-oidc")
},
Permissions =
{
Permissions.Endpoints.Authorization,
Permissions.Endpoints.Logout,
Permissions.Endpoints.Token,
Permissions.GrantTypes.AuthorizationCode,
Permissions.GrantTypes.RefreshToken,
Permissions.ResponseTypes.Code,
Permissions.Scopes.Email,
Permissions.Scopes.Profile,
Permissions.Scopes.Roles,
},
Requirements =
{
Requirements.Features.ProofKeyForCodeExchange
}
});
}
}
}
when i try to connect to the server with a C# razor app with the following startup.cs, it works fine and w/out any issues:
string clientSecretString = "blahblahblah";
services.AddAuthentication(options =>
{
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
}).AddCookie(CookieAuthenticationDefaults.AuthenticationScheme, options =>
{
options.LoginPath = "/login";
options.ExpireTimeSpan = TimeSpan.FromMinutes(50);
options.SlidingExpiration = false;
})
.AddOpenIdConnect(OpenIdConnectDefaults.AuthenticationScheme, options =>
{
// Note: these settings must match the application details
// inserted in the database at the server level.
options.ClientId = Configuration.GetSection("ClientId").Get<string>();
options.ClientSecret = clientSecretString;
options.RequireHttpsMetadata = false;
options.GetClaimsFromUserInfoEndpoint = true;
options.SaveTokens = true;
// Use the authorization code flow.
options.ResponseType = OpenIdConnectResponseType.Code;
options.AuthenticationMethod = OpenIdConnectRedirectBehavior.RedirectGet;
// Note: setting the Authority allows the OIDC client middleware to automatically
// retrieve the identity provider's configuration and spare you from setting
// the different endpoints URIs or the token validation parameters explicitly.
options.Authority = "https://localhost:44330/";
options.Scope.Add("email");
options.Scope.Add("roles");
options.Scope.Add("offline_access");
options.SecurityTokenValidator = new JwtSecurityTokenHandler
{
// Disable the built-in JWT claims mapping feature.
InboundClaimTypeMap = new Dictionary<string, string>()
};
options.TokenValidationParameters.NameClaimType = "name";
options.TokenValidationParameters.RoleClaimType = "role";
options.AccessDeniedPath = "/";
});
But when i try to connect to it with https://oidcdebugger.com/, or if I try to connect to it using Azure B2C user flows, I get the error message above about missing a code_challenge (see image )
What am i missing here? My plan was to use B2C, but i'm not seeing what is blocking me.
See https://github.com/openiddict/openiddict-core/issues/1361 for reference. Issue ended up being a problem with B2C itself, and will require a fix for them

ASP.NET Core 3.1 Use both OpenIDConnect and Custom Cookie Authentication

I have an existing application that makes use of Cookie Authentication, and would like to add the ability to authenticate users using Active Directory. The current application uses Cookie based authentication and custom authorisation - roles in a database.
I am adding bits from example located here:
Add sign-in with Microsoft to an ASP.NET Core web app
When I run the application I get an error:
System.InvalidOperationException: Scheme already exists: Cookies
What is the correct way to configure OpenIdConnect and Cookie Authentication.
// STEP 1 Basic Cookie Auth
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
.AddCookie(options =>
{
options.LoginPath = "/Auth";
options.AccessDeniedPath = "/Home/AccessDenied";
options.Cookie.IsEssential = true;
options.SlidingExpiration = true;
options.ExpireTimeSpan = TimeSpan.FromSeconds(day/2.0);
options.Cookie.HttpOnly = true; // not accessible via JavaScript
options.Cookie.Name = "login_token";
options.TicketDataFormat = new CustomJwtDataFormat(
SecurityAlgorithms.HmacSha256,
tokenValidationParameters);
});
// STEP 2 OpenID Connect Auth
services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApp(Configuration.GetSection("AzureAd"), "OpenIdConnect", "Cookies", true);
I am not able to find any examples using both Cookie Authentication and OpenID Connect. Is this possible? Allowing users to login selectively using Active Directory authentication, or local authentication (details stored in local database).
After changing the "Cookie" name, get's rid of the error message,
but breaks the local authorisation, e.g.
When a valid Username and Password is given, I typically
authorise the login.
HttpContext.Response.Cookies.Append("login_token", token, GetCookieOptions());
Currently with OpenIDConnect configured User.Identity.IsAuthenticated
remains false.
According to the error messages, it tell you that you have multiple Scheme which named cookies.
According to the AddMicrosoftIdentityWebApp Method document, you could find the third parameter name is the cookieScheme.
The cookie-based scheme name to be used. By default it uses "Cookies".
But you have already set this name at above, so you should use other one. For example: "ADCookies".
Like below:
services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApp(Configuration.GetSection("AzureAd"), "OpenIdConnect", "ADCookies", true);
The mixed approach is a minefield but the below is allowing use to Authenticate Users via IdentityServer4 using OIDC while authenticating the Application into AzureAD with Identity.Web to get tokens for Api calls.
services.AddAuthentication(options =>
{
options.DefaultScheme = "IS4Cookies";
options.DefaultChallengeScheme = "oidc";
})
.AddCookie("IS4Cookies")
.AddOpenIdConnect("oidc", "OpenID Connect", options =>
{
options.SignInScheme = "IS4Cookies";
// Get IdentityServer configuration from appsettings.json.
var config = Configuration.GetSection("IdentityServerOptions").Get<IdentityServerOptions>();
options.Authority = config.Authority;
options.RequireHttpsMetadata = false;
options.ClientId = config.ClientId;
options.ClientSecret = config.ClientSecret;
options.ResponseType = "code";
options.SaveTokens = true;
options.GetClaimsFromUserInfoEndpoint = true;
options.ClaimActions.MapJsonKey("role", "role");
options.ClaimActions.MapJsonKey("role", System.Security.Claims.ClaimTypes.Role);
options.ClaimActions.MapJsonKey("email", "email");
options.ClaimActions.MapJsonKey("preferred_username", "preferred_username");
options.Events = new OpenIdConnectEvents
{
OnRemoteFailure = context =>
{
context.Response.Redirect("/");
context.HandleResponse();
return Task.FromResult(0);
}
};
})
.AddMicrosoftIdentityWebApp(Configuration, "AzureOptions")
.EnableTokenAcquisitionToCallDownstreamApi(new string[]{"sms.all" })
.AddInMemoryTokenCaches();
This is what I use and it works, you just need to specify the configureCookieAuthenticationOptions and set the name inside there and you should be good to go, also I had to use lax for SameSite or it would not work for me.
services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApp(identityOptions =>
/* {identityOptions.ClientId ="";}, // if you want to specify the options manually instead of Configuration.GetSection() call*/
Configuration.GetSection("AzureAd"),
configureCookieAuthenticationOptions: authCookie => { // Setup SSO cookie
authCookie.Cookie.Name ="Your.Cookie.Name.Here";// change name to hide .net identifiers in name
authCookie.Cookie.HttpOnly = true;// make so client cannot alter cookie
authCookie.Cookie.SecurePolicy = CookieSecurePolicy.Always;// require https
authCookie.Cookie.SameSite = SameSiteMode.Lax;// from external resource
// verify options are valid or throw exception
authCookie.Validate();
}
);
You may or may not need all of the authCookie values here, but it should get you started in the right direction!
It's possible to mix two mechanisms.
I use MicrosoftIdentity authentication for access to administration web pages and cookies authentication for my APIs and SignalR hubs.
I use this in startup ConfigureServices
services
.AddAuthentication(sharedOptions =>
{
sharedOptions.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
sharedOptions.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
sharedOptions.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
})
.AddCookie("CookiesApiScheme", options =>
{
options.SlidingExpiration = true;
// There is no redirection to a login page for APIs and SignalR Hubs, I just made a call to /Api/Login/SignIn with credential
options.AccessDeniedPath = new PathString("/Api/Login/AccessDenied"); // Action who just returns an Unauthorized
})
.AddMicrosoftIdentityWebApp(Configuration); // By default scheme is "CookieAuthenticationDefaults.AuthenticationScheme"
And in API controller you can use something like this
[Route("api/[controller]")]
[ApiController]
[Authorize(Roles = Roles.ADMIN)]
[Authorize(AuthenticationSchemes = "CookiesApiScheme")]
public class DefaultController : ControllerBase
{
[HttpGet]
public IEnumerable<string> Get()
{
return new string[] { "value1", "value2" };
}
}
Based on this post: ASP.NET Core 2.0 AzureAD Authentication not working

how to redirect from /signin-oidc back to my controller/action?

the callback url is https://localhost:44338/signin-oidc
lets say i am in controller/action , decorated with [Authorize]
how do i redirect from https://localhost:44338/signin-oidc back to my controller/action ?
Note : I am following the wiki :
Quickstart: Add sign-in with Microsoft to an ASP.NET Core web app
You can store the url on server side . For example ,base on code sample :
Quickstart: Add sign-in with Microsoft to an ASP.NET Core web app
modify your OIDC configurations like :
services.AddAuthentication(AzureADDefaults.AuthenticationScheme)
.AddAzureAD(options => Configuration.Bind("AzureAd", options));
services.Configure<OpenIdConnectOptions>(AzureADDefaults.OpenIdScheme, options =>
{
options.Authority = options.Authority + "/v2.0/";
options.Events = new OpenIdConnectEvents
{
OnRedirectToIdentityProvider = async n =>
{
//save url to state
n.ProtocolMessage.State = n.HttpContext.Request.Path.Value.ToString();
},
OnTokenValidated = ctx =>
{
var url = ctx.ProtocolMessage.GetParameter("state");
var claims = new List<Claim>
{
new Claim("myurl", url)
};
var appIdentity = new ClaimsIdentity(claims);
//add url to claims
ctx.Principal.AddIdentity(appIdentity);
return Task.CompletedTask;
},
OnTicketReceived = ctx =>
{
var url = ctx.Principal.FindFirst("myurl").Value;
ctx.ReturnUri = url;
return Task.CompletedTask;
}
};
// Per the code below, this application signs in users in any Work and School
// accounts and any Microsoft Personal Accounts.
// If you want to direct Azure AD to restrict the users that can sign-in, change
// the tenant value of the appsettings.json file in the following way:
// - only Work and School accounts => 'organizations'
// - only Microsoft Personal accounts => 'consumers'
// - Work and School and Personal accounts => 'common'
// If you want to restrict the users that can sign-in to only one tenant
// set the tenant value in the appsettings.json file to the tenant ID of this
// organization, and set ValidateIssuer below to true.
// If you want to restrict the users that can sign-in to several organizations
// Set the tenant value in the appsettings.json file to 'organizations', set
// ValidateIssuer, above to 'true', and add the issuers you want to accept to the
// options.TokenValidationParameters.ValidIssuers collection
options.TokenValidationParameters.ValidateIssuer = false;
});