How to authenticate and redirect a user to his 'own' page in Jersey REST service - rest

How to authenticate and redirect a user to his own page i.e to www.mysite.com/"user's email".
I am using the following algo which is not working...
userDB in User class:
Map<String,String> userdata=new HashMap<String,String>();
First my login process form :
#Path("/login")
#POST
#Produces(MediaType.TEXT_HTML)
#Consumes(MediaType.APPLICATION_FORM_URLENCODED)
public void login(
#FormParam("email") String emailc,
#FormParam("password") String pass,
#Context HttpServletResponse servletResponse
) throws IOException,RuntimeException {
User u1=new User();
pass=u1.getPassword();
emailc=u1.getEmailaddrs();
boolean checked=false;
boolean exists;
exists=u1.userdata.containsKey(emailc);
if(exists){
String mypass =u1.userdata.get(emailc);
if(mypass==pass){
checked=true;
}else{
checked=false;
}
}else{
checked=false;
}
if(!checked){
//User Doesn't exists
servletResponse.sendRedirect("http://localhost:8080/MySite/pages/Create_Profile.html");
}else{
servletResponse.sendRedirect("http://localhost:8080/MySite/{email}"); <<<< How to redirect using #FormParam("email")
}
}
createprofile
#POST
#Produces(MediaType.TEXT_HTML)
#Consumes(MediaType.APPLICATION_FORM_URLENCODED)
public void newUser(
#FormParam("email") String email,
#FormParam("password") String password,
#Context HttpServletResponse servletResponse
) throws IOException {
User u = new User(email,password);
User.userdata.put(email,password);
}

Your usage of userdata [Map] looks wrong to me. Is it a part of user class, is it non static or static ?
If it is non static then every time you will do new User() .. that map will be initialized and it will have no data in it. Hence u1.userdata.containsKey(emailc); will be always false.
If you are using a hashmap as a temporary database for dev purposes then, make it static rather keep it in a different class like UserStore or some DB access layer. Exmaple below:
public class UserDAO(){
private static Map<String,User> userdata = new HashMap<String,User>();
public boolean hasUser(String email){
return userdata.contains(email);
}
public User saveUser(String email, String password ...){
//make user object save it in map and return the same
}
// more methods for delete and edit etc.
}
And use this in your REST layer classes like this
exists = userDao.hasUser(email);
Advantages :
Your problem will be solved.
Later on when you move to actual db implementation you will just have to change your UserDao code and rest application code will be just fine. -- Loose coupling :)
Also regarding forward using email
servletResponse.sendRedirect("http://localhost:8080/MySite/{email}"); <<<< How to redirect using #FormParam("email")
add the email parameter there in the url only, if thats what you want:
servletResponse.sendRedirect("http://localhost:8080/MySite/"+emailc);
UPDATE :
See the fundamental thing is that you get request parameters [email , password]. You check it whether it is present in map or not. Now what you are doing wrong here is you create a new user like this User u = new User(); and then get email and password from it emailc = u.getEmail();. This emailc will always be null and your userdata map will always return false for that. You have two choices :
Either set email and password in user object and then get the data from user object.
Use the email and password obtained from request parameters for your logic. Do not alter them
One good practice to follow while programming is that at all times think of your method parameters as final parameters.
UPDATE 2 :
if(mypass==pass){
checked=true;
}else{
checked=false;
}
Change == to equals method. String matching should be done by equals or equalsIgnoreCase method not ==.

You always create a new User without any parameters: User u1=new User();. All these User instances will have the same property values and probably exists is always false.

Related

How to storage and get token when custom ClientDetailsService?

This is my code.
The clientService implements ClientDetailsService , but not found the token storage.
How to storage and get token when custom(e.g. database) ClientDetailsService?
When we have a custom implementation of ClientDetailsService, we essentially override its loadClientByClientId(..) method. This method takes clientId in parameter i.e. the username of the client. In that custom implementation class, all we need to do is check if the given client name exists in database or not. If it does exist, then load all its data and return the object. This class needs be injected with DAO or Repository's dependency to talk to database.
#Override
public ClientDetails loadClientByClientId(final String clientId) throws ClientRegistrationException {
Objects.requireNonNull(clientId, "Client ID must not be null");
final com.ex.auth.domain.ClientDetails clientDetails = clientDetailsRepository.findOne(clientId);
if (clientDetails == null) {
throw new NoSuchClientException(String.format("Client %s does not exist.", clientId));
}
return convertToDmo(clientDetails);
}

custom Shiro realm - who does the actual authentication

