java.lang.IllegalStateException: No user is currently signed in - java

I have been try to integrate social login in my spring application. Previously I had encountered errors like no bean name facebook and connectionRepository. Once I integrated code from https://github.com/spring-social/spring-social-google-example, specially socialConfig and other files , I was able to move forward. But still I get error, java.lang.IllegalStateException: No user is currently signed in, which exists on SecurityContext.java file where the getCurrentUser() method throws IllegalStateException, Even though I have set the currentUser from the SimpleSignInAdapter.signIn method.
For facebook user i have used the org.springframework.social.facebook.api.User and set SecurityContext.setCurrentUser(new User(userId, null, null, null, null, null));
Error occurs from ConnectionRepository.connectionRepository while calling User user = SecurityContext.getCurrentUser(). I have printed the value and it returns null and exception is thrown. I havent used threadlocal before and having difficulties working it. Is there another alternatives for threadlocal and any other possible solution ?
My SecurityContext class is as below
public final class SecurityContext {
private static final ThreadLocal<User> currentUser = new ThreadLocal<User>();
private static Logger logger = LoggerFactory.getLogger(SecurityContext.class);
public static User getCurrentUser() {
User user = currentUser.get();
if (user == null) {
throw new IllegalStateException("No user is currently signed in");
}
return user;
}
public static void setCurrentUser(User user) {
currentUser.set(user);
}
public static boolean userSignedIn() {
return currentUser.get() != null;
}
public static void remove() {
currentUser.remove();
}
}
The ThreadLocal currentUser is set from following class
public final class SimpleSignInAdapter implements SignInAdapter {
private final UserCookieGenerator userCookieGenerator = new UserCookieGenerator();
public String signIn(String userId, Connection<?> connection, NativeWebRequest request) {
User user= new User(userId, null, null, null, null, null);
SecurityContext.setCurrentUser(user);
userCookieGenerator.addCookie(userId, request.getNativeResponse(HttpServletResponse.class));
boolean flag = true;
if (flag) {
return "/signup";
}
return null;
}
}
Below is my connectionRepository method from socialConfig.class from where the error occurs while calling SecurityContext.getCurrentUser() which is null even thoogh the currentuser is set in above class.
#Bean
#Scope(value="request", proxyMode=ScopedProxyMode.INTERFACES)
public ConnectionRepository connectionRepository() {
User user = SecurityContext.getCurrentUser();
ConnectionRepositorycr=usersConnectionRepository().createConnectionRepository(user.getId());
logger.debug("cr==>"+cr);
return cr;
}

Related

SQL Permission with Java Authentication and Authorization Service

