Spring Security authentication ignoring password - spring

In my project I have implemented Spring Security. It's checking whether username and password is correct or not. I want to authenticate only username but not password. How can I achieve this?
public UserDetails loadUserByUsername(String username) {
if (lan == null) {
// loadPasswordRules();
}
List<UserDetails> users = loadUsersByUsername(username);
if (users.size() == 0) {
throw new AuthenticationServiceException("Username " + username + " is invalid ");
}
UserDetails user = users.get(0); // contains no IRole[]
/** Raising exception since start and expiry of user is not valid. */
/** Raising exception since start and expiry of user is not valid. */
Date todayDate = new Date();
if ( !((todayDate).after(((User) user).getStartDate()) && (todayDate).before(((User) user).getExpiryDate())) ) {
throw new AuthenticationServiceException("User " + username + " account is expired.");
/* throw new LockedException("User " + username + " account is expired.");
throw new UsernameNotFoundException("User {" + username + "} account is expired."); SPRING_SECURITY_LAST_EXCEPTION.message */
}
/*if ( ((User) user).getLastSuccessLogin() != null) {
Calendar newDate = Calendar.getInstance();
newDate.setTime( todayDate );
newDate.add(Calendar.DAY_OF_YEAR, - lan.intValue());
Calendar oldDate = Calendar.getInstance();
oldDate.setTime( ((User) user).getLastSuccessLogin() );
if (newDate.after(oldDate)) {
lockUserAccount(username);
throw new AuthenticationServiceException("User " + username + " account is expired.");
}
}*/
Set<IRole> dbAuthsSet = new HashSet<IRole>();
if (enableAuthorities) {
dbAuthsSet.addAll(loadUserAuthorities(user.getUsername()));
}
List<IRole> dbAuths = new ArrayList<IRole>(dbAuthsSet);
if (dbAuths.size() == 0) {
throw new AuthenticationServiceException("Username " + username + " has no assigned roles.");
}
((User) user).setRoles(dbAuths);
return user;
}

You should be able to accomplish this creating a custom AuthenticationProvider implementation and configure your AuthenticationManager to use that.

You should create a Custom Filter to due with this. The Filter should extends class AbstractAuthenticationProcessingFilter and return a Custom Authentication object. Then the Authentication Provider will see it and do check only username which is return by the Filter. After completing everything, you must do configure the Filter to Spring Security context to make it works.
You also can see my complete example here : http://phuonghuynh.github.io/java/spring/security/2015/09/06/spring-security-multiple-authentication-providers.html

Related

Error when accessing outlook emails that need SSO login, using javax mail

