I want to do a simple login request where I send the username and the password to the backend and try to get an access token. When I test the request from postman it works just fine.
What could the problem be?
The login methode from the front-end:
login(username: string, password: string) {
return this.http.post(
'http://localhost:8080/login',
{
username: username,
password: password
}
)
.pipe(
catchError(this.handleError)
);
}
UPDATE:
login(username: string, password: string) {
const header = new HttpHeaders()
.set('content-type', 'application/json')
const params = new HttpParams()
.set('print', 'pretty')
.set('username', username)
.set('password', password)
return this.http.post(
'http://localhost:8080/login',
{},{
headers : header,
params: params,
}
)
.pipe(
catchError(this.handleError)
);
}
The login method in the backend:
#Slf4j
#CrossOrigin
public class CustomAuthorizationFilter extends OncePerRequestFilter {
#Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
if (request.getServletPath().equals("/login") || request.getServletPath().equals("/token/refresh")) {
filterChain.doFilter(request, response);
} else {
String authorizationHeader = request.getHeader(AUTHORIZATION);
if (authorizationHeader != null && authorizationHeader.startsWith("Bearer ")) {
try {
String token = authorizationHeader.substring("Bearer ".length());
Algorithm algorithm = Algorithm.HMAC256("secret".getBytes());
JWTVerifier verifier = JWT.require(algorithm).build();
DecodedJWT decodedJWT = verifier.verify(token);
String username = decodedJWT.getSubject();
String[] roles = decodedJWT.getClaim("roles").asArray(String.class);
Collection<SimpleGrantedAuthority> authorities = new ArrayList<>();
stream(roles).forEach(role-> {
authorities.add(new SimpleGrantedAuthority(role));
});
UsernamePasswordAuthenticationToken authenticationToken =
new UsernamePasswordAuthenticationToken(username, null, authorities);
SecurityContextHolder.getContext().setAuthentication(authenticationToken);
filterChain.doFilter(request, response);
} catch (Exception e) {
log.error("Error# logging in: {}", e.getMessage());
response.setHeader("error", e.getMessage());
Map<String, String> error = new HashMap<>();
error.put("error_message", e.getMessage());
response.setContentType(APPLICATION_JSON_VALUE);
new ObjectMapper().writeValue(response.getOutputStream(), error);
}
} else {
filterChain.doFilter(request, response);
}
}
}
}
and then: (my request is not reaching this step).
#Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
String username = request.getParameter("username");
String password = request.getParameter("password");
log.info("Username is: {}", username); log.info("Password is: {}", password);
UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(username, password);
return authenticationManager.authenticate(authenticationToken);
}
#Override
protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authentication) throws IOException, ServletException {
User user = (User)authentication.getPrincipal();
//TODO:hide it.
Algorithm algorithm = Algorithm.HMAC256("secret".getBytes());
String access_token = JWT.create()
.withSubject(user.getUsername())
.withExpiresAt(new Date(System.currentTimeMillis() + 60 * 60 * 1000))
.withIssuer(request.getRequestURL().toString())
.withClaim("roles", user.getAuthorities().stream().map(GrantedAuthority::getAuthority).collect(Collectors.toList()))
.sign(algorithm);
String refresh_token = JWT.create()
.withSubject(user.getUsername())
.withExpiresAt(new Date(System.currentTimeMillis() + 300 * 60 * 1000))
.withIssuer(request.getRequestURL().toString())
.sign(algorithm);
response.setHeader("access_token", access_token);
response.setHeader("refresh_token", refresh_token);
Map<String, String> tokens = new HashMap<>();
tokens.put("access_token", access_token);
tokens.put("refresh_token", refresh_token);
response.setContentType(APPLICATION_JSON_VALUE);
new ObjectMapper().writeValue(response.getOutputStream(), tokens);
}
Related
I configured Vaadin 23 application with Spring Security and Keyclock. Everything works fine except the users are not redirect to the page where they initiated the login process. The user is always redirected to the home page.
This is a SecurityConfiguration:
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(securedEnabled = true)
public class SecurityConfiguration extends VaadinWebSecurity {
private final ClientRegistrationRepository clientRegistrationRepository;
private final GrantedAuthoritiesMapper authoritiesMapper;
private final ProfileService profileService;
private String jwtAuthSecret;
SecurityConfiguration(#Value("${spring.security.jwt.auth.secret}") String jwtAuthSecret, ClientRegistrationRepository clientRegistrationRepository,
GrantedAuthoritiesMapper authoritiesMapper, ProfileService profileService) {
this.jwtAuthSecret = jwtAuthSecret;
this.clientRegistrationRepository = clientRegistrationRepository;
this.authoritiesMapper = authoritiesMapper;
this.profileService = profileService;
SecurityContextHolder.setStrategyName(VaadinAwareSecurityContextHolderStrategy.class.getName());
}
#Override
protected void configure(HttpSecurity http) throws Exception {
super.configure(http);
http
// Enable OAuth2 login
.oauth2Login(oauth2Login ->
oauth2Login
.clientRegistrationRepository(clientRegistrationRepository)
.userInfoEndpoint(userInfoEndpoint ->
userInfoEndpoint
.userAuthoritiesMapper(authoritiesMapper)
)
.loginPage("/login")
.successHandler(new KeycloakVaadinAuthenticationSuccessHandler(profileService))
)
// Configure logout
.logout(logout ->
logout
.logoutSuccessHandler(logoutSuccessHandler())
.logoutRequestMatcher(new AntPathRequestMatcher("/logout", "GET"))
).sessionManagement(sessionManagement -> {
sessionManagement.sessionConcurrency(concurrency -> {
concurrency.maximumSessions(-1);
concurrency.sessionRegistry(sessionRegistry());
final var expiredStrategy = new UidlExpiredSessionStrategy();
concurrency.expiredSessionStrategy(expiredStrategy);
});
});
setStatelessAuthentication(http, new SecretKeySpec(Base64.getDecoder().decode(jwtAuthSecret), JwsAlgorithms.HS256), "com.example");
}
#Bean
public SessionRegistry sessionRegistry() {
return new SessionRegistryImpl();
}
#Bean
#Primary
public SpringViewAccessChecker springViewAccessChecker(AccessAnnotationChecker accessAnnotationChecker) {
return new KeycloakSpringViewAccessChecker(accessAnnotationChecker, "/oauth2/authorization/keycloak");
}
private OidcClientInitiatedLogoutSuccessHandler logoutSuccessHandler() {
var logoutSuccessHandler = new OidcClientInitiatedLogoutSuccessHandler(clientRegistrationRepository);
logoutSuccessHandler.setPostLogoutRedirectUri("{baseUrl}");
return logoutSuccessHandler;
}
#Override
public void configure(WebSecurity web) throws Exception {
super.configure(web);
web.ignoring().antMatchers("/session-expired", "/images/*", "/login", "/favicon.ico");
}
#Bean
public PolicyFactory htmlSanitizer() {
return Sanitizers.FORMATTING.and(Sanitizers.BLOCKS).and(Sanitizers.STYLES).and(Sanitizers.LINKS);
}
}
How to properly redirect user to the original page?
UPDATED
public class KeycloakVaadinAuthenticationSuccessHandler extends VaadinSavedRequestAwareAuthenticationSuccessHandler {
private static final Logger logger = LoggerFactory.getLogger(KeycloakVaadinAuthenticationSuccessHandler.class);
private final ServiceFacade serviceFacade;
public KeycloakVaadinAuthenticationSuccessHandler(ServiceFacade serviceFacade) {
this.serviceFacade = serviceFacade;
}
#Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
if (authentication == null || !(authentication instanceof OAuth2AuthenticationToken)) {
String message = String.format("Authentication is null or not an instance of OAuth2AuthenticationToken: %s", authentication);
logger.error(message);
throw new IllegalStateException(message);
}
Collection<VaadinSession> vaadinSessions = VaadinSession.getAllSessions(request.getSession());
OAuth2AuthenticationToken token = (OAuth2AuthenticationToken) authentication;
String keycloakSessionId = (String) token.getPrincipal().getAttributes().get("sid");
serviceFacade.getProfileService().createUserWithProfileIfNotExists((OAuth2AuthenticationToken) authentication, (user, profile, principalUserUuid) -> {
try {
if (CollectionUtils.isNotEmpty(vaadinSessions)) {
for (VaadinSession vaadinSession : vaadinSessions) {
if (vaadinSession.getService() != null) {
vaadinSession.access(() -> {
vaadinSession.setAttribute(UserInfo.SUB_PROPERTY, user.getUuid());
vaadinSession.setAttribute(UserInfo.KEYCLOAK_SESSION_ID, keycloakSessionId);
});
}
}
}
} catch (Exception e) {
logger.error(e.getMessage(), e);
throw new IOException(e);
}
});
super.onAuthenticationSuccess(request, response, authentication);
}
The success handler is the one taking care of redirecting to the original view. You are overriding that with your own version so it will not work out of the box. There is nowadays a setOAuth2LoginPage helper in VaadinWebSecurity that will set up the correct success handler.
Below is my example of Configuration, as far as I understand, JwtUsernameAndPasswordAuthenticationFilter works first ( it gets username, password from request, checks if they are correct and provides a token ), then - JwtTokenVerifier.
I have a few questions:
Is JwtUsernameAndPasswordAuthenticationFilter checks requests every time for containing username and password? If not, when does it check it? Once per what?
Why do we create Authentication object in JwtTokenVerifier class with no password ( just username and Authorities ) and put it in Context?
P.S. I do appreciate your answers! And know how dumb the question may seems to be.
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.addFilter(new JwtUsernameAndPasswordAuthenticationFilter(authenticationManager(), jwtConfig, secretKey))
.addFilterAfter(new JwtTokenVerifier(secretKey, jwtConfig),JwtUsernameAndPasswordAuthenticationFilter.class)
.authorizeRequests()
.antMatchers("/", "index", "/css/*", "/js/*").permitAll()
.antMatchers("/api/**").hasRole(STUDENT.name())
.anyRequest()
.authenticated();
}
public class JwtUsernameAndPasswordAuthenticationFilter extends UsernamePasswordAuthenticationFilter {
private final AuthenticationManager authenticationManager;
private final JwtConfig jwtConfig;
private final SecretKey secretKey;
public JwtUsernameAndPasswordAuthenticationFilter(AuthenticationManager authenticationManager,
JwtConfig jwtConfig,
SecretKey secretKey) {
this.authenticationManager = authenticationManager;
this.jwtConfig = jwtConfig;
this.secretKey = secretKey;
}
#Override
public Authentication attemptAuthentication(HttpServletRequest request,
HttpServletResponse response) throws AuthenticationException {
try {
UsernameAndPasswordAuthenticationRequest authenticationRequest = new ObjectMapper()
.readValue(request.getInputStream(), UsernameAndPasswordAuthenticationRequest.class);
Authentication authentication = new UsernamePasswordAuthenticationToken(
authenticationRequest.getUsername(),
authenticationRequest.getPassword()
);
Authentication authenticate = authenticationManager.authenticate(authentication);
return authenticate;
} catch (IOException e) {
throw new RuntimeException(e);
}
}
#Override
protected void successfulAuthentication(HttpServletRequest request,
HttpServletResponse response,
FilterChain chain,
Authentication authResult) throws IOException, ServletException {
String token = Jwts.builder()
.setSubject(authResult.getName())
.claim("authorities", authResult.getAuthorities())
.setIssuedAt(new Date())
.setExpiration(java.sql.Date.valueOf(LocalDate.now().plusDays(jwtConfig.getTokenExpirationAfterDays())))
.signWith(secretKey)
.compact();
response.addHeader(jwtConfig.getAuthorizationHeader(), jwtConfig.getTokenPrefix() + token);
}
}
public class JwtTokenVerifier extends OncePerRequestFilter {
private final SecretKey secretKey;
private final JwtConfig jwtConfig;
public JwtTokenVerifier(SecretKey secretKey,
JwtConfig jwtConfig) {
this.secretKey = secretKey;
this.jwtConfig = jwtConfig;
}
#Override
protected void doFilterInternal(HttpServletRequest request,
HttpServletResponse response,
FilterChain filterChain) throws ServletException, IOException {
String authorizationHeader = request.getHeader(jwtConfig.getAuthorizationHeader());
if (Strings.isNullOrEmpty(authorizationHeader) || !authorizationHeader.startsWith(jwtConfig.getTokenPrefix())) {
filterChain.doFilter(request, response);
return;
}
String token = authorizationHeader.replace(jwtConfig.getTokenPrefix(), "");
try {
Jws<Claims> claimsJws = Jwts.parser()
.setSigningKey(secretKey)
.parseClaimsJws(token);
Claims body = claimsJws.getBody();
String username = body.getSubject();
var authorities = (List<Map<String, String>>) body.get("authorities");
Set<SimpleGrantedAuthority> simpleGrantedAuthorities = authorities.stream()
.map(m -> new SimpleGrantedAuthority(m.get("authority")))
.collect(Collectors.toSet());
Authentication authentication = new UsernamePasswordAuthenticationToken(
username,
null,
simpleGrantedAuthorities
);
SecurityContextHolder.getContext().setAuthentication(authentication);
} catch (JwtException e) {
throw new IllegalStateException(String.format("Token %s cannot be trusted", token));
}
filterChain.doFilter(request, response);
}
}
JwtUsernameAndPasswordAuthenticationFilter extends UsernamePasswordAuthenticationFilter, and by default its triggered when you make a "POST" call to "/login". This can be changed by calling the setFilterProcessesUrl(<PATH_HERE>) in the JwtUsernameAndPasswordAuthenticationFilter's constructor.
You don't keep the password in the Authentication object simply because it's not needed, and it's safer to keep the password off-memory because anyone with access to the memory dump can retrieve the password.
I am trying to login using httpServletRequest.login(), after registration for automatic login. BUT when I do this, I hit the OncePerRequest.doFilterInternal which checks the headers for an authorization header and kicks me out.
I dont think I am supposed to hit this for login, right now when I hit the route "api/v1/auth/login" I never hit the filter OncePerRequest.doFilterInternal. And its 200 response includes authorization jwt token as expected.
Am I not using the OncePerRequest.doFilterInternal correctly? I want to be able to login and set an authorization header in the response when a user registers.
Relevant code:
public class JwtTokenVerifier extends OncePerRequestFilter {
private final SecretKey secretKey;
private final JwtConfig jwtConfig;
public JwtTokenVerifier(SecretKey secretKey,
JwtConfig jwtConfig) {
this.secretKey = secretKey;
this.jwtConfig = jwtConfig;
}
#Override
protected void doFilterInternal(HttpServletRequest request,
HttpServletResponse response,
FilterChain filterChain) throws ServletException, IOException {
String authorizationHeader = request.getHeader(jwtConfig.getAuthorizationHeader());
if (Strings.isNullOrEmpty(authorizationHeader) || !authorizationHeader.startsWith(jwtConfig.getTokenPrefix())) {
filterChain.doFilter(request, response);
return;
}
String token = authorizationHeader.replace(jwtConfig.getTokenPrefix(), "");
try {
Jws<Claims> claimsJws = Jwts.parser()
.setSigningKey(secretKey)
.parseClaimsJws(token);
Claims body = claimsJws.getBody();
String username = body.getSubject();
var authorities = (List<Map<String, String>>) body.get("authorities");
Set<SimpleGrantedAuthority> simpleGrantedAuthorities = authorities.stream()
.map(m -> new SimpleGrantedAuthority(m.get("authority")))
.collect(Collectors.toSet());
Authentication authentication = new UsernamePasswordAuthenticationToken(
username,
null,
simpleGrantedAuthorities
);
SecurityContextHolder.getContext().setAuthentication(authentication);
} catch (JwtException e) {
throw new IllegalStateException(String.format("Token %s cannot be trusted:", token));
}
filterChain.doFilter(request, response);
}
Config:
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(prePostEnabled = true)
public class ApplicationSecurityConfig extends
WebSecurityConfigurerAdapter {
private final AuthUserServiceImpl authUserServiceImpl;
private final IUserRepository iUserRepository;
private final PasswordEncoder passwordEncoder;
private final SecretKey secretKey;
private final JwtConfig jwtConfig;
private final AccessDeniedFilter accessDeniedFilter;
private final AuthenticationEntryPointFilter authenticationEntryPointFilter;
#Autowired
public ApplicationSecurityConfig(PasswordEncoder passwordEncoder,
AuthUserServiceImpl authUserServiceImpl,
SecretKey secretKey,
JwtConfig jwtConfig,
AccessDeniedFilter accessDeniedFilter,
AuthenticationEntryPointFilter authenticationEntryPointFilter,
IUserRepository iUserRepository) {
this.passwordEncoder = passwordEncoder;
this.authUserServiceImpl = authUserServiceImpl;
this.secretKey = secretKey;
this.jwtConfig = jwtConfig;
this.accessDeniedFilter = accessDeniedFilter;
this.authenticationEntryPointFilter = authenticationEntryPointFilter;
this.iUserRepository = iUserRepository;
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.cors()
.and()
.csrf()
.disable()
.authorizeRequests()
.antMatchers("/", "index", "/css/*", "/js/*", "/api/v1/auth/register").permitAll()
.antMatchers("/api/**").hasAnyRole(ADMIN.name(), USER.name())
.anyRequest()
.authenticated()
.and()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.exceptionHandling()
.accessDeniedHandler(accessDeniedFilter)
.authenticationEntryPoint(authenticationEntryPointFilter)
.and()
.addFilter(jwtAuthorizationFilter())
.addFilterAfter(new JwtTokenVerifier(secretKey, jwtConfig), JwtUsernameAndPasswordJwtFilter.class);
}
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(daoAuthenticationProvider());
}
#Bean
CorsConfigurationSource corsConfigurationSource() {
final CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowedOrigins(Arrays.asList("whatever.com));
configuration.setAllowedMethods(ImmutableList.of("HEAD", "GET", "POST", "PUT", "DELETE", "OPTIONS"));
configuration.setAllowCredentials(true);
configuration.setAllowedHeaders(ImmutableList.of("Authorization", "Cache-Control", "Content-Type", "access-control-allow-origin"));
configuration.setExposedHeaders(Arrays.asList("Authorization"));
final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}
#Bean
public DaoAuthenticationProvider daoAuthenticationProvider() {
DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
provider.setUserDetailsService(authUserServiceImpl);
provider.setPasswordEncoder(passwordEncoder);
return provider;
}
public JwtUsernameAndPasswordJwtFilter jwtAuthorizationFilter() throws Exception {
JwtUsernameAndPasswordJwtFilter jwtAuthenticationFilter = new JwtUsernameAndPasswordJwtFilter(authenticationManager(), jwtConfig, secretKey, iUserRepository);
jwtAuthenticationFilter.setFilterProcessesUrl("/api/v1/auth/login");
return jwtAuthenticationFilter;
}
}
#PostMapping("/register")
public ResponseEntity<?> registerUserAccount(
#Valid #RequestBody AuthUserRequest authUserRequest,
Errors errors) throws NullPointerException {
String password = authUserRequest.getPassword();
if (errors.hasErrors()) {
return ResponseEntity.badRequest().body(errors.getFieldError());
}
try {
iAuthUser.registerNewUserAccount(authUserRequest);
} catch (Exception e) {
return ResponseEntity.badRequest().build();
}
try {
httpServletRequest.login(authUserRequest.getUsername(), password);
} catch (ServletException e) {
System.out.println("Servlet Error: " + e);
}
return ResponseEntity.ok().build();
}
I need to integrate on Liferay 6.2 GA6 a SSO from a web application that provide info by oAuth
A native support doesn't exist.
My problem is to create the automatic login on Liferay (after the user creation or if the user already exists). Any help ?
You have to create a hook where you create an AutoLogin class that extends BaseAutoLogin. Read the oAuth documentation and write a login logic in that hook, then set it in auto.login.hooks property in portal-ext.properties(properties reference). Then you will have to create a filter that extends BasePortalFilter and implemets processFilter method. You can model on CASFilter and CASAutologin
override portal.properties adding
auto.login.hooks=com.yourpackage.hook.MyAutoLogin
Create the class:
package com.yourpackage.hook;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import com.liferay.portal.kernel.exception.PortalException;
import com.liferay.portal.kernel.exception.SystemException;
import com.liferay.portal.kernel.util.ParamUtil;
import com.liferay.portal.kernel.util.Validator;
import com.liferay.portal.model.User;
import com.liferay.portal.security.auth.AutoLogin;
import com.liferay.portal.security.auth.AutoLoginException;
import com.liferay.portal.service.UserLocalServiceUtil;
import com.liferay.portal.util.PortalUtil;
//based on example
// https://bitbucket.org/brandizzi/liferay-examples/src/a41d71eba8f2fb2d4272a3ce8f393e77cec41d60/unsafe-login-hook/docroot/WEB-INF/src/br/brandizzi/adam/liferay/unsecure/UnsecureAutoLogin.java?at=default&fileviewer=file-view-default
public class MyAutoLogin implements AutoLogin {
#Override
public String[] login(HttpServletRequest request,HttpServletResponse response) throws AutoLoginException {
HttpSession session = request.getSession();
String emailAddress = (String) session.getAttribute("LIFERAY_SHARED_EMAIL");
if (emailAddress == null || emailAddress.isEmpty())
return null;
long companyId = PortalUtil.getCompanyId(request);
User user = null;
try {
user = UserLocalServiceUtil.getUserByEmailAddress(companyId, emailAddress);
} catch (PortalException | SystemException e) {
e.printStackTrace();
}
String redirect = ParamUtil.getString(request, "redirect");
if (Validator.isNotNull(redirect)) {
request.setAttribute(AutoLogin.AUTO_LOGIN_REDIRECT_AND_CONTINUE,PortalUtil.escapeRedirect(redirect));
}
String[] credentials = new String[3];
credentials[0] = String.valueOf(user.getUserId());
credentials[1] = user.getPassword();
credentials[2] = String.valueOf(user.isPasswordEncrypted());
// credentials[2] = Boolean.FALSE.toString();
return credentials;
}
#Override
public String[] handleException(HttpServletRequest arg0,
HttpServletResponse arg1, Exception arg2)
throws AutoLoginException {
System.out.println("AutoLogin handleException ");
return null;
}
}
create an other class with the static methods:
public static JSONObject doSSO(String firstname, String surname, String email, String username,String accessToken, ActionRequest actionRequest, ActionResponse actionResponse){
JSONObject jsonResp = JSONFactoryUtil.createJSONObject();
//Get default Liferay company
String webId = new String("liferay.com");
Company company = null;
try {
company = CompanyLocalServiceUtil.getCompanyByWebId(webId);
} catch (PortalException | SystemException e) {
e.printStackTrace();
}
System.out.println("email "+email);
User currentUser = null;
try {
currentUser = UserLocalServiceUtil.getUserByEmailAddress(company.getCompanyId(), email);
} catch (SystemException | PortalException e) {
System.out.println("User to create");
}
if (Validator.isNull(currentUser)){
long newUserId = 0;
try {
jsonResp = addNewUser( firstname, surname, email, username );
} catch (Exception e) {
e.printStackTrace();
}
String newUserIdS = jsonResp.getString("newUserId");
newUserId = Long.valueOf(newUserIdS);
try {
currentUser = UserLocalServiceUtil.fetchUser(newUserId);
} catch (SystemException e) {
e.printStackTrace();
}
notifyAuthorAboutInvited(email, currentUser);
}
setExistingUserOnSession( actionRequest,currentUser, accessToken);
//Login the user
HttpServletRequest request = PortalUtil.getOriginalServletRequest(PortalUtil.getHttpServletRequest(actionRequest));
HttpServletResponse response = PortalUtil.getHttpServletResponse(actionResponse);
MyAutoLogin myLogin = new MyAutoLogin();
try {
myLogin.login(request, response);
jsonResp.put("message","OK - User logged on Liferay");
} catch (AutoLoginException e1) {
e1.printStackTrace();
}
//set Token on customfield
//remember to set permission guest to view and update
ServiceContext serviceContext = null;
try {
serviceContext = ServiceContextFactory.getInstance(User.class.getName(), actionRequest);
} catch (PortalException | SystemException e) {
e.printStackTrace();
}
Map<String,Serializable> expandoBridgeAttributes = new HashMap<String, Serializable>();
expandoBridgeAttributes.put("token", accessToken);
serviceContext.setExpandoBridgeAttributes(expandoBridgeAttributes);
currentUser.setExpandoBridgeAttributes(serviceContext);
try {
UserLocalServiceUtil.updateUser(currentUser);
} catch (SystemException e) {
e.printStackTrace();
}
String userToken =currentUser.getExpandoBridge().getAttribute("token").toString();
//System.out.println("doSSO accessToken dopo "+userToken);
return jsonResp;
}
and:
private static void setExistingUserOnSession(ActionRequest actionRequest,User user, String accessToken) {
HttpServletRequest req = PortalUtil.getHttpServletRequest(actionRequest);
HttpSession session = req.getSession();
session.setAttribute("LIFERAY_SHARED_EMAIL", user.getEmailAddress());
}
I'm trying to configure WebSocket via Spring with STOMP, OAuth 2 and SockJS.
New spec tells us how to implement it using Interceptors.
The case is: if user is authenticated there is an Bearer Token in Native header of CONNECT request and there is no problem to set principal via Token.
But my task is to use BrowserToken for unauthorized users (which is saved in Cookies). How can i get it from the request?
I've found a solution:
#Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/websocket/tracker")
.withSockJS()
.setInterceptors(httpSessionHandshakeInterceptor());
}
#Bean
public HandshakeInterceptor httpSessionHandshakeInterceptor() {
return new HandshakeInterceptor() {
#Override
public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Map<String, Object> attributes) throws Exception {
if (request instanceof ServletServerHttpRequest) {
ServletServerHttpRequest servletServerRequest = (ServletServerHttpRequest) request;
HttpServletRequest servletRequest = servletServerRequest.getServletRequest();
Cookie token = WebUtils.getCookie(servletRequest, "key");
attributes.put("token", token.getValue());
}
return true;
}
#Override
public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Exception exception) {
}
};
}
And finally
#Override
public void configureClientInboundChannel(ChannelRegistration registration) {
registration.setInterceptors(new ChannelInterceptorAdapter() {
#Override
public Message<?> preSend(Message<?> message, MessageChannel channel) {
StompHeaderAccessor accessor =
MessageHeaderAccessor.getAccessor(message, StompHeaderAccessor.class);
if (StompCommand.CONNECT.equals(accessor.getCommand())) {
Map<String, Object> sessionAttributes = accessor.getSessionAttributes();
List<String> authorization = accessor.getNativeHeader("Authorization");
Principal user = ... ; // get Principal using authentication / browser token
accessor.setUser(user);
}
return message;
}
});
}