How to navigate to different pages on the basis of query params by jsf page initialization in the corresponding controller - jsf

#Factory("loginContext")
#Begin(join = true)
public LoginContext initLoginContext() {
if (loginContext == null) {
loginContext = new LoginContext();
}
loginContext.setLanguageCode(LocaleSelector.instance().getLanguage());
checkEnvironment();
Map<String,String> requestParams = FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap();
String prodCode=requestParams.get("prodCode");
String token=requestParams.get("token");
//token validation
if (token.equals("admin")) {
System.out.println("admin page");
} else if (token.equals("user")) {
System.out.println("user page");
} else {
return loginContext;
}
}
here i will be getting user credentials in token(JWE string) and then some validation of on user is done(till here code is fine and i am clear how to do this). later on on the basis of user privilege, i will navigate directly to related page for user(instead of loading the login page related to controller)
I am stuck here, Pls suggest something

in the LoginController i added following code which worked for me.:
#Factory("loginContext")
#Begin(join = true)
public LoginContext initLoginContext() {
if (loginContext == null) {
loginContext = new LoginContext();
}
loginContext.setLanguageCode(LocaleSelector.instance().getLanguage());
Map<String,String> requestParams =
FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap();
String prodCode=requestParams.get("prodCode");
String token=requestParams.get("token");
//token validation
loginContext.setToken(token);
loginContext.setProductCode(prodCode);
return loginContext;
}
#Factory(value = "redirectWelcome", autoCreate = true, scope = ScopeType.EVENT)
public boolean isRedirectWelcome()
{
boolean welRet=false;
if(loginContext.isLoggedIn()==false)
{
String loginReturn=login();// login is customized method as per my requirement
if(loginReturn.equals("loggedIn"))
{
FacesContext.getCurrentInstance().getApplication().getNavigationHandler().handleNavigation(FacesContext.getCurrentInstance(),
null, "/myservice/auth/showWelcome/welcome.jspx?faces-redirect=true");
loginContext.setLoggedIn(true);
welRet=true;
}}
return welRet;
}
then In JSP page(login.jspx) i added following in the body.
<h:outputText value="Login bypass..." rendered="#{loginController.redirectWelcome}" />

Related

Test Method Implementation in jhipster

