I'm trying to pre-populate my local registration with Linkedin Callback. I am getting a NullPointer Exception on the "Email" field when I attempt to register.
It is possible that Email Address Field is not accessible with Linkedin but the Class UserProfile (used to populate fields) Docs say otherwise - "model provides access to those common fields in an uniform way".
It works with Facebook. When the Authentication process is triggered with a click on "Sign in with Facebook" Button, I am redirected back to the local site (after authentication) with the local signup form pre-populated with name and email.
This does not work for LinkedIn or Twitter, both throw NullPointer Exception. I would like settings for both LinkedIn and Twitter.
Here is my form
Linkedin
<form name="linkedin_signin" id="linkedin_signin" action="${linkedin_uri}" method="POST">
<input type="image" src="${linkedin_img}" />
</form>
Twitter
<form:form id="twitter_signin" action="${twitter_uri}" method="POST">
<input type="image" src="${twitter_img}" />
</form:form>
You must request r_emailaddress permission when authorizing your application for LinkedIn.
<form name="linkedin_signin" id="linkedin_signin" action="${linkedin_uri}" method="POST">
<input type="image" src="${linkedin_img}" />
<input type="hidden" name="scope" value="r_emailaddress" />
</form>
Permissions for LinkedIn: https://developer.linkedin.com/documents/authentication#granting
Permissions for Facebook: http://developers.facebook.com/docs/reference/login/#permissions
It looks like you can't do it with twitter https://dev.twitter.com/discussions/4019
Related
I am programming in Spring and using Thymeleaf as my view, and am trying to create a form where users can update their profile. I have a profile page which lists the user's information (first name, last name, address, etc), and there is a link which says "edit profile". When that link is clicked it takes them to a form where they can edit their profile. The form consists of text fields that they can input, just like your standard registration form.
Everything works fine, but my question is, when that link is clicked, how do I add the user's information to the input fields so that it is already present, and that they only modify what they want to change instead of having to re-enter all the fields.
This should behave just like a standard "edit profile" page.
Here is a segment of my edit_profile.html page:
First Name:
Here is the view controller method that returns edit_profile.html page:
#RequestMapping(value = "/edit", method = RequestMethod.GET)
public String getEditProfilePage(Model model) {
model.addAttribute("currentUser", currentUser);
System.out.println("current user firstname: " + currentUser.getFirstname());
model.addAttribute("user", new User());
return "edit_profile";
}
currentUser.getFirstname() prints out the expected value, but I'm getting blank input values in the form.
Thanks.
Solved the problem by removing th:field altogether and instead using th:value to store the default value, and html name and id for the model's field. So name and id is acting like th:field.
I'm slightly confused, you're adding currentUser and a new'd user object to the model map.
But, if currentUser is the target object, you'd just do:
<input type="text" name="firstname" value="James" th:value="${currentUser.firstname}" />
From the documentation:
http://www.thymeleaf.org/doc/tutorials/2.1/usingthymeleaf.html
I did not have a form with input elements but only a button that should call a specific Spring Controller method and submit an ID of an animal in a list (so I had a list of anmials already showing on my page). I struggled some time to figure out how to submit this id in the form. Here is my solution:
So I started having a form with just one input field (that I would change to a hidden field in the end). In this case of course the id would be empty after submitting the form.
<form action="#" th:action="#{/greeting}" th:object="${animal}" method="post">
<p>Id: <input type="text" th:field="*{id}" /></p>
<p><input type="submit" value="Submit" /> </p>
</form>
The following did not throw an error but neither did it submit the animalIAlreadyShownOnPage's ID.
<form action="#" th:action="#{/greeting}" th:object="${animal}" method="post">
<p>Id: <input type="text" th:value="${animalIAlreadyShownOnPage.id}" /></p>
<p><input type="submit" value="Submit" /> </p>
</form>
In another post user's recommended the "th:attr" attribute, but it didn't work either.
This finally worked - I simply added the name element ("id" is a String attribute in the Animal POJO).
<form action="#" th:action="#{/greeting}" th:object="${animal}" method="post">
<p>Id: <input type="text" th:value="${animalIAlreadyShownOnPage.id}" name="id" /></p>
<p><input type="submit" value="Submit" /> </p>
</form>
I'm working in a recovery password form with Spring Boot and Thymeleaf, the process is that the backend sends a link to the user with a token, this token is saved in a DB with the user information. The user clicks the link and the backend validate the token, if it's correct it redirects with the user information to the "new pass" form where the user has to introduce a new password and repeat it. When the user introduces the passwords and press save, it sends the information to the back end, with the userId it searches the register and changes the password.
In the controller where I validate the token when the user presses the link, I search the users' information and I build and usersRecoverPassDto with the userId and the passwords null and organize the model object to send it to the "new pass" form like this:
PasswordManagmentPostDto passManagment = new PasswordManagmentPostDto();
passManagment.setUserId(userId);
model.addAttribute ("passInfo", passManagment);
In the "new pass" form I received the correct information:
passInfo={
userId: 123456,
newPassword: null,
repeatePassword: null
}
The "new pass" form I code is like this:
<form action="#" th:action="#{/password/recovery}" th:object="${passInfo}" method="post">
<div class="mb-2 mr-sm-2 mb-sm-0 position-reNew pass:</label>
<input type="password" th:field="*{newPassword}" placeholder="Contraseña" class="form-control">
</div>
<div class="mb-2 mr-sm-2 mb-sm-0 position-relative form-group">
<label for="repeatePass" class="mr-sm-2">Repeat pass:</label>
<input type="password" th:field="*{repeatNewPassword}" placeholder="Repita contraseña" class="form-control"/>
</div>
<div class="mb-2 mr-sm-2 mb-sm-0 mt-3 position-relative form-group">
<input name="submit" type="submit" value="Save" class="inputButton btn btn-success "/>
</div>
</form>
I enter the two passwords and press the button Save but in the controller, I receive the next object:
passInfo={
userId: null,
newPassword: password,
repeatePassword: password
}
The userId parameter is just a parameter that passes without any modification and without being shown but I don't know how to persist this value from the controller to the view and then to the other controller.
I trayed adding another input to the new pass form:
<input type="text" th:field="*{userId}" th:value="*{userId}" placeholder="userId" class="form-control"/>
And I did nothing with this input, just put the two passwords and press the save button and it worked, I received the object with the correct information.
Of course, the userId parameter must not be shown in the form or modified.
Can someone help me, please?
Thank you very much in advance
OLD ANSWER
Use a hidden input:
<input type="hidden" id="userId" name="userId" th:value="*{userId}" />
This is part of what hidden inputs are for, to maintain data that should be sent back to the controller, but isn't something for the user to see / change.
NEW ANSWER
Per our discussion in the comments, it sounds like the appropriate approach is to retain the user's token on the front end. Pass that token to the controller when submitting the form, then look up the user by that token to reset the password.
I have a Spring boot application with a flow like this.
A new user register get registered
He/She receives a verification email
When the user clicks on the verification URL he/she will be redirected to the login page.
It's all good up to this point but what I want to do is when user gets to login page, I want to populate user's email into the email field and let user to enter his/her password to continue.
My email field looks like this:
<input type="email"
id="userLoginFormEmail"
class="form-control mb-4"
th:field="*{email}"
placeholder="Your email" required />
When the user gets redirected to login page, I'm adding user's email to model attribute like this:
model.addAttribute("userEmail", userEmail);
return "user/login";
So, how do I pre populate email field is userEmail attribute is not null?
UPDATE
I have an alert in the login page which appears fine when an activation url visited. It look like this
<div class="alert alert-info mt-5" role="alert" th:if="${userEmail != null}">
<strong>Your account is activated. Please login to proceed.</strong>
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
So, userEmail works fine but still can't show it in the email field.
In the controller, set the users email on the userEmail object (before the page is rendered).
Add the attribute th:value="userEmail" to the input field in the template
I am working with Spring Security version 4.2.3.RELEASE
Use csrf is mandatory.
I used how reference the following for the login.jsp file, 5.3 Java Configuration and Form Login, thus I have:
<body>
<spring:url var="loginUrl" value="/perform_/login"/>
<form name="login" action="${loginUrl}" method="POST">
<fieldset class="fieldset">
<legend><spring:message code="login.legend"/></legend>
<c:if test="${param.error != null}">
<p class="error"><spring:message code="login.invalid"/></p>
</c:if>
<c:if test="${param.logout != null}">
<p><spring:message code="logout.valid"/></p>
</c:if>
<table>
.... fields for username and password and submit button ...
<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/>
</form>
in other .jsp page to logout purposes exists:
<spring:url var="logoutUrl" value="/perform/logout" />
<form id="logoutForm" action="${logoutUrl}" method="post">
<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/>
<spring:message code="logout.title"/>
</form>
<script>
function formSubmit() {
document.getElementById("logoutForm").submit();
}
</script>
Finally through Javaconfig for Spring Security the following exists:
.formLogin()
.loginPage("/perfom/login")
.loginProcessingUrl("/perform_/login")
.usernameParameter("username")//default
.passwordParameter("password")//default
.defaultSuccessUrl("/welcome")
.failureUrl("/perfom/login?error") //default is /login?error
.permitAll()
.and()
.logout()
.logoutUrl("/perform/logout")//default is /logout
.logoutSuccessUrl("/perfom/login?logout")//default is /login?logout
.invalidateHttpSession(true)
.deleteCookies("JSESSIONID");
Note: /perfom/login is used in:
#Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/message").setViewName("general/message");
registry.addViewController("/welcome").setViewName("general/welcome");
registry.addViewController("/perfom/login").setViewName("login/login");
}
When the login page is loaded and either username or password values are incorrects the same login page is loaded again and the error message appears. Therefore <c:if test="${param.error != null}"> works fine.
The problem is when the logout event happens it goes to the login.jsp page how is expected but the logout message does not appear. But if in that moment I try to do a login with valid values the same login.jsp page is loaded again and just then the logout message appears.
I did a research and 'seems' correct my configuration, even according with this:
How to get the logout message in custom login page
What missing configuration is need it?
TL; DR You need to add another permitAll() call after deleteCookies("JSESSIONID").
As per documentation permitAll() for FormLoginConfigurer
Ensures the urls for failureUrl(String) as well as for the HttpSecurityBuilder, the getLoginPage and getLoginProcessingUrl are granted access to any user.
But you need to grant access to logoutSuccessUrl as well (to be fair access to logoutUrl is also needed but prerequisite for logout is that user is authenticated).
So what happens in your case is this:
You perform logout and get redirect to logoutSuccessUrl in response;
You dont have access to logoutSuccessUrl so normal process kicks in: url is saved to session and you get another redirect to login page (without parameter);
When you perform login you get redirect to saved logoutSuccessUrl and finally see your message.
I want to place the Login Form of the generated Login View from the Grails Spring Security Plugin at the main layout in layouts/main.gsp. I just copied it over, but it doesn't work, because of cause, now no controller is available to pass the form data to. The form-code looks like this:
<form action='${postUrl}' method='POST' id='loginForm' class='cssform' autocomplete='off'>
<p>
<label for='username'><g:message code="springSecurity.login.username.label"/>:</label>
<input type='text' class='text_' name='j_username' id='username'/>
</p>
<p>
<label for='password'><g:message code="springSecurity.login.password.label"/>:</label>
<input type='password' class='text_' name='j_password' id='password'/>
</p>
<p id="remember_me_holder">
<input type='checkbox' class='chk' name='${rememberMeParameter}' id='remember_me' <g:if test='${hasCookie}'>checked='checked'</g:if>/>
<label for='remember_me'><g:message code="springSecurity.login.remember.me.label"/></label>
</p>
<p><input type='submit' id="submit" value='${message(code: "springSecurity.login.button")}'/></p>
</form>
How should I change this code, so that I send the form code to the Login auth action?
Thanks.
As I udenrstand, your question is what to use for form action? postUrl should be same as grails.plugins.springsecurity.apf.filterProcessesUrl property in config, and by default it's /j_spring_security_check.
If you didn't change this value, you can use /j_spring_security_check instead of ${postUrl}.
Spring Securty Plugin have special filter that handles this URL, and authorizes user. Next steps are depends on configuration, but if I remember correctly, by default it redirects user to /.
See configuration options at http://grails-plugins.github.io/grails-spring-security-core/guide/urlProperties.html