How I can connect with token URL - java

how to authenticate a user without typing a name and password, but a URL sent by email with a token ?
I tried with a controller intercepting the url containing the token but my spring setting returns the login page because the user is anonymous.
I would also like to connect with token in the URL such as :
http://myWebSite/guest/18f1ff9a-fd1e-49be-bb31 ...
I have a token for each user in database
I have allowed anonymous access to the controller with token. Then I get the username and password of a user by token Like this :
String queryFindUserByToken = "from UserEntity u where u.token = :token";
Now I want to automatically create a user session with the login and password that I got from the database.
I tried to redirect to redirect to j_spring_security_check with parameters but authentication method not supported: GET
#RequestMapping(value = "guest/{tokenUser}", method = RequestMethod.GET)
public String guest(Map<String, Object> map, #PathVariable String tokenUser) {
UserEntity user = userService.findUserByToken(tokenUser);
return "redirect:j_spring_security_check?j_username=" + user.getUsername() + "&j_password=" + user.getPassword() ;
}
do you have a better solution ?

Related

Problem getting the userName from jwtToken

I implemented security for my application using JWT tokens. I make a post request to the /auth endpoint (passing userName and password) and get back a token, which I then use for further requests to the other endpoints. Everything works perfectly fine, but I can't get the userName out of this token. Here' my controller method:
#GetMapping(produces = {MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_XML_VALUE})
public ResponseEntity<List<SongList>> getSongListsForUser(#RequestParam("userId") String ownerId) {
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
String userId = auth.getName();
return ResponseEntity.ok(userId.equals(ownerId)
? songListDAO.findListsOf(userId)
: songListDAO.findPublicListsOf(ownerId));
}
Found this solution here on stackoverflow.
I put a breakpoint at the line of the return statement to inspect whats inside the userId and got this:
Why this is not working? What do I have to do to get the userName (=userId) from the jwt token?

How to authenticate and redirect to external application for SSO?

I am trying to implement a simple SSO feature in my spring-based web application. Scenario:
I have a main application Application1 and a secondary Application2. Both have their own login mechanisms (using spring-security login-forms) in place.
I want to implement SSO in Application1, so that when user logs-in to Application1, he can also seamlessly access Application2 via a link without having to fill up login details for Application2.
Here's what I have tried:
I created an API in Application2 which takes email as input, validates it, creates user session, and returns a url string.
#RequestMapping(path = "/sso/login", consumes = "application/json", method = RequestMethod.POST)
public String login(#RequestBody SSOparams params, HttpServletRequest req, ModelMap model) {
// 1. validates email from params
// 2. creates Authentication object:
UsernamePasswordAuthenticationToken authReq = new UsernamePasswordAuthenticationToken(username, password);
Authentication auth = authManager.authenticate(authReq);
SecurityContext sc = SecurityContextHolder.getContext();
sc.setAuthentication(auth);
HttpSession session = req.getSession(true);
session.setAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY, sc);
// 3. returns a url string:
return "/user/dashboard";
}
User logs-in to Application1.
Inside Application1's home-page, when user clicks on a Application2's link, a call is made to Application1's controller method.
Application1's controller method calls Application2's login API with an email parameter, and finally redirects to the url returned from the API.
Application1's controller method:
#RequestMapping(value = "/callapplication2", method = RequestMethod.POST)
public String callapplication2(ModelMap model,HttpSession session) {
String output = "";
String redirectionUrl = "";
try {
// 1. calling application2's login API
URL url = new URL("http://localhost:8080/application2/api/sso/login");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setDoOutput(true);
conn.setRequestMethod("POST");
conn.setRequestProperty("Content-Type", "application/json");
String input = "{\"uniqueemail\":\"abc#gmail.com\"}";
OutputStream os = conn.getOutputStream();
os.write(input.getBytes());
os.flush();
BufferedReader br = new BufferedReader(new InputStreamReader((conn.getInputStream())));
while ((output = br.readLine()) != null) {
redirectionUrl = redirectionUrl + output;
}
conn.disconnect();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
// 2. returns a url
return "redirect:http://localhost:8080/application2" + redirectionUrl ;
}
All of the above is working fine. But when I login to Application1 and click on application2's link, I expect application should redirect to
http://localhost:8080/application2/user/dashboard
without having to fill up credentials.
But instead, Application2's login page opens. I can see in the network console of Chrome that /user/dashboard is being called, but since the page is secured, I am redirected to application2's login page.
Does this mean that the authentication I created using API is not being used. What am I missing?
Best approach is to set filter in web.xml and put it in top of the list.
Whenever your application will get any request it will first go to the filter and there you will check that session is present or not if its null then simply redirect to your sso login page else respective landing page.
Now in your case,
Solution i can see
1) Put filter into app2 web.xml
2) Now when you redirect from app1 to app2 (Pass one parameter anything like username, email whatever)
3) Store it into the session.
4) Whenever any request will come to app2 you will first verify session from filter, If username found that means user not need to login again else redirect to sso login page.
Thats standars steps (I belive)
5) Having a peek into your implementation.Specifically you have to add one more step into app filter. When you are redirecting from app1 for te first time with http://localhost:8080/application2/user/dashboard ( You will pass one parameter along with this url as explained above).
This let you to check 2 condition into your filter. Either request should have valid parameter or username should be into session. If any condition stated true you can let redirect request to further else you have to redirect to login page.
Hope this will help to resolve your issue.

