User is not getting authenticated (cookies not getting set) after SAML getting processed successfully - saml-2.0

I am using an idp initiated SSO flow. I am using Kentor.AuthServices using OWIN middleware.
Most of the flow works except, user identity is not getting SET when the control reaches my callback method after successfully processing the SAML response.
Setting in web.config:
<kentor.authServices entityId="https://one-staging.com/MVSAMLServiceProvider"
returnUrl="https://5814a15e.ngrok.io/api/Account/UnsolicitedExternalLogin">
<identityProviders>
<add entityId="https://shibidp.edu/idp/shibboleth"
metadataLocation = "~/Providers/SAML2/Metadata/shibidp.edu.xml"
allowUnsolicitedAuthnResponse="false"
disableOutboundLogoutRequests="false"
binding="HttpRedirect">
</add>
<add entityId="abb:one:saml20:idp"
metadataLocation="~/Providers/SAML2/Metadata/abb.xml"
allowUnsolicitedAuthnResponse="true"
disableOutboundLogoutRequests="false"
binding="HttpRedirect">
</add>
</identityProviders>
</kentor.authServices>
Here is my Startup.cs:
public void ConfigureOAuth(IAppBuilder app)
{
app.UseExternalSignInCookie(Microsoft.AspNet.Identity.DefaultAuthenticationTypes.ExternalCookie);
OAuthBearerOptions = new OAuthBearerAuthenticationOptions();
OAuthAuthorizationServerOptions OAuthServerOptions = new OAuthAuthorizationServerOptions()
{
//For Dev enviroment only (on production should be AllowInsecureHttp = false)
AllowInsecureHttp = true,
TokenEndpointPath = new PathString("/oauth2/token"),
AccessTokenExpireTimeSpan = TimeSpan.FromMinutes(30),
Provider = new CustomOAuthProvider(),
AccessTokenFormat = new CustomJwtFormat()
};
// OAuth 2.0 Bearer Access Token Generation
app.UseOAuthAuthorizationServer(OAuthServerOptions);
app.UseOAuthBearerAuthentication(OAuthBearerOptions);
googleAuthOptions = new GoogleOAuth2AuthenticationOptions()
{
ClientId = System.Configuration.ConfigurationManager.AppSettings["GoogleClientId"],
ClientSecret = System.Configuration.ConfigurationManager.AppSettings["GoogleClientSecret"],
Provider = new GoogleAuthProvider()
};
app.UseGoogleAuthentication(googleAuthOptions);
app.Use(async (Context, next) =>{await next.Invoke();});
app.UseKentorAuthServicesAuthentication(CreateSAMLAuthServicesOptions());
app.Use(async (Context, next) =>{await next.Invoke();});
}
Here are the Kentor logs (no errors in the logs):
DEBUG 2018-12-28 14:02:32,682 8859ms emv-authService-logger MoveNext - Received unsolicited Saml Response _t0r6DHtsGygxkYcfNzdkEs72.M which is allowed for idp abb:one:saml20:idp
DEBUG 2018-12-28 14:02:32,729 8906ms emv-authService-logger MoveNext - Signature validation passed for Saml Response _t0r6DHtsGygxkYcfNzdkEs72.M
DEBUG 2018-12-28 14:02:32,729 8906ms emv-authService-logger MoveNext - Extracted SAML assertion oN4v.k9x2GE7s5S8OdeNWS.93j9
DEBUG 2018-12-28 14:02:32,729 8906ms emv-authService-logger MoveNext - Validated conditions for SAML2 Response _t0r6DHtsGygxkYcfNzdkEs72.M
INFO 2018-12-28 14:02:32,729 8906ms emv-authService-logger ProcessResponse - Successfully processed SAML response _t0r6DHtsGygxkYcfNzdkEs72.M and authenticated 10035094
Finally my redirect method:
[OverrideAuthentication]
[HostAuthentication(DefaultAuthenticationTypes.ApplicationCookie)]
[AllowAnonymous]
[Route("UnsolicitedExternalLogin", Name = "UnsolicitedExternalLogin")]
public async void GetUnsolicitedExternalLogin()
{
bool isAuthenticated = User.Identity.IsAuthenticated; //getting false
}
I have unfortunately been stuck with this problem for a week now. I'm sure this is really close to getting done, so any help would be greatly appreciated.
Thanks!

Looking at the code, I think that there is a mismatch on authentication schemes.
In the pipeline setup, a cookie middleware for the external authentication scheme is setup. But in the GetUnsolicitedExternalLogin method, the ApplicationCookie scheme is referenced. Change it to reference the external scheme instead.
It is also a good idea to check if the redirect from ~/AuthServices/Acs to GetUnsolicitedExternalLogin sets an external authentication cookie.

Related

Keycloak and Spring Oauth2 - CORS issue [duplicate]

