EJB: how to check user is authenticated - ejb-3.1

Use logged throuth the JSP form:
#ManagedBean
#SessionScoped
public class LoginView {
private String username; //+getter +setter
private String password; //+getter +setter
public String submit()
{
try {
HttpServletRequest request = (HttpServletRequest) FacesContext
.getCurrentInstance()
.getExternalContext()
.getRequest();
request.login(username, password);
} catch (ServletException e) {
FacesContext.getCurrentInstance().addMessage("login-form:username",
new FacesMessage(FacesMessage.SEVERITY_ERROR, "Validation Error", "Incorrect login or password"));
return "/login";
}
return "/index?faces-redirect=true";
}
}
How to check user logged in thorug EJB?
Below example whan I need:
#Stateless
public class SessionServiceBean {
#Resource
SessionContext sessionContext;
#EJB
UserService userService;
#Produces
#Named
#LoggedIn
public User getLoggedUser() {
if (/* check user is logged */) {
return userService.getByName(sessionContext.getCallerPrincipal().getName());
}
}
}
I foun only that the not logged use has name "anonymous", but it not better way, I think.

You are using a #Stateless EJB. In a Stateless EJB, you are working with user sessions. This is probably not right and the bean should be #Stateful.
I see no point in using EJBs in your example. Using pure CDI bean annotated with #SessionScoped would be sufficient.
You can store you user's session information directly in a session scoped bean. There is not need to use HttpServletRequest. For example:
#Named
#SessionScoped
public class UserSession implements Serializable {
private User activeUser;
public void logIn(User user) {
this.activeUser = user;
}
public void logOut() {
activeUser = null;
}
public boolean isLoggedIn() {
return activeUser != null;
}
public User getActiveUser() {
return activeUser;
}
}

Related

Unable to login Experience cloud site

Whenever I'm trying to login, I'm getting this error 'You do not have access to the Apex class named LightningLoginFormController'. I've made changes in Apex Class Security and added all the profiles, also checked by using 'with sharing' and 'without sharing', but it's still not working.
global class LightningLoginFormController {
public LightningLoginFormController() {
}
#AuraEnabled
public static String login(String username, String password, String startUrl) {
try{
ApexPages.PageReference lgn = Site.login(username, password, startUrl);
aura.redirect(lgn);
return null;
}
catch (Exception ex) {
return ex.getMessage();
}
}
#AuraEnabled
public static Boolean getIsUsernamePasswordEnabled() {
Auth.AuthConfiguration authConfig = getAuthConfig();
return authConfig.getUsernamePasswordEnabled();
}
#AuraEnabled
public static Boolean getIsSelfRegistrationEnabled() {
Auth.AuthConfiguration authConfig = getAuthConfig();
return authConfig.getSelfRegistrationEnabled();
}
#AuraEnabled
public static String getSelfRegistrationUrl() {
Auth.AuthConfiguration authConfig = getAuthConfig();
if (authConfig.getSelfRegistrationEnabled()) {
return authConfig.getSelfRegistrationUrl();
}
return null;
}
#AuraEnabled
public static String getForgotPasswordUrl() {
Auth.AuthConfiguration authConfig = getAuthConfig();
return authConfig.getForgotPasswordUrl();
}
#TestVisible
private static Auth.AuthConfiguration getAuthConfig(){
Id networkId = Network.getNetworkId();
Auth.AuthConfiguration authConfig = new Auth.AuthConfiguration(networkId,'');
return authConfig;
}
#AuraEnabled
global static String setExperienceId(String expId) {
// Return null if there is no error, else it will return the error message
try {
if (expId != null) {
Site.setExperienceId(expId);
}
return null;
} catch (Exception ex) {
return ex.getMessage();
}
}
}
For this to work, you need to add the Apex Class in Community Portal User Profile i.e. the Profile using "Guest User License".
Navigation: All sites --> Workspaces --> Administration --> Pages --> Go to Force.com --> Public Access Settings --> Enabled Apex Class Access.
And if you have a custom function in your Apex Class that is using SOQL query, for that to fetch data you will need to use "without sharing" security settings!!

ASP.NET Core with Winforms - Saving the username once