I need to implement a test method to cover the following method. But it is not compulsory to cover it for 100% coverage.
#DeleteMapping("/users/{login:" + Constants.LOGIN_REGEX + "}")
#Timed
#Secured({AuthoritiesConstants.ADMIN, AuthoritiesConstants.STUDENT})
public ResponseEntity<Void> deleteUser(#PathVariable String login) {
log.debug("REST request to delete User: {}", login);
boolean hasAuthorityStudent = false;
boolean hasAuthorityAdmin = false;
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
Collection<? extends GrantedAuthority> authorities = authentication.getAuthorities();
hasAuthorityAdmin = authorities.contains(new SimpleGrantedAuthority(AuthoritiesConstants.ADMIN));
hasAuthorityStudent = authorities.contains(new SimpleGrantedAuthority(AuthoritiesConstants.STUDENT));
if (hasAuthorityAdmin) {
// delete user
userService.deleteUser(login);
return ResponseEntity.ok().headers(HeaderUtil.createAlert("userManagement.deleted", login)).build();
} else {
//get the authorities of the user who is going to be deleted
Optional<User> user = userService.getUserWithAuthoritiesByLogin(login);
Set<Authority> currentUserAuthorities = user.get().getAuthorities();
log.debug("REST request to delete User: {}", user);
log.debug("REST request to delete Member: {}", currentUserAuthorities);
boolean hasDeletedMembByStu = false;
if (hasAuthorityStudent) {
for (Authority auth : currentUserAuthorities) {
// delete user if it is a student
if (auth.getName().equals(AuthoritiesConstants.MEMBER)) {
userService.deleteUser(login);
hasDeletedMembByStu = true;
}
}
if (hasDeletedMembByStu) {
return ResponseEntity.ok().headers(HeaderUtil.createAlert("userManagement.deleted", login)).build();
}
}
return ResponseEntity.badRequest()
.headers(HeaderUtil.createFailureAlert(ENTITY_NAME, "AccessDenied", "Lecturer can delete only members"))
.body(null);
}
}
I an using 4.8.2 as the jhipster version. I have attempted as follows.
#Test
#Transactional
public void deleteUser() throws Exception {
// Initialize the database
userRepository.saveAndFlush(user);
userSearchRepository.save(user);
restUserMockMvc.perform(delete("/api/users/{login}", user.getLogin())
.contentType(TestUtil.APPLICATION_JSON_UTF8))
.andExpect(status().isBadRequest());
}
There user is initialized with ROLE_USER. Then generated a build failure of the test method saying java.lang.AssertionError: Status expected:<400> but was:<500&gt
You are not logged in so authentication is null and authentication.getAuthorities() throws a NullPointerException.
To fix that you need to apply Spring-Security like here and assign a user and roles to your request like here.
Other note : instead of calling SecurityContextHolder.getContext().getAuthentication() you can get the principal directly in the controller method :
ResponseEntity<Void> deleteUser(#PathVariable String login, Principal principal) {
log.debug("REST request to delete User: {}", login);
boolean hasAuthorityStudent = false;
boolean hasAuthorityAdmin = false;
if (principal != null) {
Collection<? extends GrantedAuthority> authorities = principal.getAuthorities();
...

query string param is not url-encoded inside asp.net mvc action

I'm calling ResetPassword action from an Email (ASP.NET MVC 5).
http://localhost:34162/Account/ResetPassword?code=BwEA181bAECFMcn1vwPdrctS/wcyncKPxGT9Zx1tDuPwKGpe9H1W7LI3Zm9fM+3aA5Fok5GhLPBHqbtiGfpL8Cmdx7RNC6RJ7d6t9ZgFBwgwYk3zssU1Nh64PWHJAabVG9Wv9VWDNdj+Fz0UA712XA==
This is the address in my Browser.
However, in debug I receive this string in the ResetPassword Action:
// GET: /Account/ResetPassword
[AllowAnonymous]
public ActionResult ResetPassword(string code)
{
return code == null ? View("Error") : View();
}
The 'code' is:
BwEA181bAECFMcn1vwPdrctS/wcyncKPxGT9Zx1tDuPwKGpe9H1W7LI3Zm9fM 3aA5Fok5GhLPBHqbtiGfpL8Cmdx7RNC6RJ7d6t9ZgFBwgwYk3zssU1Nh64PWHJAabVG9Wv9VWDNdj Fz0UA712XA==
i.e., it is not url-encoded and of course password is not reset with invalid token message.
What can I do for getting the right string in the Action?
You can encode the string in the following way:
[AllowAnonymous]
public ActionResult ResetPassword(string code)
{
code = Server.HtmlEncode(code);
}
Fore more information on how to encode you can look at
https://msdn.microsoft.com/en-us/library/w3te6wfz(v=vs.110).aspx
I still don't know what was the problem. Looks like it shouldn't have worked in the first place. I wish I knew why Microsoft feel the need to use tokens with slashes and pluses.
Anyway, I just Base64 encoded and decoded the token as follows:
before sending the Email to the user:
...
string code = await UserManager.GeneratePasswordResetTokenAsync(user.Id);
code = CommonFuncs.Base64Encode(code);
EmailsBL.PasswordResetEmail(model.Email, code); <-- emailing the link for password rest to the user
And then when receiving:
// POST: /Account/ResetPassword
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<ActionResult> ResetPassword(ResetPasswordViewModel model)
{
/////////////////////////////////////////////////////////////////////
// NOTE: if email is not CONFIRMED then reset password silently fails
////////////////////////////////////////////////////////////////////
if (!ModelState.IsValid)
{
return View(model);
}
model.Code = CommonFuncs.Base64Decode(model.Code);
i.e., decoding the token.
This following is just for completeness:
public static string Base64Encode(string plainText)
{
string base64string = null;
if (plainText != null)
{
var plainTextBytes = System.Text.Encoding.UTF8.GetBytes(plainText);
base64string = System.Convert.ToBase64String(plainTextBytes);
}
return base64string;
}
public static string Base64Decode(string base64EncodedData)
{
string decodedBase64String = null;
if (base64EncodedData != null)
{
var base64EncodedBytes = System.Convert.FromBase64String(base64EncodedData);
decodedBase64String = System.Text.Encoding.UTF8.GetString(base64EncodedBytes);
}
return decodedBase64String;
}

Getting UserId from MVC using WebMetrix

I'm using bellow login method to login in a MVC 5 application.
What I want to do is get the id of the user that is currently logged.
I tried to use these 2 methods:
// 1
// This one raise an exception:
Guid loggedUser = (Guid)Membership.GetUser().ProviderUserKey;
Additional information: Object reference not set to an instance of an
object.
// 2
// sets loggedUser variable to null
loggedUser = User.Identity.GetUserId();
// Login Method within Controller
public ActionResult Login(Login logindata, string ReturnUrl)
{
if (ModelState.IsValid)
{
if (WebSecurity.Login(logindata.Username, logindata.Password))
{
if (ReturnUrl != null)
{
return Redirect(ReturnUrl);
}
return RedirectToAction("Index", "Home");
}
}
ModelState.AddModelError("", "Sorry the username or password is invalid ");
return View(logindata);
}
My question is what I'm doing wrong and if it's possible to get the logged user id like this???
Thanks
I used this method and worked:
WebSecurity.GetUserId("loggedUser")

MVC Identity 2 using FormsAuthenticationTicket

I am replacing the (HttpContext.Current.User) IPrincipal with a custom version so I can store more information login and the user. I have done this before using the FormsAuthtenticationTicket, but those other ways were based on the Memberhipship and SimpleMembership providers.
My question is, can i use the FormsAuthenticationTicket to store the cookie of my ICustomPrincipal with it interfering or breaking in OWIN Identity Pipline? I feel like would i be mixing apples and oranges.
example save:
var user = userRepository.Users.Where(u => u.Email == viewModel.Email).First();
CustomPrincipalSerializeModel serializeModel = new CustomPrincipalSerializeModel();
serializeModel.UserId = user.Id;
serializeModel.FirstName = user.FirstName;
serializeModel.LastName = user.LastName;
JavaScriptSerializer serializer = new JavaScriptSerializer();
string userData = serializer.Serialize(serializeModel);
FormsAuthenticationTicket authTicket = new FormsAuthenticationTicket(
1,
viewModel.Email,
DateTime.Now,
DateTime.Now.AddMinutes(15),
false,
userData);
string encTicket = FormsAuthentication.Encrypt(authTicket);
HttpCookie faCookie = new HttpCookie(FormsAuthentication.FormsCookieName, encTicket);
Response.Cookies.Add(faCookie);
example retrieve:
protected void Application_PostAuthenticateRequest(Object sender, EventArgs e)
{
HttpCookie authCookie = Request.Cookies[FormsAuthentication.FormsCookieName];
if (authCookie != null)
{
FormsAuthenticationTicket authTicket = FormsAuthentication.Decrypt(authCookie.Value);
JavaScriptSerializer serializer = new JavaScriptSerializer();
CustomPrincipalSerializeModel serializeModel = serializer.Deserialize<CustomPrincipalSerializeModel>(authTicket.UserData);
CustomPrincipal newUser = new CustomPrincipal(authTicket.Name);
newUser.UserId = serializeModel.UserId;
newUser.FirstName = serializeModel.FirstName;
newUser.LastName = serializeModel.LastName;
HttpContext.Current.User = newUser;
}
}
EDIT
I have this for the creating the claim
public ClaimsIdentity CreateIdentity(
LoginAttempt loginAttempt)
{
UserProfile userProfile = GetUserProfile(loginAttempt.UserName);
var applicationUser = FindById(userProfile.AspNetUserId);
ClaimsIdentity identity;
try
{
identity = UserManager.CreateIdentity(applicationUser, DefaultAuthenticationTypes.ApplicationCookie);
}
catch (Exception ex)
{
_log.Error(ex.Message, ex);
return null;
}
//UserManager.GetClaims()
identity.AddClaim(new Claim("LoginAttemptId", loginAttempt.LoginAttemptId.ToString(),ClaimValueTypes.String));
identity.AddClaim(new Claim("UserProfileId", loginAttempt.UserProfileId.ToString(), ClaimValueTypes.String));
identity.AddClaim(new Claim("SubscriptionType", userProfile.SubscriptionType, ClaimValueTypes.String));
IList<string> roles= UserManager.GetRoles(applicationUser.Id);
identity.AddClaim(new Claim(ClaimTypes.Role, roles.First()));
return identity;
}
and this for extracting
public static long GetLoginAttemptId(this IIdentity principal)
{
var claimsPrincipal = principal as ClaimsIdentity;
if (claimsPrincipal == null)
{
//throw new Exception("User is not logged in!");
return -1;
}
var nameClaim = claimsPrincipal.Claims.FirstOrDefault(c => c.Type == "LoginAttemptId");
if (nameClaim != null)
{
return Convert.ToInt64( nameClaim.Value);// as long;
}
return -1;
}
EDIT
These are the claims I am getting. I have logged off and logged back in.
There are Claims that serve exactly the same purpose. Only new API is actually purposed this way.
Claims are a basically a Dictionary<String, String> that is stored in auth-cookie and available through IPrincipal. But you don't need to do ICustomPrincipal because actual object that you get behind IPrincipal is ClaimsPrincipal and that has a list of claims.
You'd add extra information to Idnentity object just before the login:
public async override Task CreateIdentityAsync(ApplicationUser applicationUser)
{
var identity = await base.CreateIdentityAsync(applicationUser, DefaultAuthenticationTypes.ApplicationCookie);
identity.AddClaim(new Claim("MyApp:FullName", applicationUser.FullName));
return identity;
}
And then you'd be able to get this data out from IPrincipal via extension:
public static String GetFullName(this IPrincipal principal)
{
var claimsPrincipal = principal as ClaimsPrincipal;
if (claimsPrincipal == null)
{
throw new Exception("User is not logged in!");
}
var nameClaim = principal.Claims.FirstOrDefault(c => c.Type == "MyApp:FullName");
if (nameClaim != null)
{
return nameClaim.Value;
}
return String.Empty;
}
I have used this method successfully in a few projects already. See other similar answers for more code samples.
Here is another article, though I discourage from using Thread.CurrentPrincipal or ClaimsPrincipal.Current in MVC application - you don't always get what you expect, especially when user is not logged in or on early stages of AppPool start up.
This approach works for me (Using MVC4), slightly different from above.
public class ApplicationUser : IdentityUser
{
public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser> manager)
{
// Note the authenticationType must match the one defined in CookieAuthenticationOptions.AuthenticationType
var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie);
// Add custom user claims here
userIdentity.AddClaim(new Claim("MyApp:OrganizationId", OrganizationID.ToString()));
return userIdentity;
}
public int OrganizationID { get; set; }
}
Extension method. Note you should use claimsPrincipal variable (instead of principal variable) to obtain the claims. I think that's a little mistake in the excelent answer of #trailmax (sorry for not comment this in your answer, my reputation doesn't allow me). Also, I use IIdentity instead of IPrincipal
public static class IdentityExtensions
{
public static int GetOrganizationId(this IIdentity principal)
{
var claimsPrincipal = principal as ClaimsIdentity;
if (claimsPrincipal == null)
{
throw new Exception("User is not logged in!");
}
var nameClaim = claimsPrincipal.Claims.FirstOrDefault(c => c.Type == "MyApp:OrganizationId");
if (nameClaim != null)
{
return int.Parse(nameClaim.Value);
}
throw new Exception("ID doesn't exists");
}
}
And then, I use the extension method in the controller like this:
var organizationId = User.Identity.GetOrganizationId();
Hope this is useful to someone.

