Does spring security context persist across REST/SOAP calls? - java

Do Spring security context persist while calling rest/soap services from Client. I have client application which sets authentication using SecurityContextHolder.getContext().setAuthentication(). Client application makes rest/soap calls where I have to get context.
//Setting security context in client application:
User contextUser = new User(username, enc_password, true, true, true, true,grantedAuthorities, null);
authentication = new UsernamePasswordAuthenticationToken(contextUser, username,grantedAuthorities);
SecurityContextHolder.getContext().setAuthentication(authentication);
// on server side
// I want to get following authentication on server side to get logged in user
Authentication auth=SecurityContextHolder.getContext().getAuthentication();
User user= null;
if (auth != null && !(auth instanceof AnonymousAuthenticationToken)) {
// userDetails = auth.getPrincipal()
Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
String username = null;
if (principal instanceof UserDetails) {
username = ((UserDetails) principal).getUsername();
user = (UserDetails) principal;
} else {
username = principal.toString();
}
}

To access username on server side, after REST/SOAP API calls are made, you can do it by adding username in each request's header, before making API call.
Intercept each request on the server-side by using Spring Interceptors, you can create interceptor class by implementing a HandlerInterceptorAdapter interface.
For more information about interceptors.

Related

How to fix the redirct url issue in social linked in integration with springmvc

i am facing one issue in linkedIn social integration with spring mvc based web application updated their social library to 1.0a Oauth to 2.0 Oauth in linked in developer network i mentioned Redirect url to http://localhost:8080/Myproject/signin/linkedin here once i run the project linkedin login page is coming but after entering user name password on click of login page is redirected once again to login page it is not going particular page of application.
this is my spring code
public ProviderSignInController providerSignInController(ConnectionFactoryLocator connectionFactoryLocator, UsersConnectionRepository usersConnectionRepository) {
ProviderSignInController providerSignInController = new ProviderSignInController(connectionFactoryLocator, usersConnectionRepository, new SignInAdapter() {
#Override
public String signIn(String socialuserid, Connection<?> connection, Nativewebrequest request) {
final HttpServletRequest httpServletRequest = request.getNativeRequest(HttpServletRequest.class);
final HttpSession httpSession = httpServletRequest.getSession(false);
final User user = userService.getUserBySocialId(userService.getSocialUser(socialUserId).getUserId());
final SecurityUser securityUser;
if (httpSession != null) {
final String token = (String)httpSession.getAttribute("invitationToken");
if(token != null && !"".equals(token)) {
System.out.println("user service token ...");
final Invitation invitation = userService.consumeInvitation(token);
if(invitation != null) user.setMembers(userService.getInvitationMembers(invitation.getEmail(), invitation.getInviteType()));
user.setRole(invitation.getInviteType());
userService.removeInvitations(invitation.getEmail(), invitation.getInviteType());
userService.createUserMember(member);
}
httpSession.removeAttribute("invitationToken");
}
}
securityUser = new SecurityUser(user);
SecurityContextHolder.getContext().setAuthentication(new UsernamePasswordAuthenticationToken(securityUser, null, securityUser.getAuthorities()));
return null;
}
});
client id and client secret id is mentioned correctly
i am little bit strck with this please help me sort out this is issue

How to configure Spring Boot OAuth2.0 server with custom UserDetailsService and password validation?

I am trying to configure a Spring Boot OAuth2.0 server on my existing schema. To authenticate a user with my schema, I need to retrieve an encrypted password from my users table and pass it to an external service for validation.
I was able to define a custom UserDetailsService as below, but the default behavior authenticates based on a comparison of the password in the returned UserDetails object and the password from the request.
How can I customize this behavior so that I can use my custom UserDetailsService, but offload the password validation to the external service?
#Component("userDetailsService")
public class UserDetailsService implements org.springframework.security.core.userdetails.UserDetailsService {
#Autowired
private DataSource dataSource;
#Override
public UserDetails loadUserByUsername(final String login) {
String sql = "select encrypted_password from users where login_name = ?";
String encryptedPassword = null;
try {
Connection con = dataSource.getConnection();
PreparedStatement statement = con.prepareStatement(sql));
statement.setString(1, login);
try (ResultSet results = statement.executeQuery()) {
if (results.next()) {
encryptedPassword = results.getLong("encrypted_password");
}
}
} catch (SQLException e) {
e.printStackTrace();
}
return new User(login, encryptedPassword, Arrays.asList(new SimpleGrantedAuthority("simpleAuth")));
}
}
I probably don't have enough details to go off from your question, but I will make some assumptions and give you the best answer I can.
Assumption: User has to login using some sort of credential that you are then doing a loadUserByUsername(loginCreds).
If you don't want to use that specific UserDetails object, you can create an CustomAuthenticationFilter that is configured in your WebSecurity class by using http.addFilterBefore(new CustomAuthenticationFilter(), UsernamePasswordAuthenticationFilter)
From there, you can customize your entire authentication flow. You can choose to create a CustomAuthenticationToken that in turn gets authenticated via CustomAuthenticationProvider. Within this provider, you can do your password check with your 3rd party validation. If it passes, you can load your user object as you have there.

How can I programmatically authenticate user with Spring Security using DaoAuthenticationProvider

