Session Id is changing every request in ASP.NET core 2.1 web api - angularjs

I am working on asp.net core web application. I am not much aware of session state. When i login the application i have got the session id and I have pushed some user data's into session using HttpContext.Session. That values are under current sessionid. And then i sent that sessionid to client(browser). where i having using angularjs.
Whenever i sent the request after login. i have sending the sessionid along with request in request header. But after request reached my backend(WebApi) where i have seen another sessionid in HttpContext.Session. but i have my sessionid which that having those session values. But using current HttpContext.Session's sessionid couldn't get those session values.
Whether i have to get those session values by my sessionid which was came along request header or have to change HttpContext.Session's sessionid or Won't allow to change HttpContext.Session's sessionid for every request. Everything i have mentioned is have tried but couldn't do anything.What else is there? Please someone help me!. I could seen lot of answers about it in online but everything is for .Net Framework not for ASP.Net core 2.1.
Here is my code,
I have set session values in my user controller. and after login i will fill data in my quote creation page and give submit. Meanwhile i have to get my session values(which i stored in user controller login method) in my quote controller create method. So current request sessionid is changed in Httpcontext(even i use IHttpContextAccessor).so couldn't get my session values
public class UserController : Controller {
public string Login(User objUser)
{...
HttpContext.Session.SetString("CompanyId", "1");
...}
}
public class QuoteController : Controller {
public string CreateQuote([FromBody]Quote objQuote)
{...
var companyId = HttpContext.Session.GetString("CompanyId");
...}
}

This should help. You can access season
by HttpContext.
Check this example how work with seasson string.
using Microsoft.AspNetCore.Http;
public class HomeController : Controller {
public IActionResult Index()
{
HttpContext.Session.SetString("Test", "Testing Session.");
return View();
}
public IActionResult About()
{
ViewBag.Message = HttpContext.Session.GetString("Test");
return View();
}
}

Related

How do I get the authentication URL and user ID using spring-cloud-azure-starter-active-directory?