when sub classing shiro's AuthorizingRealm (or only AuthenticationRealm) by overriding
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
}
Is it my job to check that the credentials provided in the AuthenticationToken actually match?
Or am I supposed to return the AuthenticationInfo with the principals resolved from the AuthenticationToken and the correct password for the given credentials and shiro will compare them on its own somewhere within the flow of the Subject.login(AuthenticationToken) call?
The Javadocs for AuthenticatingRealm.doGetAuthenticationInfo() state (emphasis mine):
Retrieves authentication data from an implementation-specific datasource (RDBMS, LDAP, etc) for the given authentication token.
For most datasources, this means just 'pulling' authentication data for an associated subject/user and nothing more and letting Shiro do the rest. But in some systems, this method could actually perform EIS specific log-in logic in addition to just retrieving data - it is up to the Realm implementation.
The method AuthenticatingRealm.getAuthenticationInfo() first calls doGetAuthenticationInfo() then subsequently calls assertCredentialsMatch() using the configured credentialsMatcher:
public final AuthenticationInfo getAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
AuthenticationInfo info = getCachedAuthenticationInfo(token);
if (info == null) {
//otherwise not cached, perform the lookup:
info = doGetAuthenticationInfo(token);
log.debug("Looked up AuthenticationInfo [{}] from doGetAuthenticationInfo", info);
if (token != null && info != null) {
cacheAuthenticationInfoIfPossible(token, info);
}
} else {
log.debug("Using cached authentication info [{}] to perform credentials matching.", info);
}
if (info != null) {
assertCredentialsMatch(token, info);
} else {
log.debug("No AuthenticationInfo found for submitted AuthenticationToken [{}]. Returning null.", token);
}
return info;
}
So depending on how typical your Realm implementation is, you might want to avoid checking the AuthenticationToken's credentials in the doGetAuthenticationInfo() method, because the getAuthenticationInfo() template method already contains a step to ensure the submitted credentials match.
To specifically address your question if it is your responsibility "to check that the credentials provided in the AuthenticationToken actually match", the answer is yes, but not in the doGetAuthenticationInfo() method. Typically you would perform the credentials comparison within an implementation of the CredentialsMatcher interface, as described here.
Inside doGetAuthenticationInfo(...) you need to verify that the user has provided you with authentication proof.
Here is a pseudo-coded example of what you might do:
protected AuthenticationInfo doGetAutheticationInfo(AuthenticationToken token) {
if(token instanceof UsernamePasswordToken) {
String username = token.getUsername();
// Look up the user by the provide username
UserRecord userRecord = lookupUserRecord(username);
// No record found - don't know who this is
if (userRecord == null) {
throw new UnknownAccountException();
}
// Check for other things, like a locked account, expired password, etc.
// Verify the user
SimpleAuthenticationInfo sai = new SimpleAuthenticationInfo(userRecord.getPrincipal(), userRecord.getHashedCredentials(), userRecord.getCredentialsSalt(), getName());
boolean successfulAuthentication = getCredentialsMatcher().doCredentialsMatch(token, sai);
if(successfulAuthentication) {
// Check for anything else that might prevent login (expired password, locked account, etc
if (other problems) {
throw new CredentialsException(); // Or something more specific
}
// Success!
return sai;
} else {
// Bad password
throw new IncorrectCredentialsException();
}
}
// Don't know what to do with this token
throw new CredentialsException();
}
You'll have to write lookupUserRecord(username) or something similar to go lookup the user information including his hashed and salted credentials.
doGetAuthenticationInfo is the main method where authentication is done. SO if you override it generally you are overriding authentication process. If you want to use the process that was defined for that reealm and do some extra things better call super class method first then get its info and then use it so you will not have to change anything. Also in case of jdbcrealm sqls in shiro.ini are automatically mapped. and they will not be changed until you override
setAuthenticationQuery, setUserRolesQuery, etc
You can easily call following method to simulate the actual process then customize it.
AuthenticationInfo info = super.doGetAuthenticationInfo(token);
Note, that super is a reference to the parent, but super() is it's constructor.
like:
public class CustomJdbcRealm extends JdbcRealm
{
#Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException
{
AuthenticationInfo info = super.doGetAuthenticationInfo(token);
// Your own code here
}
}

Issues with CurrentUserPropertyBinder it cannot always remember user