Spring Boot OAuth2 - How to access Refresh Token to save for later

I am trying to use the Eclipse's package for accessing GitHub using their client GitHubClient.
One of the methods on the client is setOAuth2Token, it takes a String token. I am assuming this is a refresh token.
Either way, I am able to login using GitHub with Spring OAuth2, but I am not sure how to retrieve the refresh token. I can retrieve the bearer token:
#GetMapping()
public PingResponse ping(#Autowired Principal principal) {
OAuth2Authentication userDetails = (OAuth2Authentication) principal;
OAuth2AuthenticationDetails userOAuthDetails = (OAuth2AuthenticationDetails) userDetails.getDetails();
OAuth2ProtectedResourceDetails protectedUserDetails = (OAuth2ProtectedResourceDetails) principal;
logger.info("user details: " + userDetails);
logger.info("user details credentials: " + userDetails.getCredentials());
logger.info("oauth user details: " + userOAuthDetails);
logger.info("token type: " + userOAuthDetails.getTokenType());
logger.info("token value: " + userOAuthDetails.getTokenValue());
logger.info("decoded details: " + userOAuthDetails.getDecodedDetails());
logger.info("Ping on the server was successful.");
return new PingResponse("Connection is successful!");
}
However, I can't seem to get at the refresh token.
I'd like to get it so I can save it in a DB to do action on user's behalf later on, without the user logged in.
How do I get at the refresh token so I can save it for later?
Thanks!

Spring Security Get logged user by session id

Recently I am trying to get existing logged user by JSESSIONID with Spring Security. After tracing the source code I still cannot find the way to do this. Is it possible? Where Spring Security store the mapping between JSESSIONID and AuthUser?
Any help will be very appreciated.
Something like this:
#RequestMapping(value = "/userAndSession/{providedSessionId}", method = RequestMethod.GET)
public String getUserAndSessionId(UsernamePasswordAuthenticationToken principal,
HttpServletRequest httpServletRequest, #PathVariable("providedSessionId") String sessionID) {
// Session ID
String sessionId = httpServletRequest.getRequestedSessionId();
if(sessionId.equals(providedSessionId)) {
// Username
String name = principal.getName();
}
}

How to login with #RestController and send the object to angularjs

I have some trouble figuring out how to create a login form in angularjs using springboot.
I can register a user and send the data to the database but the problems begin when i want to login.
in angularjs i have a function like this
function Login(username, password, callback) {
$http.post('/api/authenticate', { username: username, password: password })
.success(function (response) {
callback(response);
});
}
What i managed to do but probably is't right:
#RequestMapping(value = "/authenticate/{id}",method = RequestMethod.GET)
public User getUser(#PathVariable Integer id) {
return repo.findOne(id);
}
This gives me following json
{"id":2,"username":"jdoe","password":"$2a$10$5hgIyQr.K9wb8cXEyWGbROAU.rkYzd19vP7ajHpwp1KUYdShfcPn.","lastname":"doe","firstname":"john","customfield":"Hello there"}
But now i have following problems and questions :
How can i check if the username and password is equal to the username and password of json by going to api/authenticate ? (without {id})
can i hide this json from the users ?
Is this safe ?
how will angular now all the users propertys ? (i suggest i can retrieve this from the json)
any pro tips on how to solve this?
From AngularJS you are calling HTTP POST method and at Spring side you have declared as HTTP GET, which is wrong.
Correct request mapping is
#RequestMapping(value = "/api/authenticate",method = RequestMethod.POST, consumes = "application/json")
#ResponseBody
public User getUser(#RequestBody User user) {
//here request body contains User POJO object's payload (JSON object)
//You are getting username from JSON,
//so you need to update your call to findOne method
return repo.findOne(user.getUserName());
}
Please refer
#RequestBody and #ReponseBody spring
#RequestBody annotation spring docs
#RequestMapping#consumes

Categories