Liferay Autologin Hook produces 'Your request failed to complete' in portlet

I've done a custom Autologin Filter which seems to works well, but when Liferay redirects to the main page (once the user has been authenticated), the login portlet shows an error that I cannot understand.
The error shows "Your request failed to complete", but the user has been successfully logged and if I press F5 or navigate through the page, the error disappear.
My Autologin class implementation is:
public String[] login(HttpServletRequest request,
HttpServletResponse response) throws AutoLoginException {
String[] credentials = new String[3];
String p_id = request.getParameter("p_p_id");
String userName = null;
String password = null;
if (p_id != null) {
userName = request.getParameter("_" + p_id + "_login");
password = request.getParameter("_" + p_id + "_password");
//Custom authentication code required [...]
}
if (userName != null) {
// New Login
try {
//We log as Test user...just for TEST
long companyId = PortalUtil.getCompanyId(request);
User user = UserLocalServiceUtil.getUserByScreenName(companyId, "Test");
long userId = user.getUserId();
String userPwd = user.getPassword();
credentials[0] = Long.toString(userId);
credentials[1] = userPwd;
credentials[2] = Boolean.FALSE.toString();
} catch (Exception e) {
e.printStackTrace();
throw new AutoLoginException(e);
}
return credentials;
}
return credentials;
}
I've also implemented a Custom Authenticator which always return SUCCESS.
Do you have any idea about what I'm doing wrong?
Thank you very much in advance!
Ivan fontanals

Resources