I have a standard Hoemcontroller in ASP.NET Core MVC:
public class HomeController : Controller
{
private readonly ILogger<HomeController> _logger;
public HomeController(ILogger<HomeController> logger)
{
_logger = logger;
}
public IActionResult Index(string user)
{
if(user != null)
{
TempData["UserName"] = user;
return View("Index", user);
}
return View("Index");
}
public IActionResult Privacy()
{
return View();
}
[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
public IActionResult Error()
{
return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
}
}
In the Index Action there will be a parameter sent from a winforms application. The string will contain the username of the client connecting to the website. This is the code for winforms:
public partial class Form1 : Form
{
public ChromiumWebBrowser chromeBrowser;
public Form1()
{
InitializeComponent();
InitializeChromium();
this.WindowState = FormWindowState.Maximized;
}
public void InitializeChromium()
{
CefSettings settings = new CefSettings();
Cef.Initialize(settings);
Cef.EnableHighDPISupport();
chromeBrowser = new ChromiumWebBrowser("https://localhost:5001/Home/Index/" + Environment.UserName);
this.Controls.Add(chromeBrowser);
//chromeBrowser.Dock = DockStyle.Fill;
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
Cef.Shutdown();
}
}
Now I am unsure on how to handle this on the webserver. I get the username inside the HomeController but in the same time when a user goes to the other pages with their controllers then the user should see only his content. Is that even possible?
It is not good practice to do authorization through a parameter in URI. For that, you should use Authentication (when the user passes his login and password) and receive a token with permissions. After that, you pass the token to the server and check permission there(using Authorize attribute for example). Example
If you are making a test project, and you don't need authentication at all, then you can pass a username everywhere you need and write some code to handle the content of every user (using headers, URI parameters, etc.)

Unable to login Portal community after activating Critical update

Before I activated the critical update name 'Restrict Access to #AuraEnabled Apex Methods for Guest and Portal Users Based on User Profile' I can login to Portal community properly.
After I Activated that critical update, community user can not login to Portal and the error message in response of Network tab will be 'You do not have access to the Apex class named LightningLoginFormController
I am sure that guest or portal user profile can access LightningLoginFormController Apex class.
global class LightningLoginFormController {
public LightningLoginFormController() {
}
#AuraEnabled
public static String login(String username, String password, String startUrl) {
try{
ApexPages.PageReference lgn = Site.login(username, password, startUrl);
aura.redirect(lgn);
return null;
}
catch (Exception ex) {
return ex.getMessage();
}
}
#AuraEnabled
public static Boolean getIsUsernamePasswordEnabled() {
Auth.AuthConfiguration authConfig = getAuthConfig();
return authConfig.getUsernamePasswordEnabled();
}
#AuraEnabled
public static Boolean getIsSelfRegistrationEnabled() {
Auth.AuthConfiguration authConfig = getAuthConfig();
return authConfig.getSelfRegistrationEnabled();
}
#AuraEnabled
public static String getSelfRegistrationUrl() {
Auth.AuthConfiguration authConfig = getAuthConfig();
if (authConfig.getSelfRegistrationEnabled()) {
return authConfig.getSelfRegistrationUrl();
}
return null;
}
#AuraEnabled
public static String getForgotPasswordUrl() {
Auth.AuthConfiguration authConfig = getAuthConfig();
return authConfig.getForgotPasswordUrl();
}
#TestVisible
private static Auth.AuthConfiguration getAuthConfig(){
Id networkId = Network.getNetworkId();
Auth.AuthConfiguration authConfig = new Auth.AuthConfiguration(networkId,'');
return authConfig;
}
#AuraEnabled
global static String setExperienceId(String expId) {
// Return null if there is no error, else it will return the error message
try {
if (expId != null) {
Site.setExperienceId(expId);
}
return null;
} catch (Exception ex) {
return ex.getMessage();
}
}
}
Does someone else face the same problem?
You need to explicitly allow access to Apex classes containing #AuraEnabled methods.
Guest, portal, or community user can access an #AuraEnabled Apex method only when the user’s profile or an assigned permission set allows access to the Apex class.
More details here:
https://releasenotes.docs.salesforce.com/en-us/spring20/release-notes/rn_lc_restrict_apex_guest_users.htm

DaoAuthenticationProvider not getting invoked

I am trying to authenticate a request from using spring security, I have followed few blogs and videos but i am not able to fix the issues.
Security configuration is loaded but my requests are not getting authenticated. I get 403 error
Bean class in WebSecurityConfigureAdapter
public DaoAuthenticationProvider authenticationProvider() {
DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider();
authProvider.setUserDetailsService(userService);
System.out.println(userDetailsService());
return authProvider;
}
over riding configure method
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests().antMatchers("/products","/orders").hasAnyRole("admin");//.authenticated();
}
user details services overridding loadUserByUsername
#Override
public UserDetails loadUserByUsername(String loginName) {
String authenticated = "false";
UserDetails userDetails = null;
List<Users> usersList = usersRepository.findByLoginName(loginName);
if(usersList.size()==0) {
return null;
}else {
for (Users users : usersList) {
List<Roles> rolesList = users.getRoles();
for (Roles roles : rolesList) {
if(roles.getUserRole().equalsIgnoreCase("admin")) {
authenticated = "admin";
GrantedAuthority authority = new SimpleGrantedAuthority(authenticated);
User user = new User(users.getLoginName(),users.getPassword(),Arrays.asList(authority));
userDetails = (UserDetails)user;
}
}
}
return userDetails;
}
using postman setting up the credentials as basicAuth, its throwing 403 error
the issue was...
we need to either set the value for different getters in userdetails class or explicitly set to true
i have below getters explicitly set it to true, it worked for me
#Override
public boolean isAccountNonExpired() {
return true;
}
#Override
public boolean isAccountNonLocked() {
return true;
}
#Override
public boolean isCredentialsNonExpired() {
return true;
}
#Override
public boolean isEnabled() {
return true;
}

Spring LDAP/Active Directory with SQL

I am trying to enable both JDBA and Active Directory Authentication , i made great progress but currently i am stuck as userDetailsService is trying to compare the password in LdapUserDetails which does not exist . When checking the log i see it is able to query the user and authenticate and get the roles correctly.
I know i should use bindService or so , but i couldn't find till now how to do that.
Below is what i did .
in WebSecurityConfigurerAdapter
#Autowired
public void configureGlobal(UserDetailsService userDetailsService,UserLdapRepositoryUserDetailsService userLdapRepositoryUserDetailsService,AuthenticationManagerBuilder auth) throws Exception {
auth
.userDetailsService(userDetailsService).
and()
.userDetailsService(userLdapRepositoryUserDetailsService);
}
For LDAP Configuration
#Bean
public BaseLdapPathContextSource contextSource() {
DefaultSpringSecurityContextSource contextSource = new DefaultSpringSecurityContextSource("ldap://XXXXX:389/dc=XXXXXX,dc=co");
//contextSource.setUserDn("CN=Ali Shahbour,OU=Users,DC=XXXXXXX,DC=co");
contextSource.setUserDn("XXXXXX");
contextSource.setPassword("XXXXXX");
return contextSource;
}
#Bean
#Autowired
public LdapUserSearch userSearch(BaseLdapPathContextSource contextSource) {
FilterBasedLdapUserSearch userSearch = new FilterBasedLdapUserSearch("", "(uid={0})", contextSource);
return userSearch;
}
#Bean
#Autowired
public LdapAuthoritiesPopulator authoritiesPopulator(BaseLdapPathContextSource contextSource) {
DefaultLdapAuthoritiesPopulator authoritiesPopulator = new DefaultLdapAuthoritiesPopulator(contextSource, "OU=CDRMonitor");
authoritiesPopulator.setGroupSearchFilter("(member={0})");
//authoritiesPopulator.setRolePrefix("ROLE");
authoritiesPopulator.setSearchSubtree(true);
//authoritiesPopulator.setConvertToUpperCase(true);
return authoritiesPopulator;
}
As for the LdapUserDetailsService
#Service("userLdapRepositoryUserDetailsService")
public class UserLdapRepositoryUserDetailsService extends LdapUserDetailsService {
private final UserRepository userRepository;
#Autowired
public UserLdapRepositoryUserDetailsService(LdapUserSearch userSearch,
LdapAuthoritiesPopulator authoritiesPopulator,UserRepository userRepository) {
super(userSearch, authoritiesPopulator);
this.userRepository = userRepository;
}
#Override
public UserDetails loadUserByUsername(String username)
throws UsernameNotFoundException {
UserDetails userDetails = super.loadUserByUsername(username);
//User user = userRepository.findByEmail(username);
User user = new User();
return new LdapUserRepositoryUserDetails(user, userDetails);
}
#Override
public void setUserDetailsMapper(UserDetailsContextMapper userDetailsMapper) {
super.setUserDetailsMapper(userDetailsMapper);
}
private final static class LdapUserRepositoryUserDetails extends User implements LdapUserDetails {
private final LdapUserDetailsImpl ldapUserDetailsImpl;
private LdapUserRepositoryUserDetails(User user,UserDetails userDetails) {
super(user);
ldapUserDetailsImpl = (LdapUserDetailsImpl) userDetails;
}
private static final long serialVersionUID = 5639683223516504866L;
#Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return ldapUserDetailsImpl.getAuthorities();
}
#Override
public String getUsername() {
// TODO Auto-generated method stub
return ldapUserDetailsImpl.getUsername();
}
#Override
public boolean isAccountNonExpired() {
return ldapUserDetailsImpl.isAccountNonExpired();
}
#Override
public boolean isAccountNonLocked() {
return ldapUserDetailsImpl.isAccountNonLocked();
}
#Override
public boolean isCredentialsNonExpired() {
return ldapUserDetailsImpl.isCredentialsNonExpired();
}
#Override
public boolean isEnabled() {
return ldapUserDetailsImpl.isEnabled();
}
#Override
public String getDn() {
return ldapUserDetailsImpl.getDn();
}
}
}
LDAP and SQL in an authentication context are in general not used together,
because LDAP BIND authentication sends the password to the LDAP server instead of retrieving a hash value of the password.
The intended procedure of LDAP Authentication is as follows:
Usually a spring security UsernamePassword filter is used to pick up the credentials and is active by default. e.g. if you us a login form, when submitting the form, this filter picks up the credentials.
Next an LDAP Authentication Provider performs a login (LDAPBindAuthenticator) against the LDAP server (LDAP ContextSource) to verify the credentials.
If the login is successful, the LDAP Authentication Provider searches the LDAP for a user entry. This can be customised by providing a 'usersearch' spring bean.
If the user entry is found, the LDAP Authority mapper will map attributes of the user entry to groups/roles in spring security. By default this are all OU attributes
Lastly a new authentication object is made with the username and retrieved groups from the LDAP.
How to integrate LDAP Authentication using Spring XML is explained here.
http://docs.spring.io/spring-security/site/docs/3.1.x/reference/ldap.html

Resources