I was wondering what I am doing wrong here to authenticate a user. I have an application where the user goes through several steps to activate their account, and upon doing so I would like to bypass the login form and take them directly to their dashboard.
Here is what my automated login function looks like:
protected void automatedLogin(String username, String password, HttpServletRequest request) {
try {
// Must be called from request filtered by Spring Security, otherwise SecurityContextHolder is not updated
CustomUserDetailsService udService = new CustomUserDetailsService(userDAO, request);
UserDetails uDetails = udService.loadUserByUsername(username);
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(uDetails, password);
token.setDetails(new WebAuthenticationDetails(request));
DaoAuthenticationProvider authenticator = new DaoAuthenticationProvider();
Authentication authentication = authenticator.authenticate(token);
SecurityContextHolder.getContext().setAuthentication(authentication);
} catch (Exception e) {
e.printStackTrace();
SecurityContextHolder.getContext().setAuthentication(null);
}
}
I must use the DaoAuthenticationProvider class as my authentication provider. I have verified that I am getting a UserDetails model containing the correct credentials, ID, authority roles, etc.
When it calls the authenticate method I run into a Null Pointer somewhere along the way in the DaoAuthenticationProvider class:
org.springframework.security.authentication.AuthenticationServiceException
at
org.springframework.security.authentication.dao.DaoAuthenticationProvider.retrieveUser(DaoAuthenticationProvider.java:109)
at
org.springframework.security.authentication.dao.AbstractUserDetailsAuthenticationProvider.authenticate(AbstractUserDetailsAuthenticationProvider.java:132)
at
com.bosch.actions.BaseController.doAutoLogin(BaseController.java:659)
. . . Caused by: java.lang.NullPointerException at
org.springframework.security.authentication.dao.DaoAuthenticationProvider.retrieveUser(DaoAuthenticationProvider.java:101)
I'm really not sure what is null, as I don't have the source code available.
Edit
I was able to find the source code here - https://github.com/SpringSource/spring-security/blob/master/core/src/main/java/org/springframework/security/authentication/dao/DaoAuthenticationProvider.java
I was able to get around the Null Pointer by explicitly setting the UserDetailsService on the object:
authenticator.setUserDetailsService(udService);
But now I get bad credentials exception when I know the password provided is correct, because I've seen it in the debugger in the UserDetails object set earlier in the code.
org.springframework.security.authentication.BadCredentialsException:
Bad credentials at
org.springframework.security.authentication.dao.DaoAuthenticationProvider.additionalAuthenticationChecks(DaoAuthenticationProvider.java:87)
at
org.springframework.security.authentication.dao.AbstractUserDetailsAuthenticationProvider.authenticate(AbstractUserDetailsAuthenticationProvider.java:149)
I was able to get the authentication working by piecing together all of the properties defined in the spring bean definition and setting them programmatically on the DaoAuthenticationProvider object. Looking back this seems like it may have been a silly question, but I hope it helps someone!
Corrected Code:
protected void automatedLogin(String username, String password, HttpServletRequest request) {
try {
// Must be called from request filtered by Spring Security, otherwise SecurityContextHolder is not updated
CustomUserDetailsService udService = new CustomUserDetailsService(userDAO, request);
CustomMd5PasswordEncoder passEncoder = new CustomMd5PasswordEncoder();
ReflectionSaltSource saltSource = new ReflectionSaltSource();
saltSource.setUserPropertyToUse("salt");
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(username, password);
token.setDetails(new WebAuthenticationDetails(request));
DaoAuthenticationProvider authenticator = new DaoAuthenticationProvider();
authenticator.setUserDetailsService(udService);
authenticator.setPasswordEncoder(passEncoder);
authenticator.setSaltSource(saltSource);
Authentication authentication = authenticator.authenticate(token);
SecurityContextHolder.getContext().setAuthentication(authentication);
} catch (Exception e) {
e.printStackTrace();
SecurityContextHolder.getContext().setAuthentication(null);
}
}

Jersey HTTP authentication:How Can I Access and the HTTP authentication in jersey restful url?

I am Writting a Restful webservice with Jersey, this is the sample code:
#GET
#Produce(MediaType.APPLICATION_JSON)
public String findItems(){
...
}
and the url of findItem is localhost:8080/items
the method should verify the http authentication info(digest or basic) of this url before excutes, how to access authentication from the a url request first?
I would not put this in the controller itself, but in a com.sun.jersey.spi.container.ContainerRequestFilter around the resource classes you wish to protect, but should give you the basic idea.
#Context
private HttpServletRequest request;
#GET
#Produce(MediaType.APPLICATION_JSON)
public String findItems(){
String auth = request.getHeader("authorization");
if (auth != null) {
String basic_prefix = "Basic ";
if (auth.startsWith(basic_prefix)) {
String auth_data = new String(Base64.decode(auth.substring(basic_prefix.length())));
String [] user_and_key = auth_data.split(":", 2);
// user and password available here
} else {
// reject access
}
} else {
// reject access
}
}
Usually the authentication is handled by the container, you just have to add the corresponding constraint to web.xml to indicate what Uris should be protected and what kind of auth is required. Then in jersey you can get the roles and principal info from the SecurityContext you can inject to your resource.

Is it possible to programmatically authenticate with Spring Security and make it persistent?

I'm using the following method in a Spring Controller to allow authentication via Ajax. It works, but it doesn't seem to create a cookie or anything that makes the authentication persistent.
#RequestMapping(method = RequestMethod.POST)
#ResponseBody
public LoginStatus login(#RequestParam("j_username") String username,
#RequestParam("j_password") String password) {
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(username, password);
try {
Authentication auth = authenticationManager.authenticate(token);
SecurityContextHolder.getContext().setAuthentication(auth);
return new LoginStatus(auth.isAuthenticated(), auth.getName());
} catch (BadCredentialsException e) {
return new LoginStatus(false, null);
}
}
What do I need to do to make the authentication persistent?
Make sure
you have SecurityContextPersistenceFilter configured
you are not setting create-session attribute of <security:http> tag to none.

Categories