Symfony 4 - api platform - jwt - Custom Operations and Controllers - http-status-code-404

I am working on a project using Symfony 4.1 - api platform -jwt
I created a custom operation in the Entity
// App\Entity
/**
* #ApiResource(
* itemOperations={
* "get",
* "put",
* "delete",
* "request"={
* "method"="POST",
* "path"="/event/request",
* "controller"=ReservationController::class
* }
* }
* )
* #ORM\Entity(repositoryClass="App\Repository\EventRepository")
*/
I created my method in the approprite controller
public function __invoke(Event $data): ?Event
{
$eventType = $this->getDoctrine()->getRepository(EventType::class)->findRequestType();
$user = $this->getDoctrine()->getRepository(User::class)->find(1);
$data->setEventType($eventType);
$data->setUser($user);
return $data;
}
Before integrating JWT It was working perfekly but now when i try to acces the ressource i get this
2018-07-03T11:19:44+00:00 [info] Matched route "api_events_request_item".
2018-07-03T11:19:44+00:00 [debug] Checking for guard authentication credentials.
2018-07-03T11:19:44+00:00 [debug] Calling getCredentials() on guard configurator.
2018-07-03T11:19:44+00:00 [debug] Passing guard token information to the GuardAuthenticationProvider
2018-07-03T11:19:44+00:00 [debug] SELECT t0.id AS id_1, t0.email AS email_2, t0.password AS password_3, t0.is_active AS is_active_4, t0.role_id AS role_id_5 FROM user t0 WHERE t0.email = ? LIMIT 1
2018-07-03T11:19:44+00:00 [info] User Deprecated: Calling Symfony\Component\Security\Core\User\UserChecker::checkPreAuth with an AdvancedUserInterface is deprecated since Symfony 4.1. Create a custom user checker if you wish to keep this functionality.
2018-07-03T11:19:44+00:00 [info] User Deprecated: Calling Symfony\Component\Security\Core\User\UserChecker::checkPostAuth with an AdvancedUserInterface is deprecated since Symfony 4.1. Create a custom user checker if you wish to keep this functionality.
2018-07-03T11:19:44+00:00 [info] Guard authentication successful!
2018-07-03T11:19:44+00:00 [debug] Guard authenticator set no success response: request continues.
2018-07-03T11:19:44+00:00 [debug] Remember me skipped: it is not configured for the firewall.
2018-07-03T11:19:44+00:00 [error] Uncaught PHP Exception Symfony\Component\HttpKernel\Exception\NotFoundHttpException: "Not Found" at /Users/simonackermann/Sites/courses/symfony/champeryNb/vendor/api-platform/core/src/EventListener/ReadListener.php line 103
[Tue Jul 3 13:19:44 2018] 127.0.0.1:56389 [404]: /api/event/request
Here is what i get with the debug:router command
default ANY ANY ANY /
test ANY ANY ANY /test
images ANY ANY ANY /images/{name}
api_entrypoint ANY ANY ANY /api/{index}.{_format}
api_doc ANY ANY ANY /api/docs.{_format}
api_jsonld_context ANY ANY ANY /api/contexts/{shortName}.{_format}
api_events_get_collection GET ANY ANY /api/events.{_format}
api_events_post_collection POST ANY ANY /api/events.{_format}
api_events_get_item GET ANY ANY /api/events/{id}.{_format}
api_events_put_item PUT ANY ANY /api/events/{id}.{_format}
api_events_delete_item DELETE ANY ANY /api/events/{id}.{_format}
api_events_request_item POST ANY ANY /api/event/request
api_event_types_get_collection GET ANY ANY /api/event_types.{_format}
api_event_types_get_item GET ANY ANY /api/event_types/{id}.{_format}
api_places_get_collection GET ANY ANY /api/places.{_format}
api_places_post_collection POST ANY ANY /api/places.{_format}
api_places_get_item GET ANY ANY /api/places/{id}.{_format}
api_places_delete_item DELETE ANY ANY /api/places/{id}.{_format}
api_places_put_item PUT ANY ANY /api/places/{id}.{_format}
api_users_get_collection GET ANY ANY /api/users.{_format}
api_users_post_collection POST ANY ANY /api/users.{_format}
api_users_get_item GET ANY ANY /api/users/{id}.{_format}
api_users_delete_item DELETE ANY ANY /api/users/{id}.{_format}
api_users_put_item PUT ANY ANY /api/users/{id}.{_format}
api_users_name_item GET ANY ANY /api/user/{email}
_twig_error_test ANY ANY ANY /_error/{code}.{_format}
api_login_check ANY ANY ANY /api/login_check
Any ideas ?
Thank in advance