I am using keycloak to secure my rest service. I am refering to the tutorial given here. I created the rest and front end. Now when I add keycloak on the backend I get CORS error when my front end makes api call.
Application.java file in spring boot looks like
#SpringBootApplication
public class Application
{
public static void main( String[] args )
{
SpringApplication.run(Application.class, args);
}
#Bean
public WebMvcConfigurer corsConfiguration() {
return new WebMvcConfigurerAdapter() {
#Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/api/*")
.allowedMethods(HttpMethod.GET.toString(), HttpMethod.POST.toString(),
HttpMethod.PUT.toString(), HttpMethod.DELETE.toString(), HttpMethod.OPTIONS.toString())
.allowedOrigins("*");
}
};
}
}
The keycloak properties in the application.properties file look like
keycloak.realm = demo
keycloak.auth-server-url = http://localhost:8080/auth
keycloak.ssl-required = external
keycloak.resource = tutorial-backend
keycloak.bearer-only = true
keycloak.credentials.secret = 123123-1231231-123123-1231
keycloak.cors = true
keycloak.securityConstraints[0].securityCollections[0].name = spring secured api
keycloak.securityConstraints[0].securityCollections[0].authRoles[0] = admin
keycloak.securityConstraints[0].securityCollections[0].authRoles[1] = user
keycloak.securityConstraints[0].securityCollections[0].patterns[0] = /api/*
The sample REST API that I am calling
#RestController
public class SampleController {
#RequestMapping(value ="/api/getSample",method=RequestMethod.GET)
public string home() {
return new string("demo");
}
}
the front end keycloak.json properties include
{
"realm": "demo",
"auth-server-url": "http://localhost:8080/auth",
"ssl-required": "external",
"resource": "tutorial-frontend",
"public-client": true
}
The CORS error that I get
XMLHttpRequest cannot load http://localhost:8090/api/getSample. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:9000' is therefore not allowed access. The response had HTTP status code 401.
I know.. the Problem is quite Old.
But if you've Problems with the local development with Spring Boot + Keycloak you can use the Config
keycloak.cors=true
in your application.properties.
Cheers :)
Try creating your CORS bean like my example. I recently went through the same thing (getting CORS to work) and it was a nightmare because the SpringBoot CORS support is currently not as robust or straightforward as the MVC CORS.
#Bean
public FilterRegistrationBean corsFilter() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
CorsConfiguration config = new CorsConfiguration();
config.setAllowCredentials(true);
config.addAllowedOrigin("*");
config.addAllowedHeader("*");
config.addAllowedMethod("*");
source.registerCorsConfiguration("/**", config);
FilterRegistrationBean bean = new FilterRegistrationBean(new CorsFilter(source));
bean.setOrder(0);
return bean;
}
This is how I set it up to accept any origin application-wide, but if you change a few of the parameters you should be able to replicate what you want. ie. if you wanted to add only the methods you mentioned, chain some addAllowedMethod(). Allowed origins would be the same, and then your addMapping("/api/*") would become source.registerCorsConfiguration("/api/*", config);.
Edit:
Spring Data Rest and Cors
Take a look at this. Sebastian is on the Spring engineering team so this is about as good as you're going to get for an official answer.
I came here with the same problem and fix it ommiting authentication for OPTIONS method only, like this:
keycloak.securityConstraints[0].security-collections[0].omitted-methods[0]=OPTIONS
It worked for me because the OPTIONS request Keycloack does, does not include Authentication header.
UPDATE
There was something with my browser's cache so I could not see the real impact of a change in my backend code. It looks like what really worked for me was enabling all CORS origins at #RestController level, like this:
#CrossOrigin(origins = "*")
#RestController
public class UsersApi {...}
I don't have access to code examples, but based on the code configurations you have included, it looks like a missing configuration is causing spring to exclude CORS headers.
J. West's response is similar to recent issues I encountered with Spring and CORS, I would however caution you to look into which implementation a spring example references, because there are two. Spring Security and Spring MVC Annotations. Both of these implementations work independent of each other, and can not be combined.
When using the filter based approach as you are (even boiled down), the key was to set allow credentials to true, in order for the authentication headers to be sent by the browser across domains. I would also advise using the full code method proposed above, as this will allow you to create a far more configurable web application for deployment across multiple domains or environments by property injection or a service registry.
Access-Control-Allow-Origin header is supposed to be set by the server application basis the Origin request header provided in the request to the server application. Usually browsers set the Origin header in request whenever they sense a cross origin request being made. And they expect a Access-Control-Allow-Origin header in response to allow it.
Now, for keycloak, I struggled with the same issue. Looking at this, it seems like keycloak does not add Access-Control-Allow-Origin header in case of error response. However, for me it was not adding this header in the response even in case of success response.
Looking into the code and adding breakpoints, I noticed that the webOrigin for client object was not getting populated from the Origin header even if passed and hence CORS was not adding the access control response header.
I was able to get it working by adding the following line of code just before the CORS build call:
client.addWebOrigin(headers.getRequestHeader("Origin").get(0));
before:
Cors.add(request, Response.ok(res, MediaType.APPLICATION_JSON_TYPE)).auth().allowedOrigins(client).allowedMethods("POST").exposedHeaders(Cors.ACCESS_CONTROL_ALLOW_METHODS).build();
Once I built the code with this change and started the server, I started getting the three access control response headers:
Access-Control-Expose-Headers: Access-Control-Allow-Methods
Access-Control-Allow-Origin: http://localhost:9000
Access-Control-Allow-Credentials: true
I am using client credentials grant type; hence i added it only in the buildClientCredentialsGrant at TokenEndpoint.java#L473.
I still need to do some more code diving in order to say for sure that it is a bug for success responses at well and to find a better place to set this on the client object in keycloak code (like where client object is being constructed)
You are welcome to give it a try.
UPDATE:
I take this back. I re-registered my client in keycloak with Root URL as http://localhost:9000 (which is my front-end's application port) and i started getting the proper access control response headers. Hope this helps you.
I know the problem is too old but, I found better solution.
Read more at official documentation
Inside your application.yml file
keycloak:
auth-server-url: http://localhost:8180/auth
realm: CollageERP
resource: collage-erp-web
public-client: true
use-resource-role-mappings: true
cors: true
cors-max-age: 0
principal-attribute: preferred_username
cors-allowed-methods: POST, PUT, DELETE, GET
cors-allowed-headers: X-Requested-With, Content-Type, Authorization, Origin, Accept, Access-Control-Request-Method, Access-Control-Request-Headers
or you can config using application.properties file
keycloak.auth-server-url= http://localhost:8180/auth
keycloak.realm= CollageERP
keycloak.resource= collage-erp-web
keycloak.public-client= true
keycloak.use-resource-role-mappings= true
keycloak.cors= true
keycloak.cors-max-age= 0
keycloak.principal-attribute= preferred_username
keycloak.cors-allowed-methods= POST, PUT, DELETE, GET
keycloak.cors-allowed-headers= X-Requested-With, Content-Type, Authorization, Origin, Accept, Access-Control-Request-Method, Access-Control-Request-Headers
and my java adaper class
import org.keycloak.adapters.KeycloakConfigResolver;
import org.keycloak.adapters.springboot.KeycloakSpringBootConfigResolver;
import org.keycloak.adapters.springsecurity.KeycloakConfiguration;
import org.keycloak.adapters.springsecurity.config.KeycloakWebSecurityConfigurerAdapter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.core.session.SessionRegistryImpl;
import org.springframework.security.web.authentication.session.RegisterSessionAuthenticationStrategy;
import org.springframework.security.web.authentication.session.SessionAuthenticationStrategy;
import javax.ws.rs.HttpMethod;
#KeycloakConfiguration
#EnableGlobalMethodSecurity(jsr250Enabled = true)
public class KeycloakSecurityConfig extends KeycloakWebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
super.configure(http);
http.cors().and().authorizeRequests()
.antMatchers(HttpMethod.OPTIONS).permitAll()
.antMatchers("/api/**")
.authenticated()
.anyRequest().permitAll();
http.csrf().disable();
}
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) {
auth.authenticationProvider(keycloakAuthenticationProvider());
}
#Bean
#Override
protected SessionAuthenticationStrategy sessionAuthenticationStrategy() {
return new RegisterSessionAuthenticationStrategy(new SessionRegistryImpl());
}
#Bean
public KeycloakConfigResolver KeycloakConfigResolver() {
return new KeycloakSpringBootConfigResolver();
}
}
I want to share with you the solution that worked for me hoping to help whoever is facing the same issue. I am going to give you two solutions actually.
Spring reactive:
#Configuration
#EnableWebFluxSecurity
public class SecurityConfig {
#Autowired
private ReactiveClientRegistrationRepository clientRegistrationRepository;
#Bean
SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {
CorsConfiguration cors_config = new CorsConfiguration();
cors_config.setAllowCredentials(true);
cors_config.applyPermitDefaultValues();
cors_config.setAllowedOrigins(Arrays.asList("http://localhost:3000", "null"));
cors_config.setAllowedMethods(List.of("GET","POST","OPTIONS","DELETE"));
cors_config.setAllowedHeaders(List.of("*"));
http.cors().configurationSource(source -> cors_config)
.and()
.csrf().disable()
.authorizeExchange(exchanges -> exchanges.anyExchange().authenticated())
.oauth2Login()//Setting Oauth2Login
.authenticationSuccessHandler(new RedirectServerAuthenticationSuccessHandler("")).and()
.logout(logout -> logout //Setting Oauth2Logout
.logoutHandler(logoutHandler())
.logoutSuccessHandler(oidcLogoutSuccessHandler()));
return http.build();
}
private ServerLogoutSuccessHandler oidcLogoutSuccessHandler() {
OidcClientInitiatedServerLogoutSuccessHandler oidcLogoutSuccessHandler =
new OidcClientInitiatedServerLogoutSuccessHandler(this.clientRegistrationRepository);
// Sets the location that the End-User's User Agent will be redirected to
// after the logout has been performed at the Provider
oidcLogoutSuccessHandler.setPostLogoutRedirectUri("");
return oidcLogoutSuccessHandler;
}
private DelegatingServerLogoutHandler logoutHandler() {
//Invalidate session on logout
return new DelegatingServerLogoutHandler(
new SecurityContextServerLogoutHandler(), new WebSessionServerLogoutHandler());
}
}
Spring MVC:
#Configuration
public class SecurityConfig {
#Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
CorsConfiguration cors_config = new CorsConfiguration();
cors_config.setAllowCredentials(true);
cors_config.applyPermitDefaultValues();
cors_config.setAllowedOrigins(Arrays.asList("http://localhost:3000", "null"));
cors_config.setAllowedMethods(List.of("GET","POST","OPTIONS","DELETE"));
cors_config.setAllowedHeaders(List.of("*"));
http.cors().configurationSource(source -> cors_config).and()...
return http.build();
}
}
Be sure to have cors enabled on Keycloak too, navigate to
realm->clients->settings->weborigins
and submit your permitted origins.
If you are sending credentials or cookies in your requests, be sure to configure it, for example, if you are using ReactJS:
const httpConfig = { withCredentials: true };
axios.get('YourUrl', httpConfig)
.then(response => {})
.catch(error => {})
.finally(() => {});
When your client is sending an Authentication header, you cannot use
allowedOrigins("*"). You must configure a specific origin URL.
Since you have set the property keycloak.cors = true in your application.properties file, you have to mention the CORS enabled origins in the Keycloak server. To do that follow the below steps.
Go to Clients -> Select the client (Token owner) -> Settings -> Web Origins
Add origins one by one or add * to allow all.
After doing this you have to get a new token. (If you decode the token you will see your origins as allowed-origins": ["*"])
Setting the property keycloak.cors = false is another option. But this completely disables CORS.

Auth0 getting powerBI token

I am authentocating using Auth0 and my provider is wadd
I am trying to get the token to use with PowerBi, I have tried the follow console app (token, is from the above, clientId and Secret are the same as what is used in my Auth0 connector for the connection to my AzureAD
var cred = new ClientCredential(clientId, secret);
var access_token_from_client_side = token;
var context = new AuthenticationContext("https://login.windows.net/common");
var res = context.AcquireTokenAsync("https://analysis.windows.net/powerbi/api",
functionCred, new UserAssertion(access_token_from_client_side)).ConfigureAwait(false).GetAwaiter().GetResult();
Console.WriteLine(res.AccessToken);
I get the following error
{"error":"invalid_grant","error_description":"AADSTS50013: Assertion failed signature validation. [Reason - The provided signature value did not match the expected signature value., Thumbprint of key used by client: '...', Found key 'Start=12/26/2019 00:00:00, End=12/25/2024 00:00:00']\r\nTrace ID: ...\r\nCorrelation ID: ...\r\nTimestamp: 2020-02-25 21:13:48Z","error_codes":[50013],"timestamp":"2020-02-25 21:13:48Z","trace_id":"...","correlation_id":"b890dfad-1d6f-4e4a-ab15-34328818c295","error_uri":"https://login.microsoftonline.com/error?code=50013"}
My goal is to get a Token to use for PowerBI starting with my AzureAD auth token. I have allow the application permissions for PowerBI from Azure
What am I missing?

Why doesn't "AutomaticRedirectAfterSignOut = true;" work for redirecting "post-logout" in the following context?

The main application is a ASP.NET Core 2.2 Web Application using Razor Pages.
User accesses the application URL & gets redirected to IdentityServer4 login screen
User successfully login
User Logsout and gets redirected to "You have been logged out screen" of IdentityServer4 after successfully skipping the logout confirmation prompt.
This step fails: The user is NOT automatically redirected to the login page of IdentityServer4. He is instead redirected to a page where he is informed that he has logged off, here he is also asked if he wants to go to the login page, which is where i want him to be automatically redirected to without any prompts.
What I have tried so far:
In IDP >> Quickstart >> Account >> AccountOptions >> public static bool AutomaticRedirectAfterSignOut = true; (this should be regarded as set to true the entire post)
In IDP >> Startup >> ConfigureServices >> .AddOpenIdConnect >>
options.SignedOutCallbackPath = "/signout-callback-oidc"; Adding this line of code did not help.
I tried running using Chrome, Firefox, Edge - the issue persisted
Code from IDP Startup.cs
public void ConfigureServices(IServiceCollection services)
{
// adds MVC framework services
services.AddMvc();
/*// adds services Razor Pages and ASP.NET MVC require
.AddRazorPagesOptions(options => {options.Conventions.AddPageRoute("/index", "home"); });*/
// dependency injection of services
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>(); // registers an IHttpContextAccessor so we can access the current HttpContext in services by injecting it
services.AddScoped<IThisHttpClient, ThisHttpClient>(); // registers an "ThisHttpClient"
services.AddScoped<IOrderService, OrderService>();
services.AddScoped<IAccountService, AccountService>();
services.AddLogging();
// adding open id connect authentication
services
.AddAuthentication(options =>
{
options.DefaultScheme = "Cookies";
options.DefaultChallengeScheme = "oidc";
})
.AddCookie("Cookies") // configures the cookie handler and enables the application to use cookie based authentication for the default scheme
// The below handler creates authorization requests, token and other requests, and handles the identity token validation
// "oidc" ensure when part of application requires authentication, "OpenIdConnect" will be triggered by default
.AddOpenIdConnect("oidc", options =>
{
options.SignInScheme = "Cookies"; // matches the default scheme for authentication, ensures that succesful authentication result will be stored in a our applications "cookie"
options.Authority = "https://localhost:44370/"; // the authority is set to be the identity provider (the authority responsible for the IDP part of the OIDC flow), the middleware will use this value to read the metadata on the discovery end point, so it knows where to find different endpoints ad other information
options.ClientId = "3TL"; // must match client ID at IDP level
options.ResponseType = "code id_token"; // one of response type of the Hybrid ground to be used
//options.CallbackPath = new PathString("..."); // allows the change of the redirect Uri from inside the IdentityServerConfig (hand made class)
//options.SignedOutCallbackPath = new PathString("...") //
options.Scope.Add("openid"); // required scope which requires in sub value being included
options.Scope.Add("profile"); // ensures profile related claims are included
options.Scope.Add("roles"); // requesting a CUSTOM MADE scope (check IDP scopes/roles for details)
options.SaveTokens = true; // allows the middleware to save the tokens it receives from the identity provider so we can easelly use them afterwards
options.ClientSecret = "test_secret"; // must match secret at IDP level
options.GetClaimsFromUserInfoEndpoint = true; // enables GETing claims from user info endpoint regarding the current authenticate user
//options.ClaimActions.Remove("amr"); // allows us to remove CLAIM FILTERS (AKA this ensures the AMR(Authentication Method Reference) claim is dispalyed and not filtered out)
options.ClaimActions.DeleteClaim("sid"); // removing unnecessary claims from the initial cookie (session ID at level of IDP)
options.ClaimActions.DeleteClaim("idp"); // removing unnecessary claims from the initial cookie (the Identity Provider)
options.ClaimActions.DeleteClaim("name"); // removing unnecessary claims from the initial cookie (removing this type of data reduces the cookie size)
options.ClaimActions.DeleteClaim("given_name"); // removing unnecessary claims from the initial cookie (removing this type of data reduces the cookie size)
options.ClaimActions.DeleteClaim("family_name"); // removing unnecessary claims from the initial cookie (removing this type of data reduces the cookie size)
options.ClaimActions.MapUniqueJsonKey("role", "role"); // adding the CUSTOM MADE claim to the claims map
//options.SignedOutCallbackPath = "/signout-callback-oidc"; // NOTE THIS DOES NOT WORK
});
}
Code from IDP Config.cs
public static IEnumerable<Client> GetClients()
{
return new List<Client>
{
/// IMPORTANT: The client details declared in here must be matched with their exact copy on the client
new Client
{
ClientId = "3TL",
ClientName = "3 Tier Logistics",
//using hybrid flow to authenticate users
AllowedGrantTypes = GrantTypes.Hybrid,
// limits the URIs the user can be redirected to after getting authenticated or logging out
RedirectUris = {"https://localhost:44321/signin-oidc" },
PostLogoutRedirectUris = { "https://localhost:44321/signout-callback-oidc" },
AllowedScopes = // configures the allowed scopes for this particular client (aka what user info to share from all the available)
{
IdentityServerConstants.StandardScopes.OpenId,
IdentityServerConstants.StandardScopes.Profile,
"roles"
},
ClientSecrets =
{
new Secret("test_secret".Sha256())
}
}
};
}
Code from Application Server Logout Page
public class LoginModel : PageModel
{
private OrderService orderService;
private string targetUrlRegisterClient;
[BindProperty]
public Client Client { get; set; }
public void OnGet()
{
Task.Run(() => HttpContext.SignOutAsync("Cookies"));
Task.Run(() => HttpContext.SignOutAsync("oidc"));
}
public void OnPost()
{
targetUrlRegisterClient = "http://localhost:8080/server_war_exploded/root/api/registerclient";
orderService = new OrderService();
Task<string> response = orderService.PostRegisterClientAsync(Client, targetUrlRegisterClient);
}
}
Debug output of logout hit
Microsoft.AspNetCore.Hosting.Internal.WebHost:Information: Request starting HTTP/1.1 GET http://localhost:44321/Login
Microsoft.AspNetCore.Mvc.RazorPages.Internal.PageActionInvoker:Information: Route matched with {page = "/Login"}. Executing page /Login
Microsoft.AspNetCore.Mvc.RazorPages.Internal.PageActionInvoker:Information: Executing handler method Client_Customer.Pages.LoginModel.OnGet with arguments ((null)) - ModelState is Valid
Microsoft.AspNetCore.Mvc.RazorPages.Internal.PageActionInvoker:Information: Executed handler method OnGet, returned result .
Microsoft.AspNetCore.Mvc.RazorPages.Internal.PageActionInvoker:Information: Executing an implicit handler method - ModelState is Valid
Microsoft.AspNetCore.Mvc.RazorPages.Internal.PageActionInvoker:Information: Executed an implicit handler method, returned result Microsoft.AspNetCore.Mvc.RazorPages.PageResult.
Microsoft.AspNetCore.Authentication.OpenIdConnect.OpenIdConnectHandler:Information: AuthenticationScheme: oidc signed out.
Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationHandler:Information: AuthenticationScheme: Cookies signed out.
Microsoft.AspNetCore.Mvc.RazorPages.Internal.PageActionInvoker:Information: Executed page /Login in 69.7362ms
Microsoft.AspNetCore.Hosting.Internal.WebHost:Information: Request starting HTTP/2.0 GET https://localhost:44370/connect/endsession?post_logout_redirect_uri=https%3A%2F%2Flocalhost%3A44321%2Fsignout-callback-oidc&id_token_hint=eyJhbGciOiJSUzI1NiIsImtpZCI6IjA5MmI0Yjk0MjQzNjJiZmQ3ZWM3Y2MyMDU1NGFiMTZlIiwidHlwIjoiSldUIn0.eyJuYmYiOjE1NTc5MDkzNzAsImV4cCI6MTU1NzkwOTY3MCwiaXNzIjoiaHR0cHM6Ly9sb2NhbGhvc3Q6NDQzNzAiLCJhdWQiOiIzVEwiLCJub25jZSI6IjYzNjkzNTA2MTYwMzY3NjQyMC5ZMkl6WTJReVlqRXRZMlF5TXkwME5UTmlMVGhpWkdFdFlqQTBNRGsxTVRWak1qazRNak5rTVdaaU1XRXRNV1EwTXkwME0yVTBMVGsxTlRNdFlUTmpZalEwWlRVd1pHSm0iLCJpYXQiOjE1NTc5MDkzNzAsImF0X2hhc2giOiJWWHVYRHJZcTZNWnF3X2N2T0h3eDNnIiwic2lkIjoiNGViNzQ5ZjA5ZGQ4MjNkNzI5NmQzMjU1NWU5MGJiMDYiLCJzdWIiOiIyMjIyIiwiYXV0aF90aW1lIjoxNTU3OTA5MzY3LCJpZHAiOiJsb2NhbCIsImFtciI6WyJwd2QiXX0.NzqA4kILvZgjlTd6dhku6827dG-_9MkJpAH11inQ0-biR0GXP7fkrklIRy8DgxDh8zEriNMUSM8gd9E_p7Zn4hn-HRZ5MJf1hOHfyo3Pdih0sgZ6eNzOvAManiLgNb85n6hcNx04H7PRLHjlZOR01dYkjZrnRCNTWLnVlrsu3xmnonagOtvtF5a_QuZqVJvUedqxby95RH-U5AuqW2pdPTQfzQVZBvUXrAdJGj6wOXwHCn9TSpRJcH4OPtWOMvP8Z84Iiz8vH_lK_qtBUkcSmjs_kOt_qFeGYgDE_xv71HMa0HhcbJlQ-GPwTJu2cA0teGUby33Sj-td92A7y1v5mQ&state=CfDJ8IMSTeB9liZHhYIais0HVw5svLoMCzrej-fgkjkCV_TaQjqMXAXfoVdkgkWNdpnCfCNjv9hXQ_qcU3uSC7KVbJaFghyxVZD1b3eL8Yeb_G8gnDDGoJYODAljLU_pki5M9aZbR_UbjmpgodcofaWnccPgRlLOf3nSTH1eiS2zoe8n&x-client-SKU=ID_NETSTANDARD2_0&x-client-ver=5.3.0.0
Microsoft.AspNetCore.Hosting.Internal.WebHost:Information: Request finished in 94.0857ms 302 text/html; charset=utf-8
IdentityServer4.Hosting.EndpointRouter:Debug: Request path /connect/endsession matched to endpoint type Endsession
IdentityServer4.Hosting.EndpointRouter:Debug: Endpoint enabled: Endsession, successfully created handler: IdentityServer4.Endpoints.EndSessionEndpoint
IdentityServer4.Hosting.IdentityServerMiddleware:Information: Invoking IdentityServer endpoint: IdentityServer4.Endpoints.EndSessionEndpoint for /connect/endsession
IdentityServer4.Endpoints.EndSessionEndpoint:Debug: Processing signout request for 2222
IdentityServer4.Validation.EndSessionRequestValidator:Debug: Start end session request validation
IdentityServer4.Validation.TokenValidator:Debug: Start identity token validation
IdentityServer4.Stores.ValidatingClientStore:Debug: client configuration validation for client 3TL succeeded.
IdentityServer4.Validation.TokenValidator:Debug: Client found: 3TL / 3 Tier Logistics
IdentityServer4.Test.TestUserProfileService:Debug: IsActive called from: IdentityTokenValidation
IdentityServer4.Validation.TokenValidator:Debug: Calling into custom token validator: IdentityServer4.Validation.DefaultCustomTokenValidator
IdentityServer4.Validation.TokenValidator:Debug: Token validation success
{
"ClientId": "3TL",
"ClientName": "3 Tier Logistics",
"ValidateLifetime": false,
"Claims": {
"nbf": 1557909370,
"exp": 1557909670,
"iss": "https://localhost:44370",
"aud": "3TL",
"nonce": "636935061603676420.Y2IzY2QyYjEtY2QyMy00NTNiLThiZGEtYjA0MDk1MTVjMjk4MjNkMWZiMWEtMWQ0My00M2U0LTk1NTMtYTNjYjQ0ZTUwZGJm",
"iat": 1557909370,
"at_hash": "VXuXDrYq6MZqw_cvOHwx3g",
"sid": "4eb749f09dd823d7296d32555e90bb06",
"sub": "2222",
"auth_time": 1557909367,
"idp": "local",
"amr": "pwd"
}
}
IdentityServer4.Validation.EndSessionRequestValidator:Information: End session request validation success
{
"ClientId": "3TL",
"ClientName": "3 Tier Logistics",
"SubjectId": "2222",
"PostLogOutUri": "https://localhost:44321/signout-callback-oidc",
"State": "CfDJ8IMSTeB9liZHhYIais0HVw5svLoMCzrej-fgkjkCV_TaQjqMXAXfoVdkgkWNdpnCfCNjv9hXQ_qcU3uSC7KVbJaFghyxVZD1b3eL8Yeb_G8gnDDGoJYODAljLU_pki5M9aZbR_UbjmpgodcofaWnccPgRlLOf3nSTH1eiS2zoe8n",
"Raw": {
"post_logout_redirect_uri": "https://localhost:44321/signout-callback-oidc",
"id_token_hint": "***REDACTED***",
"state": "CfDJ8IMSTeB9liZHhYIais0HVw5svLoMCzrej-fgkjkCV_TaQjqMXAXfoVdkgkWNdpnCfCNjv9hXQ_qcU3uSC7KVbJaFghyxVZD1b3eL8Yeb_G8gnDDGoJYODAljLU_pki5M9aZbR_UbjmpgodcofaWnccPgRlLOf3nSTH1eiS2zoe8n",
"x-client-SKU": "ID_NETSTANDARD2_0",
"x-client-ver": "5.3.0.0"
}
}
IdentityServer4.Endpoints.EndSessionEndpoint:Debug: Success validating end session request from 3TL
Microsoft.AspNetCore.Hosting.Internal.WebHost:Information: Request finished in 60.2054ms 302
Microsoft.AspNetCore.Hosting.Internal.WebHost:Information: Request starting HTTP/2.0 GET https://localhost:44370/Account/Logout?logoutId=CfDJ8IMSTeB9liZHhYIais0HVw7kc9GyTnHxoDNbRDCp7qA3cjwUvTmwOc8iOz2QeBz21IjWognFICseoXkQwH-eQJtXY9bWxa1vP3GLUz98cWKI1VMcnArspUbxRT9bcUF1ZrmloS7t_Us-uV9Ipa-VkgSUmLZfXAWa2f-WXPIv3VRmGwLNV7dqQa_pQOTkyDoiW_ddGElcwit15bJ3BLS6f52dYIU5fzjlSBtzGqT516-usiS-wmfacbACtJQn1VaEahKiBnW7X1gI4PRhQhCZF-IFzeXjESuMigwFyUay7K79DOZCqJ7ReU-RZ7GR1TsFsnqS8212Dr10hkznljRMnDeB6CZbB87LorJxZvf_eH33NBhzJzCZ1bwvPoz_vJeQoHO50P1IfNUGZjO8Y7pYimUC52SCe0jCKUUF8a5t_HZHMNVvtoCgC8b42zHE9rM5ms25BWLTFsgQH6wJFG09fmI5Eu_ICWCTm7XbQxMsBLK8cXdyIb_g1ccqaoz1gohMtpfciokB5_xInN1EcResbtkRUNeLO5DN_c5aFX5QZrC-HJVqxLAdKzZ4coL-x06s8Emvu9w3S1ZjlYLZCPMKHfK1LKgAFnqq1rUEV9PDtwmWDe_gz9ga45MHyMYrrFTswq2ut2gylVFbnb9nEt-g4OWzC6Mqi1mq6Y9CmWefYDwmbsyO-hM9r-p3bZVgYCJkw77zP0UDzFndpM_82gwMau8PH85qxEk1Hz3kJJxilbvAOX1lowfBBymXZH1M0qaiIVS0V2MPL19ySkhIiBQZs7rYcsXMU-wILzhm_729Xt9TxUwZxRFgwngE2fFizgyG_g
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker:Information: Route matched with {action = "Logout", controller = "Account"}. Executing action IdentityServer4.Quickstart.UI.AccountController.Logout (IdentityServer)
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker:Information: Executing action method IdentityServer4.Quickstart.UI.AccountController.Logout (IdentityServer) with arguments (CfDJ8IMSTeB9liZHhYIais0HVw7kc9GyTnHxoDNbRDCp7qA3cjwUvTmwOc8iOz2QeBz21IjWognFICseoXkQwH-eQJtXY9bWxa1vP3GLUz98cWKI1VMcnArspUbxRT9bcUF1ZrmloS7t_Us-uV9Ipa-VkgSUmLZfXAWa2f-WXPIv3VRmGwLNV7dqQa_pQOTkyDoiW_ddGElcwit15bJ3BLS6f52dYIU5fzjlSBtzGqT516-usiS-wmfacbACtJQn1VaEahKiBnW7X1gI4PRhQhCZF-IFzeXjESuMigwFyUay7K79DOZCqJ7ReU-RZ7GR1TsFsnqS8212Dr10hkznljRMnDeB6CZbB87LorJxZvf_eH33NBhzJzCZ1bwvPoz_vJeQoHO50P1IfNUGZjO8Y7pYimUC52SCe0jCKUUF8a5t_HZHMNVvtoCgC8b42zHE9rM5ms25BWLTFsgQH6wJFG09fmI5Eu_ICWCTm7XbQxMsBLK8cXdyIb_g1ccqaoz1gohMtpfciokB5_xInN1EcResbtkRUNeLO5DN_c5aFX5QZrC-HJVqxLAdKzZ4coL-x06s8Emvu9w3S1ZjlYLZCPMKHfK1LKgAFnqq1rUEV9PDtwmWDe_gz9ga45MHyMYrrFTswq2ut2gylVFbnb9nEt-g4OWzC6Mqi1mq6Y9CmWefYDwmbsyO-hM9r-p3bZVgYCJkw77zP0UDzFndpM_82gwMau8PH85qxEk1Hz3kJJxilbvAOX1lowfBBymXZH1M0qaiIVS0V2MPL19ySkhIiBQZs7rYcsXMU-wILzhm_729Xt9TxUwZxRFgwngE2fFizgyG_g) - Validation state: Valid
Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationHandler:Information: AuthenticationScheme: idsrv signed out.
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker:Information: Executed action method IdentityServer4.Quickstart.UI.AccountController.Logout (IdentityServer), returned result Microsoft.AspNetCore.Mvc.ViewResult in 24.8267ms.
Microsoft.AspNetCore.Mvc.ViewFeatures.ViewResultExecutor:Information: Executing ViewResult, running view LoggedOut.
Microsoft.AspNetCore.Mvc.ViewFeatures.ViewResultExecutor:Information: Executed ViewResult - view LoggedOut executed in 19.1822ms.
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker:Information: Executed action IdentityServer4.Quickstart.UI.AccountController.Logout (IdentityServer) in 48.1906ms
Microsoft.AspNetCore.Hosting.Internal.WebHost:Information: Request finished in 59.083ms 200 text/html; charset=utf-8
Microsoft.AspNetCore.Hosting.Internal.WebHost:Information: Request starting HTTP/2.0 GET https://localhost:44370/lib/bootstrap/css/bootstrap.css
Microsoft.AspNetCore.Hosting.Internal.WebHost:Information: Request starting HTTP/2.0 GET https://localhost:44370/icon.png
Microsoft.AspNetCore.Hosting.Internal.WebHost:Information: Request starting HTTP/2.0 GET https://localhost:44370/lib/jquery/jquery.js
Microsoft.AspNetCore.Hosting.Internal.WebHost:Information: Request finished in 17.4182ms 404
Microsoft.AspNetCore.Hosting.Internal.WebHost:Information: Request finished in 16.464ms 404
Microsoft.AspNetCore.Hosting.Internal.WebHost:Information: Request starting HTTP/2.0 GET https://localhost:44370/css/site.css
Microsoft.AspNetCore.Hosting.Internal.WebHost:Information: Request finished in 20.1358ms 404
Microsoft.AspNetCore.Hosting.Internal.WebHost:Information: Request finished in 8.4111ms 404
Microsoft.AspNetCore.Hosting.Internal.WebHost:Information: Request starting HTTP/2.0 GET https://localhost:44370/lib/bootstrap/js/bootstrap.js
Microsoft.AspNetCore.Hosting.Internal.WebHost:Information: Request starting HTTP/2.0 GET https://localhost:44370/js/signout-redirect.js
Microsoft.AspNetCore.Hosting.Internal.WebHost:Information: Request starting HTTP/2.0 GET https://localhost:44370/connect/endsession/callback?endSessionId=CfDJ8IMSTeB9liZHhYIais0HVw4UP5MHpGg4UIrZ1rPYhDNKZ0T8aLNc6sQ00tDxQN7898mdUQGymNjElfE09nHu53Jcmj2OlrmLZdqwrS33_ea8BVUC1KpYuh1NtSAGTbqHF-Z4GVqWLIM3--4-kv1Jwggs2PBPjytq65cjCge00Zg2lNQEsKjgNxupv-gNwSWvdklOEQ9gRuGAd8dTXhUJqHomK7a87OWqQvuE1hQieeDesgtCSaVhC9-CcaEJycYkOkmyrxFrOWG4Npw6smPd-XU
Microsoft.AspNetCore.Hosting.Internal.WebHost:Information: Request finished in 7.3577ms 404
Microsoft.AspNetCore.Hosting.Internal.WebHost:Information: Request finished in 7.7551ms 404
IdentityServer4.Hosting.EndpointRouter:Debug: Request path /connect/endsession/callback matched to endpoint type Endsession
'iisexpress.exe' (CoreCLR: clrhost): Loaded 'C:\Program Files\dotnet\shared\Microsoft.NETCore.App\2.2.4\System.Net.Security.dll'. Symbols loaded.
IdentityServer4.Hosting.EndpointRouter:Debug: Endpoint enabled: Endsession, successfully created handler: IdentityServer4.Endpoints.EndSessionCallbackEndpoint
IdentityServer4.Hosting.IdentityServerMiddleware:Information: Invoking IdentityServer endpoint: IdentityServer4.Endpoints.EndSessionCallbackEndpoint for /connect/endsession/callback
IdentityServer4.Endpoints.EndSessionCallbackEndpoint:Debug: Processing signout callback request
IdentityServer4.Stores.ValidatingClientStore:Debug: client configuration validation for client 3TL succeeded.
IdentityServer4.Validation.EndSessionRequestValidator:Debug: No client front-channel logout URLs
IdentityServer4.Validation.EndSessionRequestValidator:Debug: No client back-channel logout URLs
IdentityServer4.Endpoints.EndSessionCallbackEndpoint:Information: Successful signout callback.
IdentityServer4.Endpoints.EndSessionCallbackEndpoint:Debug: No client front-channel iframe urls
IdentityServer4.Endpoints.EndSessionCallbackEndpoint:Debug: No client back-channel iframe urls
Microsoft.AspNetCore.Hosting.Internal.WebHost:Information: Request finished in 103.2685ms 200 text/html; charset=UTF-8
Microsoft.AspNetCore.Hosting.Internal.WebHost:Information: Request starting HTTP/2.0 GET https://localhost:44370/favicon.ico
Microsoft.AspNetCore.Hosting.Internal.WebHost:Information: Request finished in 1.9017ms 404
Microsoft.AspNetCore.Hosting.Internal.WebHost:Information: Request starting HTTP/2.0 GET https://localhost:44370/favicon.ico
Microsoft.AspNetCore.Hosting.Internal.WebHost:Information: Request finished in 2.2642ms 404
Microsoft.AspNetCore.Hosting.Internal.WebHost:Information: Request starting HTTP/2.0 GET https://localhost:44370/favicon.ico
Microsoft.AspNetCore.Hosting.Internal.WebHost:Information: Request finished in 2.4325ms 404
The core problem:
I want to be redirected to the login page of the IDP which i can not currently achieve, and i need help to understand what am I doing wrong.
P.S. I am 3rd semester at IT University and this is the first time I am using IndetityServer4, I hope to use it for all my future applications, thank you for your patience.
If you're looking for the signout-redirect.js:
window.addEventListener("load", function () {
var a = document.querySelector("a.PostLogoutRedirectUri");
if (a) {
window.location = a.href;
}
});