I have a SQL table user with 2 roles: ADMIN and USER.
I'm trying to use Java Authentication and Authorization Service(jaas) to make user with ADMIN role can read and modify other tables while USER role can read only.
I create a custom class extent java.security.Permission and a custom class extend
Policy class but I can't find any way to check permission with SecurityManager
PolicyImpl policy = new PolicyImpl();
Policy.setPolicy(policy);
Subject subject = loginContext.getSubject();
try {
Subject.doAsPrivileged(subject, (PrivilegedAction) () -> {
SecurityManager sm = System.getSecurityManager();
sm.checkSecurityAccess();
if (sm != null) {
sm.checkPermission(); // I don't know how to make this function check for
// SQL permission based on custom policy
}
return null;
}, null);
My Policy class
public class PolicyImpl extends Policy {
#Override
public PermissionCollection getPermissions(ProtectionDomain domain) {
List<Principal> principals = Arrays.asList(domain.getPrincipals());
if (principals.isEmpty()) {
return null;
}
BasicPermission basicPermission = null;
try {
for (Principal principal : principals) {
basicPermission = (BasicPermission) AccessController
.doPrivileged((PrivilegedExceptionAction) () -> Controller.getRoles(principal.getName()));
}
} catch (Exception ex) {
ex.printStackTrace();
return null;
}
return basicPermission.newPermissionCollection();
}
}
It seems that java.security.FilePermission is the most suitable one since this permission has read and write property but I don't know how can I use this class for SQL Server.

Create a global Realm file for a collaborative android app

My app is a collaborative app where users should be able to write/read into a global Realm file to share data between them. I would also like to include some initial data (realmObjects) in the Realm file which will be common to all users.
User will sign up to, then, be able to create data and share the data with all the users. The initial data, created only once, should be available to all users.
I am not able to assign user permissions (write/read) to each new user once they sign-up/login in the app. The common data is created multiple time since the query (realm.where(realmObject.class).findall() returns no results, even though it has been created.
public static final String AUTH_URL = "http://" + BuildConfig.OBJECT_SERVER_IP + ":9080/auth";
public static final String REALM_URL = "realm://" + BuildConfig.OBJECT_SERVER_IP + ":9080/default";
UserManager class
public class UserManager {
// Supported authentication mode
public enum AUTH_MODE {
PASSWORD,
FACEBOOK,
GOOGLE
}
private static AUTH_MODE mode = AUTH_MODE.PASSWORD; // default
public static void setAuthMode(AUTH_MODE m) {
mode = m;
}
public static void logoutActiveUser() {
switch (mode) {
case PASSWORD: {
break;
}
case FACEBOOK: {
LoginManager.getInstance().logOut();
break;
}
case GOOGLE: {
break;
}
}
SyncUser.currentUser().logout();
}
// Configure Realm for the current active user
public static void setActiveUser(SyncUser user) {
Realm.removeDefaultConfiguration();
SyncConfiguration defaultConfig = new SyncConfiguration.Builder(user, REALM_URL).name("Realm").schemaVersion(0).build();
Realm.setDefaultConfiguration(defaultConfig);
setDefaultPermissionsRealm(user);
}
private static void setDefaultPermissionsRealm(SyncUser user){
if (user.getIdentity().toString().equals(PRIVILAGE)){
Realm realm = user.getManagementRealm();
realm.executeTransaction(new Realm.Transaction() {
#Override
public void execute(Realm realm) {
Boolean mayRead = true; // Grant read access
Boolean mayWrite = true; // Keep current permission
Boolean mayManage = false; // Revoke management access
PermissionChange change = new PermissionChange(REALM_URL,
"*",
mayRead,
mayWrite,
mayManage);
realm.insert(change);
}
});
}
}
}
SplashActivity
SyncUser.loginAsync(SyncCredentials.usernamePassword(eMail, password, true), AUTH_URL, new SyncUser.Callback() {
#Override
public void onSuccess(SyncUser syncUser) {
loginRegistrationSuccess = true;
registrationComplete(syncUser);
}
#Override
public void onError(ObjectServerError error) {
loginRegistrationSuccess = false;
}
});
facebookAuthRegistration = new FacebookAuth((LoginButton) findViewById(R.id.sign_up_facebook), this) {
#Override
public void onRegistrationComplete(final LoginResult loginResult, User userInfo) {
UserManager.setAuthMode(UserManager.AUTH_MODE.FACEBOOK);
SyncCredentials credentials = SyncCredentials.facebook(loginResult.getAccessToken().getToken());
SyncUser.loginAsync(credentials, AUTH_URL, SplashScreenActivity.this);
}
};
googleAuthRegistration = new GoogleAuth((Button) findViewById(R.id.sign_up_google), this, googleAuthLogin.getmGoogleApiClient()) {
#Override
public void onRegistrationComplete(GoogleSignInResult result) {
UserManager.setAuthMode(UserManager.AUTH_MODE.GOOGLE);
GoogleSignInAccount acct = result.getSignInAccount();
SyncCredentials credentials = SyncCredentials.google(acct.getIdToken());
SyncUser.loginAsync(credentials, AUTH_URL, SplashScreenActivity.this);
}
};
#Override
public void onSuccess(SyncUser syncUser) {
loginRegistrationSuccess = true;
showProgress(false);
registrationComplete(syncUser);
}
private void registrationComplete(SyncUser syncUser) {
UserManager.setActiveUser(syncUser);
Intent mainIntent = new Intent(SplashScreenActivity.this, MainActivity.class);
mainIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
SplashScreenActivity.this.startActivity(mainIntent);
SplashScreenActivity.this.finish();
}
It looks like if I am creating a different realm for each user even though I am not including in the URL the "~".
Could anyone tell me what I am doing wrong?
Thanks
Initially, you will need to create the Realm using the admin user, and set the permissions for all other users can access it. If you are using the Pro edition, you could create the Realm using a small node.js script. Alternatively, you could create a small internal app with the single purpose of creating the Realm using the admin user.
Users are only allowed to create Realm within their home directory (~ so to speak) but they can share it with other users. Doing so, you will have to distribute the user id of that first user.

How to detect that the account is already login? [duplicate]

I have a login funcitonality in my application ,
where i am able to store the user in a session
and i am also able to stop user to signIn , if he is already Signed in on the same browser ..
But if a signedIn user tries to logIn again from a DIFFERENT browser i am not able to stop him .
here is the code..
I am using this
session=getThreadLocalRequest().getSession(true);
User loggedInUser = (User) session.getAttribute("user");
Now this loggedInUser have the user object if a loggedInUser tries to get in the application from the SAME browser in another tab (SO it works for me)
BUT this loggedInUser is null if a loggedInUser tries to get in the application from the DIFFERENT browser(SO its not working for me)
here is the code..
public User signIn(String userid, String password) {
String result = "";
ApplicationContext ctx = new ClassPathXmlApplicationContext(
"applicationContext.xml");
MySQLRdbHelper rdbHelper = (MySQLRdbHelper) ctx.getBean("ManagerTie");
User user = (User) rdbHelper.getAuthentication(userid, password);
if(user!=null)
{
session=getThreadLocalRequest().getSession(true);
User loggedInUser = (User) session.getAttribute("user");
if(loggedInUser != null && user.getId() == loggedInUser.getId()){
user.setId(0);
}else{
session=getThreadLocalRequest().getSession(true);
session.setAttribute("user", user);
}
}
return user;
I am using JAVA , GWT
Yes by storing static map on server side,Which stores User Id as a key and Session as value.
Here is working code from my bag directly.
class SessionObject implements HttpSessionBindingListener {
User loggedInUser;
Logger log = Logger.getLogger(SessionObject.class);
public SessionObject(User loggedInUser) {
this.loggedInUser=loggedInUser;
}
public void valueBound(HttpSessionBindingEvent event) {
LoggedInUserSessionUtil.getLogggedUserMap()
.put(loggedInUser, event.getSession());
return;
}
public void valueUnbound(HttpSessionBindingEvent event) {
try {
LoggedInUserSessionUtil.removeLoggedUser(loggedInUser);
return;
} catch (IllegalStateException e) {
e.printStackTrace();
}
}
}
Java tip I followed and Java2s link while I developed.

how to stop already signedIn user to sign in from other browser

I have a login funcitonality in my application ,
where i am able to store the user in a session
and i am also able to stop user to signIn , if he is already Signed in on the same browser ..
But if a signedIn user tries to logIn again from a DIFFERENT browser i am not able to stop him .
here is the code..
I am using this
session=getThreadLocalRequest().getSession(true);
User loggedInUser = (User) session.getAttribute("user");
Now this loggedInUser have the user object if a loggedInUser tries to get in the application from the SAME browser in another tab (SO it works for me)
BUT this loggedInUser is null if a loggedInUser tries to get in the application from the DIFFERENT browser(SO its not working for me)
here is the code..
public User signIn(String userid, String password) {
String result = "";
ApplicationContext ctx = new ClassPathXmlApplicationContext(
"applicationContext.xml");
MySQLRdbHelper rdbHelper = (MySQLRdbHelper) ctx.getBean("ManagerTie");
User user = (User) rdbHelper.getAuthentication(userid, password);
if(user!=null)
{
session=getThreadLocalRequest().getSession(true);
User loggedInUser = (User) session.getAttribute("user");
if(loggedInUser != null && user.getId() == loggedInUser.getId()){
user.setId(0);
}else{
session=getThreadLocalRequest().getSession(true);
session.setAttribute("user", user);
}
}
return user;
I am using JAVA , GWT
Yes by storing static map on server side,Which stores User Id as a key and Session as value.
Here is working code from my bag directly.
class SessionObject implements HttpSessionBindingListener {
User loggedInUser;
Logger log = Logger.getLogger(SessionObject.class);
public SessionObject(User loggedInUser) {
this.loggedInUser=loggedInUser;
}
public void valueBound(HttpSessionBindingEvent event) {
LoggedInUserSessionUtil.getLogggedUserMap()
.put(loggedInUser, event.getSession());
return;
}
public void valueUnbound(HttpSessionBindingEvent event) {
try {
LoggedInUserSessionUtil.removeLoggedUser(loggedInUser);
return;
} catch (IllegalStateException e) {
e.printStackTrace();
}
}
}
Java tip I followed and Java2s link while I developed.

Struts2 if tag not working

I am writing a login page that when a invalid user tries to login I redirect to the login action with a error parameter equal to 1.
private String username;
private String password;
private int error;
#Override
public String execute()
{
//validate user input
if (username == null || password == null || username.isEmpty() || password.isEmpty())
{
error = 2;
return LOGIN;
}
LoginModel loginModel = new LoginModel(username, password);
HttpBuilder<LoginModel, User> builder = new HttpBuilder<LoginModel, User>(User.class);
builder.setPath("service/user/authenticate");
builder.setModel(loginModel);
IHttpRequest<LoginModel, User> request = builder.buildHttpPost();
User user = request.execute(URL.BASE_LOCAL);
//redirects to login page
if (user == null)
{
error = 1;
return LOGIN;
}
else
{
return SUCCESS;
}
}
//Getters/Setters
If a invalid user trys to login it redirects to localhost:8080/app/login.action?error=1. I am trying to display a error message to user by access the error parameter by using the if tag but its not working the message is not displaying.
<s:if test="error == 1">
<center>
<h4 style="color:red">Username or Password is invalid!!</h4>
</center>
What am I doing wrong?
As far as I'm concerned what you're doing wrong is completely ignoring the framework.
Roughly, IMO this should look more like this:
public class LoginAction extends ActionSupport {
private String username;
private String password;
#Override
public String validate() {
if (isBlank(username) || isBlank(password)) {
addActionError("Username or Password is invalid");
}
User user = loginUser(username, password);
if (user == null) {
addActionError("Invalid login");
}
}
public User loginUser(String username, String password) {
LoginModel loginModel = new LoginModel(username, password);
HttpBuilder<LoginModel, User> builder = new HttpBuilder<LoginModel, User>(User.class);
builder.setPath("service/user/authenticate");
builder.setModel(loginModel);
IHttpRequest<LoginModel, User> request = builder.buildHttpPost();
return request.execute(URL.BASE_LOCAL);
}
}
You would have an "input" result containing the form, and display any action errors present using whatever style you wanted. If it's critical to change the styling based on which type of login error it is you'd have to play a few more games, but that seems excessive.
Unrelated, but I'd move that loginUser code completely out of the action and into a utility/service class, but at least with it wrapped up in a separate method you can mock it more easily. It certainly does not belong in the execute method.
You need to provide the getter and setter of field 'error' to access it from value stack.
public int getError()
{
return error;
}
public void setError(int error)
{
this.error = error;
}
And try to access it in OGNL:
<s:if test="%{#error==1}"></s:if>
Or using JSTL:
<c:if test="${error==1}"></c:if>

Categories