Related

Fetch response is 401 Unauthenticated React Frontend Spring Boot Backend with Spring Security

I have created this Spring Boot backend for a university assignment, which requires authorization/authentication. I have made the api work fine standalone , and the calls go through with correct authorization/authentication through Postman requests. But when i try to call the api from a react app, it always returns unauthanticaded 401.
I removed the security completely from the api, just to see if it would work, it does , the api calls return the results as expected (without Spring Security). But when i re-add Spring security only the Postman requests work.
Javascript Fetch requests don't work (Returning 401)
var myHeaders = new Headers();
myHeaders.append("Authorization", "Basic " + btoa("root:root"));
const res = await fetch("http://localhost:7979/api/users", myHeaders)
console.log(res);
const data = await res.json();
console.log(data);
Console Output:
and wget/curl requests don't work with both outputing Connection Refused
Successful Postman request:
Here is the security config from the spring boot backend:
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true)
public class SecurityConfig
{
#Resource
private DataSource dataSource;
#Autowired
private UserDetailsService userDetailsService;
#Bean
SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http) throws Exception
{
http.authorizeHttpRequests(auth -> auth
.requestMatchers(HttpMethod.POST , "/api/users").permitAll()
.requestMatchers( "/api/authority").hasAuthority(Constants.ADMIN)
.anyRequest().authenticated()
)
.formLogin().permitAll()
.and().logout().permitAll()
.and().userDetailsService(userDetailsService)
.cors()
.and().csrf().disable()
.httpBasic();
http.headers().frameOptions().sameOrigin();
return http.build();
}
#Bean
public PasswordEncoder passwordEncoder()
{
return new BCryptPasswordEncoder();
}
}
the spring backend is run on localhost:7979
and the react app is run on localhost:3000
also, maybe important, i am on windows and run the React app on Windows Subsystem for Linux but the spring app but the default runner of Intellij.
I'm quite stumped and i can't figure out how to debug Spring Security, everyone just says enable logging which i have done but the Spring Security Logging offers 0 useful info (unless i don't understand what I'm seeing)
Update:
So wsl is a bit of a problem, i have this script on .zshrc on wsl that get the ip of the windows host (i don't know how it works, a person here told me to add it and it worked)
script:
export winhost=$(cat /etc/resolv.conf | grep nameserver | awk '{ print $2 }')
if [ ! -n "$(grep -P "[[:space:]]winhost" /etc/hosts)" ]; then
printf "%s\t%s\n" "$winhost" "winhost" | sudo tee -a "/etc/hosts"
fi
so now if i use the winhost instead of localhost wget/curl works fine
Successful wget request:
Successful curl request:
I tried doing the same on the React app but it came up with a new error
I also tried running the React app on windows instead of wsl , but i had the same result:
Update Update:
I found a way to activate logging on spring security, here are the log for a successful request:
2023-01-26T02:00:33.435+02:00 DEBUG 17932 --- [nio-7979-exec-9] o.s.security.web.FilterChainProxy : Securing GET /api/users
Hibernate:
select
u1_0.`id`,
u1_0.`AFM`,
u1_0.`address`,
u1_0.`email`,
u1_0.`enabled`,
u1_0.`password`,
u1_0.`phone_number`,
u1_0.`username`
from
`users` u1_0
where
u1_0.`username`=?
Hibernate:
select
a1_0.`user_id`,
a1_1.`id`,
a1_1.`authority`
from
`user_authorities` a1_0
join
`authorities` a1_1
on a1_1.`id`=a1_0.`authority_id`
where
a1_0.`user_id`=?
Hibernate:
select
u1_0.`authority_id`,
u1_1.`id`,
u1_1.`AFM`,
u1_1.`address`,
u1_1.`email`,
u1_1.`enabled`,
u1_1.`password`,
u1_1.`phone_number`,
u1_1.`username`
from
`user_authorities` u1_0
join
`users` u1_1
on u1_1.`id`=u1_0.`user_id`
where
u1_0.`authority_id`=?
2023-01-26T02:00:33.508+02:00 DEBUG 17932 --- [nio-7979-exec-9] o.s.s.a.dao.DaoAuthenticationProvider : Authenticated user
2023-01-26T02:00:33.508+02:00 DEBUG 17932 --- [nio-7979-exec-9] o.s.s.w.a.www.BasicAuthenticationFilter : Set SecurityContextHolder to UsernamePasswordAuthenticationToken [Principal=gr.hua.dit.it22023_it22026.models.SecurityUserDetails#2e536336, Credentials=[PROTECTED], Authenticated=true, Details=WebAuthenticationDetails [RemoteIpAddress=172.20.196.70, SessionId=null], Granted Authorities=[ADMIN]]
2023-01-26T02:00:33.509+02:00 DEBUG 17932 --- [nio-7979-exec-9] o.s.security.web.FilterChainProxy : Secured GET /api/users
Hibernate:
select
u1_0.`id`,
u1_0.`AFM`,
u1_0.`address`,
u1_0.`email`,
u1_0.`enabled`,
u1_0.`password`,
u1_0.`phone_number`,
u1_0.`username`
from
`users` u1_0
Hibernate:
select
a1_0.`user_id`,
a1_1.`id`,
a1_1.`authority`
from
`user_authorities` a1_0
join
`authorities` a1_1
on a1_1.`id`=a1_0.`authority_id`
where
a1_0.`user_id`=?
Hibernate:
select
u1_0.`authority_id`,
u1_1.`id`,
u1_1.`AFM`,
u1_1.`address`,
u1_1.`email`,
u1_1.`enabled`,
u1_1.`password`,
u1_1.`phone_number`,
u1_1.`username`
from
`user_authorities` u1_0
join
`users` u1_1
on u1_1.`id`=u1_0.`user_id`
where
u1_0.`authority_id`=?
Hibernate:
select
a1_0.`user_id`,
a1_1.`id`,
a1_1.`authority`
from
`user_authorities` a1_0
join
`authorities` a1_1
on a1_1.`id`=a1_0.`authority_id`
where
a1_0.`user_id`=?
Hibernate:
select
a1_0.`user_id`,
a1_1.`id`,
a1_1.`authority`
from
`user_authorities` a1_0
join
`authorities` a1_1
on a1_1.`id`=a1_0.`authority_id`
where
a1_0.`user_id`=?
Hibernate:
select
u1_0.`authority_id`,
u1_1.`id`,
u1_1.`AFM`,
u1_1.`address`,
u1_1.`email`,
u1_1.`enabled`,
u1_1.`password`,
u1_1.`phone_number`,
u1_1.`username`
from
`user_authorities` u1_0
join
`users` u1_1
on u1_1.`id`=u1_0.`user_id`
where
u1_0.`authority_id`=?
And here are the logs for a failed request:
2023-01-26T02:02:23.041+02:00 DEBUG 17932 --- [nio-7979-exec-1] o.s.security.web.FilterChainProxy : Securing GET /api/users
2023-01-26T02:02:23.042+02:00 DEBUG 17932 --- [nio-7979-exec-1] o.s.s.w.a.AnonymousAuthenticationFilter : Set SecurityContextHolder to anonymous SecurityContext
2023-01-26T02:02:23.042+02:00 DEBUG 17932 --- [nio-7979-exec-1] s.w.a.DelegatingAuthenticationEntryPoint : Trying to match using RequestHeaderRequestMatcher [expectedHeaderName=X-Requested-With, expectedHeaderValue=XMLHttpRequest]
2023-01-26T02:02:23.042+02:00 DEBUG 17932 --- [nio-7979-exec-1] s.w.a.DelegatingAuthenticationEntryPoint : No match found. Using default entry point org.springframework.security.web.authentication.www.BasicAuthenticationEntryPoint#456e1a23
2023-01-26T02:02:23.042+02:00 DEBUG 17932 --- [nio-7979-exec-1] o.s.security.web.FilterChainProxy : Securing GET /error
2023-01-26T02:02:23.042+02:00 DEBUG 17932 --- [nio-7979-exec-1] o.s.s.w.a.AnonymousAuthenticationFilter : Set SecurityContextHolder to anonymous SecurityContext
2023-01-26T02:02:23.042+02:00 DEBUG 17932 --- [nio-7979-exec-1] s.w.a.DelegatingAuthenticationEntryPoint : Trying to match using RequestHeaderRequestMatcher [expectedHeaderName=X-Requested-With, expectedHeaderValue=XMLHttpRequest]
2023-01-26T02:02:23.042+02:00 DEBUG 17932 --- [nio-7979-exec-1] s.w.a.DelegatingAuthenticationEntryPoint : No match found. Using default entry point org.springframework.security.web.authentication.www.BasicAuthenticationEntryPoint#456e1a23
I don't understand the fail request logs at all, can any spring boot security expert help?
issue was in javascript
const res = await fetch("http://localhost:7979/api/users", headers);
should have been
const res = await fetch("http://localhost:7979/api/users", {headers:headers})

com.ctc.wstx.exc.WstxParsingException: Unexpected close tag </span>; expected </br>

I created the stub classes using CXF wsdl2java tool.
I am using Apache CXF library, with JCIFS. I validated the WSDL file itself through couple tools, it is good. Here is the code. It looks like some setting I must do.
//JCIFS Authentication related code
jcifs.Config.setProperty("jcifs.smb.client.domain", "NTS");
jcifs.Config.setProperty("jcifs.netbios.wins", "ecmchat.mark.gov");
jcifs.Config.setProperty("jcifs.smb.client.soTimeout", "300000"); // 5 minutes
jcifs.Config.setProperty("jcifs.netbios.cachePolicy", "1200"); // 20 minutes
jcifs.Config.setProperty("jcifs.smb.client.username", "user");
jcifs.Config.setProperty("jcifs.smb.client.password", "password");
//Register the jcifs URL handler to enable NTLM
jcifs.Config.registerSmbURLHandler();
//WSDL and Client settings
URL wsdlURL = BF.WSDL_LOCATION;
if (args.length > 0 && args[0] != null && !"".equals(args[0])) {
File wsdlFile = new File(args[0]);
try {
if (wsdlFile.exists()) {
wsdlURL = wsdlFile.toURI().toURL();
} else {
wsdlURL = new URL(args[0]);
}
} catch (MalformedURLException e) {
e.printStackTrace();
}
}
BF ss = new BF(wsdlURL, SERVICE_NAME);
BFSoap port = ss.getBFSoap12();
Client client = ClientProxy.getClient(port);
HTTPConduit http = (HTTPConduit) client.getConduit();
HTTPClientPolicy httpClientPolicy = new HTTPClientPolicy();
httpClientPolicy.setConnectionTimeout(36000);
httpClientPolicy.setAllowChunking(false);
httpClientPolicy.setReceiveTimeout(32000);
http.setClient(httpClientPolicy);
// Calling the method
System.out.println("Invoking testMethod...");
String _testMethod__return = port.testMethod();
System.out.println("testMethod.result=" + _testMethod__return);
I am getting the following exception
Caused by: com.ctc.wstx.exc.WstxParsingException: Unexpected close tag </span>; expected </br>.
at [row,col,system-id]: [59,22,"https://ecmchat.mark.gov/BF/BF.asmx"]
at com.ctc.wstx.sr.StreamScanner.constructWfcException(StreamScanner.java:621)
at com.ctc.wstx.sr.StreamScanner.throwParseError(StreamScanner.java:491)
at com.ctc.wstx.sr.StreamScanner.throwParseError(StreamScanner.java:475)
at com.ctc.wstx.sr.BasicStreamReader.reportWrongEndElem(BasicStreamReader.java:3365)
at com.ctc.wstx.sr.BasicStreamReader.readEndElem(BasicStreamReader.java:3292)
at com.ctc.wstx.sr.BasicStreamReader.nextFromTree(BasicStreamReader.java:2911)
at com.ctc.wstx.sr.BasicStreamReader.next(BasicStreamReader.java:1123)
at org.apache.cxf.staxutils.StaxUtils.readDocElements(StaxUtils.java:1361)
at org.apache.cxf.staxutils.StaxUtils.readDocElements(StaxUtils.java:1255)
at org.apache.cxf.staxutils.StaxUtils.read(StaxUtils.java:1183)
at org.apache.cxf.wsdl11.WSDLManagerImpl.loadDefinition(WSDLManagerImpl.java:235)
... 9 more
If I comment out the JCIFS NTLM authentication code, I get a HTTP 401 error. Therefore, I believe, at least it is passing some kind of authorization step.
And, if I use local WSDL in place of remote URL WSDL, then I get a different error like "method not implemented" on the call to the method. May be this is due to me not using the local WSDL correctly. I do not even know if we can use the local WSDL reference for remote service.
Then, I created a SoapUI dummy service with this WSDL, and the same code (but without the JCIFS authentication code) works good, and successfully calls the methods.
It appears to me that I must add some more appropriate settings in the configuration related code.
Am I right, and are you aware of any, for NTLM authentication and Apache CXF?
But parsing error is confusing???
I do not know if this is related.
My original WSDL URL that I gave was this.
https://ecmchat.mark.gov/BF/BF.asmx
I added a ?wsdl like below
https://ecmchat.mark.gov/BF/BF.asmx?wsdl
Then I am getting a different error.
I wonder why it is working if I access my local SoapUI version of the same WSDL service, but not for the remote one.
Invoking testMethod...
Jan 07, 2020 10:47:25 AM org.apache.cxf.phase.PhaseInterceptorChain doDefaultLogging
WARNING: Interceptor for {https://ecmchat.mark.gov}BF#{https://ecmchat.mark.gov}testMethod has thrown exception, unwinding now
java.lang.UnsupportedOperationException: Method not implemented.
at java.net.URLStreamHandler.openConnection(URLStreamHandler.java:96)
at java.net.URL.openConnection(URL.java:1028)
at org.apache.cxf.transport.https.HttpsURLConnectionFactory.createConnection(HttpsURLConnectionFactory.java:92)
at org.apache.cxf.transport.http.URLConnectionHTTPConduit.createConnection(URLConnectionHTTPConduit.java:121)
at org.apache.cxf.transport.http.URLConnectionHTTPConduit.setupConnection(URLConnectionHTTPConduit.java:125)
at org.apache.cxf.transport.http.HTTPConduit.prepare(HTTPConduit.java:505)
at org.apache.cxf.interceptor.MessageSenderInterceptor.handleMessage(MessageSenderInterceptor.java:47)
at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:308)
at org.apache.cxf.endpoint.ClientImpl.doInvoke(ClientImpl.java:530)
at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:441)
at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:356)
at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:314)
at org.apache.cxf.frontend.ClientProxy.invokeSync(ClientProxy.java:96)
at org.apache.cxf.jaxws.JaxWsClientProxy.invoke(JaxWsClientProxy.java:140)
at com.sun.proxy.$Proxy33.testMethod(Unknown Source)
at edison.learn.BFSoap_BFSoap12_Client.main(BFSoap_BFSoap12_Client.java:90)
Exception in thread "main" javax.xml.ws.soap.SOAPFaultException: Method not implemented.
at org.apache.cxf.jaxws.JaxWsClientProxy.mapException(JaxWsClientProxy.java:195)
at org.apache.cxf.jaxws.JaxWsClientProxy.invoke(JaxWsClientProxy.java:145)
at com.sun.proxy.$Proxy33.testMethod(Unknown Source)
at edison.learn.BFSoap_BFSoap12_Client.main(BFSoap_BFSoap12_Client.java:90)
Caused by: java.lang.UnsupportedOperationException: Method not implemented.
at java.net.URLStreamHandler.openConnection(URLStreamHandler.java:96)
at java.net.URL.openConnection(URL.java:1028)
at org.apache.cxf.transport.https.HttpsURLConnectionFactory.createConnection(HttpsURLConnectionFactory.java:92)
at org.apache.cxf.transport.http.URLConnectionHTTPConduit.createConnection(URLConnectionHTTPConduit.java:121)
at org.apache.cxf.transport.http.URLConnectionHTTPConduit.setupConnection(URLConnectionHTTPConduit.java:125)
at org.apache.cxf.transport.http.HTTPConduit.prepare(HTTPConduit.java:505)
at org.apache.cxf.interceptor.MessageSenderInterceptor.handleMessage(MessageSenderInterceptor.java:47)
at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:308)
at org.apache.cxf.endpoint.ClientImpl.doInvoke(ClientImpl.java:530)
at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:441)
at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:356)
at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:314)
at org.apache.cxf.frontend.ClientProxy.invokeSync(ClientProxy.java:96)
at org.apache.cxf.jaxws.JaxWsClientProxy.invoke(JaxWsClientProxy.java:140)
... 2 more

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;
}
});