AddOpenIdConnect with Azure AD V2

Having some issues with AddOpenIdConnect in net core 2.0 and Azure AD (V2). After challenging, entering credentials in Azure AD and being returned back to my application the authenticationhandler seems to redirect me to the original method that initiated the challenge rather than the defined callback method.
However, the httpcontext.user is populated with a claims identity with the correct claims on it.
Code is simplified for the purpose of this post.
Startup looks like:
services.AddAuthentication(o =>
{
o.DefaultChallengeScheme = "aad";
o.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
o.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
})
.AddJwtBearer(JwtBearerDefaults.AuthenticationScheme, o =>
{
if (!Environment.IsProduction())
{
o.RequireHttpsMetadata = false;
}
o.Authority = Configuration.GetValue<string>("Authentication:Authority");
o.Audience = Constants.Audiences.Self;
o.TokenValidationParameters = new TokenValidationParameters
{
NameClaimType = OpenIdConnectConstants.Claims.Subject,
RoleClaimType = OpenIdConnectConstants.Claims.Role,
IssuerSigningKey =
new X509SecurityKey(
GetSigningCertificate(Configuration.GetValue<string>("Certificates:Signing")))
};
})
.AddCookie()
.AddOpenIdConnect("aad", o =>
{
if (!Environment.IsProduction())
{
o.RequireHttpsMetadata = false;
}
o.Authority = "https://login.microsoftonline.com/{tenantID}/v2.0";
o.AuthenticationMethod = OpenIdConnectRedirectBehavior.RedirectGet;
o.ClientId = "[clientid]";
o.ClientSecret = "[clientsecret]";
o.ResponseMode = "form_post";
o.ResponseType = "id_token";
o.CallbackPath = new PathString("/api/connect/microsoftcallback2");
o.TokenValidationParameters = new TokenValidationParameters
{
ValidIssuer = "https://login.microsoftonline.com/{tenantID}/v2.0"
};
});
Challenge:
[AllowAnonymous]
[HttpGet("authorize", Name = "authorize")]
public async Task<IActionResult> ChallengeTemp()
{
return Challenge("aad");
}
Trace log:
Microsoft.AspNetCore.Hosting.Internal.WebHost:Information: Request starting HTTP/1.1 POST https://localhost:44301/api/connect/microsoftcallback2 application/x-www-form-urlencoded 1771
Microsoft.AspNetCore.Hosting.Internal.WebHost:Information: Request starting HTTP/1.1 POST https://localhost:44301/api/connect/microsoftcallback2 application/x-www-form-urlencoded 1771
Microsoft.AspNetCore.Authentication.OpenIdConnect.OpenIdConnectHandler:Trace: Entering Microsoft.AspNetCore.Authentication.OpenIdConnect.OpenIdConnectHandler's HandleRemoteAuthenticateAsync.
Microsoft.AspNetCore.Authentication.OpenIdConnect.OpenIdConnectHandler:Trace: Entering Microsoft.AspNetCore.Authentication.OpenIdConnect.OpenIdConnectHandler's HandleRemoteAuthenticateAsync.
Microsoft.AspNetCore.Server.Kestrel:Debug: Connection id "0HLC9LOBLM019", Request id "0HLC9LOBLM019:00000004": started reading request body.
Microsoft.AspNetCore.Server.Kestrel:Debug: Connection id "0HLC9LOBLM019", Request id "0HLC9LOBLM019:00000004": started reading request body.
Microsoft.AspNetCore.Server.Kestrel:Debug: Connection id "0HLC9LOBLM019", Request id "0HLC9LOBLM019:00000004": done reading request body.
Microsoft.AspNetCore.Server.Kestrel:Debug: Connection id "0HLC9LOBLM019", Request id "0HLC9LOBLM019:00000004": done reading request body.
Microsoft.AspNetCore.DataProtection.KeyManagement.KeyRingBasedDataProtector:Trace: Performing unprotect operation to key {keyremoved} with purposes ('workspace', 'Microsoft.AspNetCore.Authentication.OpenIdConnect.OpenIdConnectHandler', 'aad', 'v1').
Microsoft.AspNetCore.DataProtection.KeyManagement.KeyRingBasedDataProtector:Trace: Performing unprotect operation to key {keyremoved} with purposes ('workspace', 'Microsoft.AspNetCore.Authentication.OpenIdConnect.OpenIdConnectHandler', 'aad', 'v1').
Microsoft.AspNetCore.Authentication.OpenIdConnect.OpenIdConnectHandler:Trace: MessageReceived: '?id_token={keyremoved}'.
Microsoft.AspNetCore.Authentication.OpenIdConnect.OpenIdConnectHandler:Trace: MessageReceived: '?id_token={keyremoved}'.
Microsoft.AspNetCore.Authentication.OpenIdConnect.OpenIdConnectHandler:Debug: Updating configuration
Microsoft.AspNetCore.Authentication.OpenIdConnect.OpenIdConnectHandler:Debug: Updating configuration
Microsoft.AspNetCore.Authentication.OpenIdConnect.OpenIdConnectHandler:Debug: Received 'id_token'
Microsoft.AspNetCore.Authentication.OpenIdConnect.OpenIdConnectHandler:Debug: Received 'id_token'
Microsoft.AspNetCore.DataProtection.KeyManagement.KeyRingBasedDataProtector:Trace: Performing unprotect operation to key {keyremoved} with purposes ('workspace', 'Microsoft.AspNetCore.Authentication.OpenIdConnect.OpenIdConnectHandler', 'System.String', 'aad', 'v1').
Microsoft.AspNetCore.DataProtection.KeyManagement.KeyRingBasedDataProtector:Trace: Performing unprotect operation to key {keyremoved} with purposes ('workspace', 'Microsoft.AspNetCore.Authentication.OpenIdConnect.OpenIdConnectHandler', 'System.String', 'aad', 'v1').
Microsoft.AspNetCore.DataProtection.KeyManagement.KeyRingBasedDataProtector:Trace: Performing protect operation to key {keyremoved} with purposes ('workspace', 'Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationMiddleware', 'Cookies', 'v2').
Microsoft.AspNetCore.DataProtection.KeyManagement.KeyRingBasedDataProtector:Trace: Performing protect operation to key {keyremoved} with purposes ('workspace', 'Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationMiddleware', 'Cookies', 'v2').
Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationHandler:Information: AuthenticationScheme: Cookies signed in.
Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationHandler:Information: AuthenticationScheme: Cookies signed in.
Microsoft.AspNetCore.Server.Kestrel:Debug: Connection id "0HLC9LOBLM019" completed keep alive response.
Microsoft.AspNetCore.Server.Kestrel:Debug: Connection id "0HLC9LOBLM019" completed keep alive response.
Microsoft.AspNetCore.Hosting.Internal.WebHost:Information: Request finished in 129.6921ms 302
Microsoft.AspNetCore.Hosting.Internal.WebHost:Information: Request finished in 129.6921ms 302
Microsoft.AspNetCore.Hosting.Internal.WebHost:Information: Request starting HTTP/1.1 GET https://localhost:44301/api/connect/authorize
Microsoft.AspNetCore.Hosting.Internal.WebHost:Information: Request starting HTTP/1.1 GET https://localhost:44301/api/connect/authorize
Microsoft.AspNetCore.DataProtection.KeyManagement.KeyRingBasedDataProtector:Trace: Performing unprotect operation to key {keyremoved} with purposes ('workspace', 'Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationMiddleware', 'Cookies', 'v2').
Microsoft.AspNetCore.DataProtection.KeyManagement.KeyRingBasedDataProtector:Trace: Performing unprotect operation to key {keyremoved} with purposes ('workspace', 'Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationMiddleware', 'Cookies', 'v2').
Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationHandler:Information: AuthenticationScheme: Cookies was successfully authenticated.
Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationHandler:Information: AuthenticationScheme: Cookies was successfully authenticated.
Microsoft.AspNetCore.Routing.Tree.TreeRouter:Debug: Request successfully matched the route with name 'authorize' and template 'api/connect/authorize'.
Microsoft.AspNetCore.Routing.Tree.TreeRouter:Debug: Request successfully matched the route with name 'authorize' and template 'api/connect/authorize'.
If you look at your log carefully, you'll see that it says this:
Request starting HTTP/1.1 POST https://localhost:44301/api/connect/microsoftcallback2
Since you specified the response should come as a POST with:
o.ResponseMode = "form_post";
You get the response as a POST in the callback you defined.
Now by default the OIDC handler will redirect you back to the path you were trying to access when the challenge was issued. You can see the 302 redirect in the log too.
In the case of an explicit login handler, that is not good.
You should define it yourself with:
return Challenge(new AuthenticationProperties
{
RedirectUri = "/"
}, "aad");
In this case the user will be redirected to the root of the app after the login is processed.