I am trying to read outlook emails within my organization using javax mail, but I keep getting the error - "javax.mail.AuthenticationFailedException: Logon failure: unknown user name or bad password."
One thing to note is that there is a Single Sign On required while logging into outlook. So you have to enter the same credentials (emailID/password) twice.
The following is my code -
public static void main(String[] args) {
String host = "pop.outlook.com";
String mailStoreType = "pop3";
String username = "firstname.lastname#companyName.com";
String password = "password";
check(host, mailStoreType, username, password);
}
public static void check(String host, String mailStoreType, String user, String password)
{
try {
//create properties field
Properties props = new Properties();
props.setProperty("mail.pop3.ssl.enable", "true");
props.setProperty("mail.pop3.auth.plain.disable", "true");
props.put("mail.pop3.host", host);
props.put("mail.pop3.port", "995");
props.setProperty("mail.pop3.starttls.enable", "true");
Session emailSession = Session.getDefaultInstance(props);
//create the POP3 store object and connect with the pop server
Store store = emailSession.getStore(mailStoreType);
store.connect(host, user, password);
//create the folder object and open it
Folder emailFolder = store.getFolder("INBOX");
emailFolder.open(Folder.READ_ONLY);
// retrieve the messages from the folder in an array and print it
Message[] messages = emailFolder.getMessages();
Logger.logConsoleMessage("messages.length---" + messages.length);
for (int i = 0, n = messages.length; i < n; i++) {
Message message = messages[i];
Logger.logConsoleMessage("---------------------------------");
Logger.logConsoleMessage("Email Number " + (i + 1));
Logger.logConsoleMessage("Subject: " + message.getSubject());
Logger.logConsoleMessage("From: " + message.getFrom()[0]);
Logger.logConsoleMessage("Text: " + message.getContent().toString());
}
//close the store and folder objects
emailFolder.close(false);
store.close();
} catch (NoSuchProviderException e) {
e.printStackTrace();
} catch (MessagingException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
After tweaking the above code a little, i am able to access a gmail account, which leads me to believe that the error above is because of the extra authentication required by SSO. Has anyone encountered this ever ? Any inputs would be greatly appreciated, Thanks!

Google calendar get events

I am using this code and getting the events from the calendar and it is working fine but, I want to get the events from google accounts calendar .For example, I want to get the (deepakcando90#gmail.com )google calendar accounts events also? I know it is possible but do not know how to implement it?
public static void readCalendarEvent(Context context) throws ParseException {
ContentResolver contentResolver = context.getContentResolver();
Calendar calendar = Calendar.getInstance();
String dtstart = "dtstart";
String dtend = "dtend";
SimpleDateFormat displayFormatter = new SimpleDateFormat("EEEE, MMMM dd, yyyy");
stime=displayFormatter.format(calendar.getTime());
SimpleDateFormat startFormatter = new SimpleDateFormat("MM/dd/yy");
String dateString = startFormatter.format(calendar.getTime());
long after = calendar.getTimeInMillis();
SimpleDateFormat formatterr = new SimpleDateFormat("hh:mm:ss MM/dd/yy");
Calendar endOfDay = Calendar.getInstance();
Date dateCCC = formatterr.parse("47:59:59 " + dateString);
endOfDay.setTime(dateCCC);
cursor = contentResolver.query(Uri.parse("content://com.android.calendar/events"), (new String[] { "calendar_id", "title", "description", "dtstart", "dtend", "eventLocation" }), "(" + dtstart + ">" + after + " and " + dtend + "<" + endOfDay.getTimeInMillis() + ")", null, "dtstart ASC");
gCalendar = new ArrayList<GoogleCalendar>();
try {
System.out.println("Count=" + cursor.getCount());
if (cursor.getCount() > 0) {
System.out.println("the control is just inside of the cursor.count loop");
while (cursor.moveToNext()) {
GoogleCalendar googleCalendar = new GoogleCalendar();
gCalendar.add(googleCalendar);
int calendar_id = cursor.getInt(0);
googleCalendar.setCalendar_id(calendar_id);
String title = cursor.getString(1);
googleCalendar.setTitle(title);
String description = cursor.getString(2);
googleCalendar.setDescription(description);
String dtstart1 = cursor.getString(3);
googleCalendar.setDtstart(dtstart1);
String dtend1 = cursor.getString(4);
googleCalendar.setDtend(dtend1);
String eventlocation = cursor.getString(5);
googleCalendar.setEventlocation(eventlocation);
}
}
} catch (AssertionError ex) {
ex.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
}
You can try OAuth 2.0 service accounts to properly access the user accounts. Using a service account lets you impersonate users and perform operation on their behalf.
Accessing domain calendars as an app
An app can access domain-owned calendars without requiring user credentials if it authenticates using a service account. The service account must have the necessary access using domain-wide authority delegation. In order to impersonate a user account, specify the email address of the user account with the setServiceAccountUser method of the GoogleCredential factory.
I hope it helps. Goodluck :)

spring security's searchForSingleEntryInternal method throws exception if record not found

I'm working on an application that uses Spring Security's searchForSingleEntryInternal method. Is there a way to do the same thing without throwing an exception if a record is not found? I want to be able to create a condition that handles missing records.
What I want to change
if (results.size() == 0) {
throw new IncorrectResultSizeDataAccessException(1, 0);
}
From this method
/**
* Internal method extracted to avoid code duplication in AD search.
*/
public static DirContextOperations searchForSingleEntryInternal(DirContext ctx, SearchControls searchControls,
String base, String filter, Object[] params) throws NamingException {
final DistinguishedName ctxBaseDn = new DistinguishedName(ctx.getNameInNamespace());
final DistinguishedName searchBaseDn = new DistinguishedName(base);
final NamingEnumeration<SearchResult> resultsEnum = ctx.search(searchBaseDn, filter, params, searchControls);
if (logger.isDebugEnabled()) {
logger.debug("Searching for entry under DN '" + ctxBaseDn + "', base = '" + searchBaseDn + "', filter = '" + filter + "'");
}
Set<DirContextOperations> results = new HashSet<DirContextOperations>();
try {
while (resultsEnum.hasMore()) {
SearchResult searchResult = resultsEnum.next();
// Work out the DN of the matched entry
DistinguishedName dn = new DistinguishedName(new CompositeName(searchResult.getName()));
if (base.length() > 0) {
dn.prepend(searchBaseDn);
}
if (logger.isDebugEnabled()) {
logger.debug("Found DN: " + dn);
}
results.add(new DirContextAdapter(searchResult.getAttributes(), dn, ctxBaseDn));
}
} catch (PartialResultException e) {
LdapUtils.closeEnumeration(resultsEnum);
logger.info("Ignoring PartialResultException");
}
if (results.size() == 0) {
throw new IncorrectResultSizeDataAccessException(1, 0);
}
if (results.size() > 1) {
throw new IncorrectResultSizeDataAccessException(1, results.size());
}
return results.iterator().next();
}
}
I'm somewhat new to spring and maybe I'm missing something obvious. Any advice would be much appreciated
easy fix, just had to copy over the searchForSingleEntryInternal method from Spring Security and place it in my own project. From there I was able to tweak the exception handling so the application didn't come to a grinding halt if a record wasn't found.

HttpSession with Spring 3 MVC

I want to use HttpSession in Spring 3 MVC. I have searched all the web and got this solution at http://forum.springsource.org/showthread.php?98850-Adding-to-stuff-to-the-session-while-using-ResponseBody
Basically, my application auto authenticates user by getting winId and authorizes through LDAP (it's an intranet site).
Here is the flow of the application:
User enters Application URL (http://localhost:8082/eIA_Mock_5) it has a welcome page (index.jsp)
index.jsp gets winId through jQuery and hits login.html (through AJAX) and passes windowsId
login.html (Controller) authenticates through LDAP and gives back 'Valid' String as a response
JavaScript, upon getting the correct response, redirects/loads welcome page i.e. goes to localhost:8082/eIA_Mock_5/welcome.html
Now, I have filter associated with it, which checks if the session is valid for each incoming request. Now the problem is even though I set data on to HttpSession, yet the filter or any other controller fails to get the data through session as a result it doesn't proceeds further.
Here is the code. Could you suggest what is wrong actually?
Home_Controller.java:
#Controller
public class Home_Controller {
public static Log logger = LogFactory.getLog(Home_Controller.class);
#RequestMapping(value = {"/welcome"})
public ModelAndView loadWelcomePage(HttpServletRequest request, HttpServletResponse response)
{
ModelAndView mdv = new ModelAndView();
try {
/*HttpSession session = request.getSession();
UserMasterBean userBean = (UserMasterBean)session.getAttribute("userBean");
String userName = userBean.getWindowsId();
if(userName == null || userName.equalsIgnoreCase(""))
{
mdv.setViewName("homePage");
System.out.println("Unable to authenticate user ");
logger.debug("Unable to authenticate user ");
}
else
{
System.out.println("Welcome User "+userName);
logger.debug("Welcome User "+userName);
*/
mdv.setViewName("homePage");
/*}*/
}
catch (Exception e){
logger.debug("inside authenticateUser ",e);
e.printStackTrace();
}
return mdv;
}
#RequestMapping(value = "/login", method = RequestMethod.GET)
public #ResponseBody String authenticateUser(#RequestParam String userName, HttpSession session)
{
logger.debug("inside authenticateUser");
String returnResponse = new String();
try {
logger.debug("userName for Authentication " + userName);
System.out.println("userName for Authentication " + userName);
//HttpSession session = request.getSession();
if (userName == null || userName.trim().equalsIgnoreCase(""))
returnResponse = "Invalid";
else
{
System.out.println("uname " + userName);
String ldapResponse = LDAPConnectUtil.isValidActiveDirectoryUser(userName, "");
if (ldapResponse.equalsIgnoreCase("true"))
{
returnResponse="Valid";
System.out.println(userName + " Authenticated");
logger.debug(userName + " Authenticated");
UserMasterBean userBean = new UserMasterBean();
userBean.setWindowsId(userName);
//if(session.getAttribute("userBean")==null)
session.setAttribute("userBean", userBean);
}
else
{
returnResponse = "Invalid";
//session.setAttribute("userBean", null);
System.out.println("Unable to Authenticate the user through Ldap");
logger.debug("Unable to Authenticate the user through Ldap");
}
System.out.println("ldapResponse " + ldapResponse);
logger.debug("ldapResponse " + ldapResponse);
System.out.println("returnResponse " + returnResponse);
}
UserMasterBean u = (UserMasterBean)session.getAttribute("userBean");
System.out.println("winId " + u.getWindowsId());
}
catch(Exception e){
e.printStackTrace();
logger.debug("Exception in authenticateUser ", e);
}
return returnResponse;
}
}
Filter:
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
{
System.out.println("in PageFilter");
boolean flag = false;
HttpServletRequest objHttpServletRequest = (HttpServletRequest)request;
HttpServletResponse objHttpServletResponse = (HttpServletResponse)response;
HttpSession session = objHttpServletRequest.getSession();
String contextPath = objHttpServletRequest.getContextPath();
String servletPath = objHttpServletRequest.getSession().getServletContext().getRealPath(objHttpServletRequest.getServletPath());
logger.debug("contextPath :" + contextPath);
logger.debug("servletPath :" + servletPath);
System.out.println("in PageFilter, contextPath :" + contextPath);
System.out.println("in PageFilter, servletPath :" + servletPath);
if (servletPath.endsWith("\\") || servletPath.endsWith("/") ||
servletPath.indexOf("css") > 0 || servletPath.indexOf("jsp") > 0 ||
servletPath.indexOf("images") > 0 || servletPath.indexOf("js") > 0 ||
servletPath.endsWith("index.jsp") || servletPath.indexOf("xls") > 0 ||
servletPath.indexOf("ini") > 0 || servletPath.indexOf("login.html") > 0 ||
/*servletPath.endsWith("welcome.html") ||*/ servletPath.endsWith("logout.do") )
{
System.out.println("User is trying to access allowed pages like Login.jsp, errorPage.jsp, js, images, css");
logger.debug("User is trying to access allowed pages like Login.jsp, errorPage.jsp, js, images, css");
flag = true;
}
if (flag == false)
{
System.out.println("flag = false");
if (session.getAttribute("userBean") == null)
System.out.println("yes session.userbean is null");
if ((session != null) && (session.getAttribute("userBean") != null))
{
System.out.println("session!=null && session.getAttribute(userId)!=null");
logger.debug("IF Part");
UserMasterBean userBean = (UserMasterBean)session.getAttribute("userBean");
String windowsId = userBean.getWindowsId();
logger.debug("User Id " + windowsId + " allowed access");
System.out.println("User Id " + windowsId + " allowed access");
flag = true;
}
else
{
System.out.println("else .....session!=null && session.getAttribute(userId)!=null");
logger.debug("Else Part");
flag = false;
}
}
if (flag == true) {
try {
System.out.println("before chain.doFilter(request, response)");
chain.doFilter(request, response);
} catch (Exception e) {
e.printStackTrace();
try {
objHttpServletResponse.sendRedirect(contextPath + "/logout.do");
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
else
{
try {
System.out.println("before sendRedirect");
objHttpServletResponse.sendRedirect(contextPath + "/jsp/errorPage.jsp");
} catch (Exception ex) {
ex.printStackTrace();
}
}
System.out.println("end of PageFilter");
}
index.jsp:
<script type="text/javascript">
//alert("inside s13");
var WinNetwork = new ActiveXObject("WScript.Network");
var userName = WinNetwork.UserName;
alert(userName);
$.ajax({
url: "login.html",
data: "userName="+userName,
success: function(result) {
alert("result == " + result);
if (result == "Valid")
window.location = "http://10.160.118.200:8082/eIA_Mock_5/welcome.html";
}
});
</script>
web.xml has a filter entry with URL pattern as *
I am using Spring 3 MVC.
I think problem in ajax call and setting windows.location after that.
Make sure you set cookie enabled. If you don't do this, your ajax request will lead to new session every time.
When you do window.location = url and this url differ than your current url, it also lead to new session, because cookie is domain related, and you changed domain, for example from localhost to 10.160.118.200.
For each request output sessionid and compare it with previous request. It helps find when session was recreated.
Also this answer can help.

Google Authentication API: How to get the user's gmail address

I've been studying the Google authentication API (AuthSub)... My question is, how do I get the user's account information (at least their Gmail address) after the authentication has passed?
Because currently, all I get back from the authentication process is a token granting me access to which ever Google service I have specified in the scope, but there's no easy way to even get the user's login id (Gmail address) as far as I can tell...
If so, what Google service allows me to access the user's information?
Google Authentication API is a token based system to authenticate a valid user. It does not expose any of other interface that allows to get account holder information back to authorizer.
Using the Google AppEngine GData services, you can request the user to give you access to their Google Mail, Calendar, Picasa, etc. Check it out here.
You can get some of the data through the OpenID API, with the ax extension. If you are authenticating with other methods, best I found is calling https://www-opensocial.googleusercontent.com/api/people/#me/#self and it will get you name, email and picture. Be sure to have http://www-opensocial.googleusercontent.com/api in scopes when authenticating.
[ValidateInput(false)]
public ActionResult Authenticate(string returnUrl)
{
try
{
logger.Info("" + returnUrl + "] LoginController : Authenticate method start ");
var response = openid.GetResponse();
if (response == null)
{
try
{
string discoveryuri = "https://www.google.com/accounts/o8/id";
//OpenIdRelyingParty openid = new OpenIdRelyingParty();
var fetch = new FetchRequest();// new
var b = new UriBuilder(Request.Url) { Query = "" };
var req = openid.CreateRequest(discoveryuri, b.Uri, b.Uri);
fetch.Attributes.AddRequired(WellKnownAttributes.Contact.Email);
fetch.Attributes.AddRequired(WellKnownAttributes.Name.FullName);
req.AddExtension(fetch);
return req.RedirectingResponse.AsActionResult();
}
catch (ProtocolException ex)
{
logger.ErrorFormat(" LoginController : Authenticate method has error, Exception:" + ex.ToString());
ViewData["Message"] = ex.Message;
return View("Login");
}
}
else
{
logger.Info("" + returnUrl + "] LoginController : Authenticate method :when responce not null ");
switch (response.Status)
{
case AuthenticationStatus.Authenticated:
logger.Info("" + response.Status + "] LoginController : Authenticate method : responce status ");
var fetchResponse = response.GetExtension<FetchResponse>();
string email = fetchResponse.GetAttributeValue(WellKnownAttributes.Contact.Email);
string userIPAddress = HttpContext.Request.UserHostAddress;
SecurityManager manager = new SecurityManager();
int userID = manager.IsValidUser(email);
if (userID != 0)
{
ViewBag.IsFailed = "False";
logger.Info("" + userID + "] LoginController : Authenticate method : user id id not null ");
Session["FriendlyIdentifier"] = response.FriendlyIdentifierForDisplay;
Session["UserEmail"] = email;
FormsAuthentication.SetAuthCookie(email, false);
WebSession.UserEmail = email;
WebSession.UserID = userID;
UserManager userManager = new UserManager();
WebSession.AssignedSites = userManager.GetAssignedSites(userID);
if (!string.IsNullOrEmpty(returnUrl))
{
logger.Info("" + returnUrl + "] LoginController : Authenticate method : retutn url not null then return Redirect ");
return Redirect(returnUrl);
}
else
{
logger.Info("" + returnUrl + "] LoginController : Authenticate method : retutn url null then return RedirectToAction ");
//
return Redirect("/Home");
}
}
else
{
ViewBag.IsFailed = "True";
logger.Info("" + returnUrl + "] LoginController : Authenticate method :user id null ");
if (!string.IsNullOrEmpty(returnUrl))
{
logger.Info("" + returnUrl + "] LoginController : Authenticate method :and return Redirect ");
return Redirect(returnUrl);
}
else
{
logger.Info("" + returnUrl + "] LoginController : Authenticate method :and return RedirectToAction ");
return View("Index");
}
}
case AuthenticationStatus.Canceled:
logger.Info("" + response.Status + "] LoginController : Authenticate method : AuthenticationStatus.Canceled and return view ");
ViewData["Message"] = "Canceled at provider";
return View("Login");
case AuthenticationStatus.Failed:
logger.Info("" + response.Status + "] LoginController : Authenticate method : AuthenticationStatus.Failed and return view ");
logger.Error(response.Exception.Message);
ViewData["Message"] = response.Exception.Message;
return View("Login");
}
}
logger.Info("" + returnUrl + "] LoginController : Authenticate method end and return EmptyResult");
return new EmptyResult();
}
catch (Exception ex)
{
logger.Error(" LoginController : Authenticate method ", ex);
throw;
}
}

Resources