Spring Integration : Connection Failure vs Error response code retryadvice()

i'm sending a request to a web service through Http.outboundGateway, and i 'm expecting to have a response with on of these three cases
1- Response success [Ok]
2- Connection Failure [ need to Retry]
3- response return with error code, ex. 400 [save it]
i used advice() after poller to reattempt the Connection Failure, but The problem is that the Error Message exception was thrown in both cases ( Connection Failure , response error code ), so the retry was called for both cases
How could i differentiate between of them and only use the Retry advice for the Connection Failure
.handle(
Http.outboundGateway(propertiesConfig.getURL())
......
, endpoint -> endpoint
.poller(Pollers.fixedDelay(delayBetweenRequests)
.errorChannel("errorChannel")
.taskExecutor(executor)
.receiveTimeout(timeoutDelay)
)
.advice(retryAdvice)
)
Retry advice creation bean
#Bean("retryAdvice")
public RequestHandlerRetryAdvice maspRetryAdvice() {
Request
HandlerRetryAdvice retryAdvice = new RequestHandlerRetryAdvice();
RetryTemplate retryTemplate = new RetryTemplate();
FixedBackOffPolicy policy = new FixedBackOffPolicy();
policy.setBackOffPeriod(interval);
retryTemplate.setBackOffPolicy(policy);
SimpleRetryPolicy retryPolicy = new SimpleRetryPolicy();
retryPolicy.setMaxAttempts(nRetry);
retryTemplate.setRetryPolicy(retryPolicy);
retryAdvice.setRetryTemplate(retryTemplate);
ErrorMessageSendingRecoverer recover = new
ErrorMessageSendingRecoverer(aggregatorChannel());
handlerRetryAdvice.setRecoveryCallback(recover);
return retryAdvice;
}
I was facing almost the exact same challenge.
For Connection time out this link provides the exact solution: [Configure error handling and retry for Http.outboundGateway spring dsl
] [1]: Configure error handling and retry for Http.outboundGateway spring dsl
....
.handle(Http.outboundGateway(
parser().parseExpression("headers[url]"))
.httpMethod(HttpMethod.POST)
.headerMapper(headerMapper())
.expectedResponseType(String.class)
.requestFactory(clientHttpRequestFactory())
// The inner writer method is doing nothing, just place holder for future usage,
// errorHandler is necessary to capture :
// e.g. org.springframework.web.client.HttpClientErrorException: 403 Forbidden
.errorHandler(responseErrorFileWriter())
, (Consumer<GenericEndpointSpec>)e -> e.advice(retryAdvice()))

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.

Resources