How to configure IdentityServerAuthenticationOptions.Authority to use wildcards

I successfully setup IdentityServer4 with ASP.NET Core.
As a default config I had this:
IdentityServerAuthenticationOptions options = new IdentityServerAuthenticationOptions()
{
Authority = "http://localhost:5000",
ScopeName = "scope",
ScopeSecret = "ScopeSecret",
AutomaticAuthenticate = true,
AutomaticChallenge = true,
RequireHttpsMetadata = false,
};
Now, using this guide I configured to be read from configuration files and so they can be any numbers in production.
For example if I setup API to be running at http://*:5000 then the client can connect to it via the service IP address like http://192.168.1.100:5000.
Once the client obtains the Bearer token and tries to use it, an Internal Server Error occures with this exception:
Unable to obtain configuration from:
'http://*:5000/.well-known/openid-configuration'.
---> System.IO.IOException: IDX10804: Unable to retrieve document from: 'http://*:5000/.well-known/openid-configuration'.
---> System.UriFormatException: Invalid URI: The hostname could not be parsed.
What is the correct way to configure IdS4 to have dynamic authority?
Update
It seems the problem is with Issuer, any idea on this?
Microsoft.IdentityModel.Tokens.SecurityTokenInvalidIssuerException:
IDX10205: Issuer validation failed. Issuer: 'http://192.168.1.100:5000'. Did not match: validationParameters.ValidIssuer: 'http://localhost:5000' or validationParameters.ValidIssuers: 'null'.
at Microsoft.IdentityModel.Tokens.Validators.ValidateIssuer(String issuer, SecurityToken securityToken, TokenValidationParameters validationParameters)
By a big surprise, all I needed, was to set a value (almost any value) for IssuerUri:
public IServiceProvider ConfigureServices(IServiceCollection services)
{
////...
var identiyBuilder = services.AddIdentityServer(options =>
{
options.RequireSsl = false;
options.IssuerUri = "MyCompany";
});
////...
}
Now, by the above config, I can use the service by any IP address.
I didn't find I could just put in MyCompany
But in my log files I had the following:
Bearer was not authenticated. Failure message: IDX10205: Issuer validation failed. Issuer: 'https://crm.example.com'. Did not match: validationParameters.ValidIssuer: 'MyCompany' or validationParameters.ValidIssuers: 'null'.
I don't quite know what 'issuer' means but I was able to just take 'https://crm.example.com' and get things working with this :
options.IssuerUri = "https://crm.example.com";

Resources