public Authentication authenticate(Authentication auth)
			throws AuthenticationException {
		if (!(auth instanceof UsernamePasswordAuthenticationToken)) {
			return null;
		}

		UsernamePasswordAuthenticationToken request = (UsernamePasswordAuthenticationToken) auth;
		Set<GrantedAuthority> authorities;

		try {
			// Create the LoginContext object, and pass our InternallCallbackHandler
			LoginContext loginContext = createLoginContext(
					new InternalCallbackHandler(auth));

			// Attempt to login the user, the LoginContext will call our
			// InternalCallbackHandler at this point.
			loginContext.login();

			// Create a set to hold the authorities, and add any that have already been
			// applied.
			authorities = new HashSet<>();

			// Get the subject principals and pass them to each of the AuthorityGranters
			Set<Principal> principals = loginContext.getSubject().getPrincipals();

			for (Principal principal : principals) {
				for (AuthorityGranter granter : this.authorityGranters) {
					Set<String> roles = granter.grant(principal);

					// If the granter doesn't wish to grant any authorities, it should
					// return null.
					if ((roles != null) && !roles.isEmpty()) {
						for (String role : roles) {
							authorities.add(new JaasGrantedAuthority(role, principal));
						}
					}
				}
			}

			// Convert the authorities set back to an array and apply it to the token.
			JaasAuthenticationToken result = new JaasAuthenticationToken(
					request.getPrincipal(), request.getCredentials(),
					new ArrayList<>(authorities), loginContext);

			// Publish the success event
			publishSuccessEvent(result);

			// we're done, return the token.
			return result;

		}
		catch (LoginException loginException) {
			AuthenticationException ase = this.loginExceptionResolver
					.resolveException(loginException);

			publishFailureEvent(request, ase);
			throw ase;
		}
	}