How do I get the authentication URL and user ID using spring-cloud-azure-starter-active-directory?
https://learn.microsoft.com/en-us/azure/developer/java/spring-framework/configure-spring-boot-starter-java-app-with-azure-active-directory
I understand that AD authentication is possible with the source code of the following URL, but I would like to output the user and authentication URL in the log.
Auth URL
https://login.microsoftonline.com/{tenantID}/oauth2/v2.0/authorize?response_type=code&client_id={clinet_id}
Login UserId
user001#tenant.onmicrosoft.com
Redirects are unknown, but user IDs can be output in the following format
#GetMapping("Adimn")
public ModelAndView Adimn(HttpServletRequest request) {
try {
String userId = request.getUserPrincipal().getName();
log.info(userId);
return new ModelAndView("redirect:" + "/index");
}
Here is the sample code that can get redirect uri:
#GetMapping("azure/redirect-uri")
public String azureRedirectUri(#RegisteredOAuth2AuthorizedClient("azure") OAuth2AuthorizedClient azure) {
return azure.getClientRegistration().getRedirectUri();
}
Other information like "client-id" can also get by "azure.getClientRegistration.getXxx()".

Spring boot rest controller POST request always create new sessionid using #SessionScope?

I have searched a lot and found no suitable answers.
I have 2 post controller method as
#PostMapping("/saveStudentInfo")
public String saveStudentInfo(#RequestBody Students stud, HttpServletRequest request) {
students.setId(stud.getId());
students.setStudentName(stud.getStudentName());
students.setSchoolInfo(stud.getSchoolInfo());
System.out.println("Hello A= "+request.getSession(false).getId());
return "Saved Sucessfully";
}
#PostMapping("/saveSubjectInfo")
public String saveSubjectInfo(#RequestBody Subjects sub, HttpServletRequest request) {
subject.setSubjectName(sub.getSubjectName());
subject.setSubjectTeacher(sub.getSubjectTeacher());
System.out.println("Hello B= "+request.getSession(false).getId());
return "Saved Sucessfully Subject";
}
Now from postman these calls, works successfully, as same JSessionId is generated
==>Problem
When called from react app via browser on 2nd
saveSubjectInfo request I get different JSessionId, as in New-Session was Created
And I have annotated both Students and Subjects as #SessionScoped.
==>Requirement
Need to maintain session, and for that JSessionId needed to be same.
By default browsers support the GET method when API is hit directly from the browser URL bar. Also the POST and PUT method are usually supposed to make request along with some data to the serving method as the body so that it is not viewed in the browser request. For POST or PUT Postman app can be used.

Identity Server - Add custom parameters to the JSON response from the Token Endpoint

I’ve a requirement to add custom members in the token response of the Identity Server Token Endpoint.
Sample expected response:
{
"access_token": "XXXXXXXXXXXXXXX",
"token_type": "bearer",
"expires_in": 3600,
"scope": "patient/Observation.read patient/Patient.read",
"patient": 123,
"refresh_token":"XXXXXXXXXXXXXXXXX"
}
I would like to add the scope, patient parameter in the response, even though it's present in the Access Token.
Any guidance on this would be really helpful!
Not possible with out of the box configuration because of the static nature of TokenResponse model.
Having said that, IdentityServer4 is extremely extensible so you could technically create your own implementation of ITokenResponseGenerator and your own custom model for TokenResponse in order to achieve this behaviour.
Would not recommend this, however, because it seems like you are trying to solve the shortcoming of some other system not being able to process a pretty standard JWT.
For Identity Server 4, you can add a custom parameter in the token response by implementing the ICustomTokenRequestValidator interface.
public class CustomTokenRequestValidator : ICustomTokenRequestValidator
{
public Task ValidateAsync(CustomTokenRequestValidationContext context)
{
context.Result.CustomResponse =
new Dictionary<string, object> {{ "patient", "alice"}};
return Task.CompletedTask;
}
public CustomTokenRequestValidator()
{
}
}
Also do not forget to register the dependency in the configureServices method in startup. You can append .AddCustomTokenRequestValidator<>({pass-in-name-of-class-implementing}) after adding the IdentityServer service.
I was able to get the Identity Server 3 to provide a customized Token Response by implementing the ICustomTokenResponseGenerator Interface and adding the required parameters in the Custom section of the tokenResponse.
Steps:
Implement the Interface
Register the Interface in the factory
This fix worked for me and i'm able to get the custom items in the token response.
//Interface Implementation
public class CustomTokenResponseGeneratorService: ICustomTokenResponseGenerator
{
protected ITokenService _tokenService;
public CustomTokenResponseGeneratorService(ITokenService tokenService)
{
_tokenService = tokenService;
}
public Task<TokenResponse> GenerateAsync(ValidatedTokenRequest request, TokenResponse response)
{
var patientID = 123;
response.Custom.Add("patient" , patientID);
response.Custom.Add("scope" , request.AuthorizationCode.Scopes.ToArray());
response.Custom.Add("need_patient_banner" , "false");
response.Custom.Add("encounter" , patientID);
response.Custom.Add("client_id" , request.AuthorizationCode.ClientId);
response.Custom.Add("smart_style_url" , "UNK");
return Task.FromResult(response);
}
}
Step2: Register the CustomTokenResponseGenerator in the Identity Server factory
//Token Service
factory.CustomTokenResponseGenerator = new Registration<ICustomTokenResponseGenerator, CustomTokenResponseGeneratorService>();
Reference: Interface Detail for Identity Server 3

Login page customized depending on client

I would like to make the login page know which client requested the login in order to display some client-specific branding: Otherwise the user may be confused as to why he's redirected to this foreign login page on a different domain. A client logo will help reassure him that he's still on the right track.
What would be the most reasonable approach to get at that information?
EDIT: Note that by "client" I'm referring to the client web applications on whose behalf the authentication happens - not the user's browser. All clients are under my control and so I'm using only the implicit workflow.
To make this even more clear: I have client web apps A and B, plus the identity server I. When the user comes to I on behalf of B, the B logo should appear as we're no longer on B's domain and that may be confusing without at least showing a B-related branding.
Some Theory
The easiest way to get the ClientId from IdSrv 4 is through a service called IIdentityServerInteractionService which is used in the Account Controller to get the AuthorizationContext. And then follow that up with the IClientStore service that allows you to get the client details given the ClientId. After you get these details then its only a matter of sending that info to the view for layout. The client model in IdSrv 4 has a LogoUri property that you can utilize to show an image at login per client.
Simple Example
// GET: /Account/Login
[HttpGet]
[AllowAnonymous]
public async Task<IActionResult> Login(string returnUrl = null)
{
var context = await _interaction.GetAuthorizationContextAsync(returnUrl);
if (context?.IdP != null)
// if IdP is passed, then bypass showing the login screen
return ExternalLogin(context.IdP, returnUrl);
if(context != null)
{
var currentClient = await _clientStore.FindClientByIdAsync(context.ClientId);
if (currentClient != null)
{
ViewData["ClientName"] = currentClient.ClientName;
ViewData["LogoUri"] = currentClient.LogoUri;
}
}
ViewData["ReturnUrl"] = returnUrl;
return View();
}

Spring Social The OAuth2 'state' parameter is missing or doesn't match? [duplicate]

I am trying to use Spring Social on my application and I noticed while debugging that the original 'OAuth2' state parameter is always null on my app.
See Spring Social source code for org.springframework.social.connect.web.ConnectSupport below:
private void verifyStateParameter(NativeWebRequest request) {
String state = request.getParameter("state");
String originalState = extractCachedOAuth2State(request);//Always null...
if (state == null || !state.equals(originalState)) {
throw new IllegalStateException("The OAuth2 'state' parameter is missing or doesn't match.");
}
}
private String extractCachedOAuth2State(WebRequest request) {
String state = (String) sessionStrategy.getAttribute(request, OAUTH2_STATE_ATTRIBUTE);
sessionStrategy.removeAttribute(request, OAUTH2_STATE_ATTRIBUTE);
return state;
}
Can anyone please help?
edit: I do see the state parameter being passed back by facebook:
Request URL:https://www.facebook.com/v2.5/dialog/oauth?client_id=414113641982912&response_type=code&redirect_uri=http%3A%2F%2Flocalhost%3A8080%2Fconnect%2Ffacebook&scope=public_profile&state=0b7a97b5-b8d1-4f97-9b60-e3242c9c7eb9
Request Method:GET
Status Code:302
Remote Address:179.60.192.36:443
edit 2: By the way, the exception I get is the following:
Exception while handling OAuth2 callback (The OAuth2 'state' parameter is missing or doesn't match.). Redirecting to facebook connection status page.
It turned out that the issue was caused by the fact that I was relying on headers - as opposed to cookies - to manage the session.
By commenting out the following spring session configuration bean:
#Bean
public HttpSessionStrategy sessionStrategy(){
return new HeaderHttpSessionStrategy();
}
The oauth2 state parameter issue was sorted.
P.S. Now I have got to find a way to get Spring Social to work with my current configuration of Spring Session...
Edit: I managed to keep the HeaderHttpSessionStrategy (on the spring session side) and get it to work by implementing my own SessionStrategy (on the spring social side) as follows:
public class CustomSessionStrategy implements SessionStrategy {
public void setAttribute(RequestAttributes request, String name, Object value) {
request.setAttribute(name, value, RequestAttributes.SCOPE_SESSION);
}
public Object getAttribute(RequestAttributes request, String name) {
ServletWebRequest servletWebRequest = (ServletWebRequest) request;
return servletWebRequest.getParameter(name);
}
public void removeAttribute(RequestAttributes request, String name) {
request.removeAttribute(name, RequestAttributes.SCOPE_SESSION);
}
}
Try this work around and see if that works for you:
To my surprise I opened application in a 'incognito' browser and everything worked. Just like that. I think before something got cached and was causing the issue.
I ran into this issue today, My application was working perfectly fine. I just took a break for few hours and when I ran it again it started complaining about 'The OAuth2 'state' parameter is missing or doesn't match.'
The state param is first put into the session then the request goes out to facebook and the request comes back with the same state param but when spring is looking for session object to get the state param, it is not finding the session. I think it is not finding the session because when the request comes back it thinks that it is a different client (or host), even though the old HttpSession object still exists. The container maintains a HttpSession per client.
What you're getting from Facebook is not a request attribute , it's a request parameter.
You should get it by something like:
request.getParameter("state")

Resources