I have implemented a CurrentUserPropertyBinder (see below) for a web application using FubuMVC.
public class CurrentUserPropertyBinder : IPropertyBinder
{
private readonly Database _database;
private readonly ISecurityContext _security;
public CurrentUserPropertyBinder(Database database, ISecurityContext security)
{
_database = database;
_security = security;
}
public bool Matches(PropertyInfo property)
{
return property.PropertyType == typeof(User)
&& property.Name == "CurrentUser";
}
public void Bind(PropertyInfo property, IBindingContext context)
{
var currentUser = //check database passing the username to get further user details using _security.CurrentIdentity.Name
property.SetValue(context.Object, currentUser, null);
}
}
When I login to my site, this works fine. The CurrentUserPropertyBinder has all the information it requires to perform the task (i.e. _security.CurrentIdentity.Name has the correct User details in it)
When I try and import a file using fineUploader (http://fineuploader.com/) which opens the standard fileDialog the _security.CurrentIdentity.Name is empty.
It doesn't seem to remember who the user was, I have no idea why. It works for all my other routes but then I import a file it will not remember the user.
Please help! Thanks in Advance
NOTE: We are using FubuMVC.Authentication to authenticate the users
I'm guessing your action for this is excluded from authentication; perhaps it's an AJAX-only endpoint/action. Without seeing what that action looks like, I think you can get away with a simple fix for this, if you've updated FubuMVC.Authentication in the past 3 months or so.
You need to enable pass-through authentication for this action. Out of the box, FubuMVC.Auth only wires up the IPrincipal for actions that require authentication. If you want access to that information from other actions, you have to enable the pass-through filter. Here are some quick ways to do that.
Adorn your endpoint/controller class, this specific action method, or the input model for this action with the [PassThroughAuthentication] attribute to opt-in to pass-through auth.
[PassThroughAuthentication]
public AjaxContinuation post_upload_file(UploadInputModel input) { ... }
or
[PassThroughAuthentication]
public class UploadInputModel { ... }
Alter the AuthenticationSettings to match the action call for pass-through in your FubuRegistry during bootstrap.
...
AlterSettings<AuthenticationSettings>(x => {
// Persistent cookie lasts 3 days ("remember me").
x.ExpireInMinutes = 4320;
// Many ways to filter here.
x.PassThroughChains.InputTypeIs<UploadInputModel>();
});
Check /_fubu/endpoints to ensure that the chain with your action call has the pass-through or authentication filter applied.

Is this the right way to do stateless authentication per call on ServiceStack?

I have REST service requirements in which some calls require authentication and some don't. Absolutely no state is used, as the calls are all independent from one another. I have put something together which seems to work, but is this the right way to go about not using sessions?
This question is kind of related to my WCF question which is answered here.
Firstly I registered the authentication method:
Plugins.Add(new AuthFeature(() => new AuthUserSession(),
new IAuthProvider[] {
new CustomCredentialsAuthProvider(), //HTML Form post of UserName/Password credentials
}
));
I then attribute the respective calls (or service or DTO) with the Authenticate attribute:
[Authenticate]
public HelloResponse Post(Hello request)
{
return new HelloResponse { Result = "Hello, " + request.Name + " with POST & Auth"};
}
I inherit from the BasicAuthProvider class which does the authentication:
public class CustomCredentialsAuthProvider : BasicAuthProvider
{
public override bool TryAuthenticate(IServiceBase authService, string userName, string password)
{
return userName == "dylan" && password == "abc123";
}
public override void OnAuthenticated(IServiceBase authService, IAuthSession session, IOAuthTokens tokens, Dictionary<string, string> authInfo)
{
session.IsAuthenticated = true;
//Important: You need to save the session!
authService.SaveSession(session, new TimeSpan(0,0,10));
}
}
As you can see, I do save the session but it times out after 10 seconds. This is the part that I'm sure can potentially be done better. It seems to work nicely though.
Is there a better way of doing what I'm trying to accomplish?
Is there also any way, due to the sessionless nature of these services, to remove the Auth, AssignRoles and UnassignRoles methods?
If you wanted to keep using ServiceStack's Authentication and Session support you could just add a response filter that clears the user session after the service is executed, e.g:
this.ResponseFilters.Add((req, res, dto) => req.RemoveSession());
Basically after each request is executed it clears the session, so no record of them having authenticated exists.
Otherwise you can just skip using ServiceStack's Authentication completely and just provide your own via RequestFitlers of FilterAttributes (which is essentially what SS Auth does under the hood).

Handling sessions in JSF while working with socialauth API, for login

I have been working with social auth API in JSF, for getting an login with facebook, I dont know whether am creating a session properly. I have searched some stuffs form internet and doing it. Now i have caught up with some error.
according to social auth first we need to call a function, which helps to get the authentication URL from the Facebook, where i need to create a session and and set attributes to it, with the parameters from facebook once user logs in into the facebook.
so my first view page will just contain,
a command button to call the respective function.
<h:form><h:commandButton value="submit" action="#{socialNetworkAuthentication.facebookAuthentication}"></h:commandButton></h:form>
then the function which is called ...
public String facebookAuthentication(){
try{
//Create an instance of SocialAuthConfgi object
SocialAuthConfig config = SocialAuthConfig.getDefault();
String propUrl="oauth_consumer.properties";
//load configuration. By default load the configuration from oauth_consumer.properties.
//You can also pass input stream, properties object or properties file name.
config.load(propUrl);
//Create an instance of SocialAuthManager and set config
SocialAuthManager manager = new SocialAuthManager();
manager.setSocialAuthConfig(config);
//URL of YOUR application which will be called after authentication
String successUrl = "http://chennaivolunteers.com/ChennaiVolunteers/faces/cv/employee-profile.xhtml";
// get Provider URL to which you should redirect for authentication.
// id can have values "facebook", "twitter", "yahoo" etc. or the OpenID URL
String url = manager.getAuthenticationUrl("facebook", successUrl);
// Store in session
HttpServletRequest request=(HttpServletRequest) FacesContext.getCurrentInstance().getExternalContext().getRequest();
HttpSession ses = request.getSession(true);
ses.setAttribute("authManager", manager);
System.out.println(url);
FacesContext.getCurrentInstance().responseComplete();
FacesContext.getCurrentInstance().getExternalContext().redirect(url);
}
then finally i redirect to the respective URL given by the facebook, after user logs in into the facebook, then it automatically moves to the succesURL which is was mentioned in the above code.
In my successURL i just have an outputtext.
<tr><td class="profile-head"><h:outputText id="name" value="#{employeeProfile.profileName}" /></td></tr>
<tr><td class="content-black">
<div class="padding-2"><h:outputText id="name" value="#{employeeProfile.profileName}" />
In the backing bean, i created a session to get the attributes which i set earlier.
public class EmployeeProfile {
public String profileName;
public String getProfileName() throws Exception {
HttpServletRequest request=(HttpServletRequest) FacesContext.getCurrentInstance().getExternalContext().getRequest();
HttpSession ses = request.getSession(true);
SocialAuthManager m = (SocialAuthManager)ses.getAttribute("authManager");
AuthProvider provider = m.connect(SocialAuthUtil.getRequestParametersMap(request));
Profile p = provider.getUserProfile();
String userName=p.getFirstName();
System.out.println(userName);
return userName;
}
public void setProfileName(String profileName) {
this.profileName = profileName;
}
when i printed the username in console it does, but its not the view page of this backing bean, have caught up with two exceptions as below.
1. javax.faces.FacesException: Could not retrieve value of component with path : {Component-Path : [Class: javax.faces.component.UIViewRoot,ViewId: /cv/employee-profile.xhtml][Class: javax.faces.component.html.HtmlOutputText,Id: name]}
Caused by: javax.el.ELException: /cv/employee-profile.xhtml at line 133 and column 105 value="#{employeeProfile.profileName}": Error reading 'profileName' on type socialServlet.EmployeeProfile
2.javax.faces.FacesException: This is not the same SocailAuthManager object that was used for login.Please check if you have called getAuthenticationUrl() method before calling connect()
Caused by: This is not the same SocailAuthManager object that was used for login.Please check if you have called getAuthenticationUrl() method before calling connect()
Last one is just an inbuilt exception of social auth API,
But i dont think any problem in this, because when i try it out with servlet, everything works fine, i think am doing some mistake in JSF session. But i dont know wher i am wrong.
My problem is now rectified.. the mistake i did is, i have invoked the connect() function again. Now i have did everything in the constructor itself. It works fine.
public class EmployeeProfile {
public EmployeeProfile() throws Exception {
// TODO Auto-generated constructor stub
ExternalContext ectx = FacesContext.getCurrentInstance().getExternalContext();
HttpServletRequest request = (HttpServletRequest)ectx.getRequest();
HttpSession session = request.getSession(true);
SocialAuthManager m = (SocialAuthManager)session.getAttribute("authManager");
AuthProvider provider = m.connect(SocialAuthUtil.getRequestParametersMap(request));
Profile p = provider.getUserProfile();
String userName=p.getFirstName();
System.out.println(userName);
setProfileName(userName);
setBirthDate(p.getDob());
setImageUrl(p.getProfileImageURL());
p.getGender();
}