I'm trying to mock authentication in Java for an authentication. This is my test class for mocking the code:
MockitoAnnotations.initMocks(this);
mvc = MockMvcBuilders.standaloneSetup(this.controller).build();
final List<AuthenticationProvider> providers = mock(ArrayList.class);
final AbstractUserDetailsAuthenticationProvider provider = mock(
AbstractUserDetailsAuthenticationProvider.class);
when(provider.supports(any(Class.class))).thenReturn(false);
when(providers.size()).thenReturn(1);
session = new MockHttpSession();
when(providers.get(anyInt())).thenReturn(provider);
when(request.getSession()).thenReturn(session);
when(request.getSession(false)).thenReturn(session);
when(providers.iterator()).thenReturn(new Iterator<AuthenticationProvider>() {
private int currentIndex = 0;
#Override
public AuthenticationProvider next() {
return providers.get(currentIndex++);
}
#Override
public boolean hasNext() {
return currentIndex < providers.size() && providers.get(currentIndex) != null;
}
});
SingleProviderAuthenticationManager manager = new SingleProviderAuthenticationManager(providers);
Map<String, AuthenticationManager> map = new HashMap<String, AuthenticationManager>();
map.put("db", manager);
filter.setAuthenticationManagerMap(map);
when(request.getMethod()).thenReturn("POST");
when(request.getParameter("username")).thenReturn("admin");
when(request.getParameter("password")).thenReturn("admin");
List<User> users = new ArrayList<User>();
User user = new User();
user.setSourceSystem("db");
users.add(user);
when(userService.getUserReferenceByUsername("admin")).thenReturn(users);
auth = filter.attemptAuthentication(request, response);
Now, on the line where I put the manager in the map.put() method, when I put "db" it actually gives the provider manager as null and I get the NullPointerException in the ProviderManager.
for (AuthenticationProvider provider : getProviders()) {
if (!provider.supports(toTest)) {
continue;
}
Even though I've tested the same thing in my main code with the providers I pass its still showing a NullPointerException. And if I put "ldap" instead it gives me a NullPointerException in the UsernamePasswordAuthenticationFilter here:
(last line where the return happens)
password = "";
}
username = username.trim();
UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(username, password);
// Allow subclasses to set the "details" property
setDetails(request, authRequest);
return this.getAuthenticationManager().authenticate(authRequest);
}
I am stuck here, both these things when I pass them are not at all null. Any help?
Don't mock ArrayList instead create new array list and send it to actual class like below :
final List<AuthenticationProvider> providers = new ArrayList<>();
providers.add("AuthenticationProvider object values");
// when(providers.size()).thenReturn(1); -- no need of doing this stuff if you create direct arraylist object.
PS- If you are working with collections, do prefer creating new objects and send that object to actual class instead of mocking and sending, that is the best practice.
Hope it's useful.
Related
I have this method, that makes the request to the specified phone number:
public Call sendVoiceCall(String responsiblePhoneNumber, String completeName) {
Twilio.init(ACCOUNT_SID, AUTH_TOKEN);
String helloTwiml = new VoiceResponse.Builder()
.say(new Say.Builder("Whatever")
.voice(Say.Voice.ALICE).language(Say.Language.PT_BR).build())
.build().toXml();
Call call = Call.creator(
new PhoneNumber(responsiblePhoneNumber),
new PhoneNumber(twilioPhoneNumber),
new Twiml(helloTwiml))
.create();
return call;
}
I call it inside this method:
#PostMapping("/sendVoiceCall")
#Transactional
#Async
public void sendVoiceCall() {
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
Optional<User> username = userRepository.findByUsername(auth.getName());
List<Dependency> uuids = dependencyRepository.returnAllContactUuid(username.orElse(null).getUuid());
uuids.forEach(contact -> {
Optional<User> user = userRepository.findByUuid(contact.getContactUuid());
voiceCallService.sendVoiceCall(user.orElse(null).getPhone(), username.get().getCompleteName());
});
log.info("There was a request to warn users responsible for: " + username.orElse(null).getCompleteName());
}
When I try to send just to one person it works, but when I try to iterate using lambda, it gives me a 200 code and makes nothing.
Thanks for your help!
I am getting below error when I try to use #Async annotation.
java.lang.IllegalStateException: No thread-bound request found: Are you referring to request attributes outside of an actual web request, or processing a request outside of the originally receiving thread? If you are actually operating within a web request and still receive this message, your code is probably running outside of DispatcherServlet/DispatcherPortlet: In this case, use RequestContextListener or RequestContextFilter to expose the current request.
Code:
#Async
#Override
#Transactional
public void triggerEmailCommunication(List<String> eventCode, Integer authorizationId, Integer claimId,
boolean callMethod) {
Map<String, Object> emailBody = new HashMap<>();
try {
if (callMethod) {
LOGGER.info("Communication async flow triggerEmailCommunication method starts.");
emailBody = emailBodyObject(authorizationId, claimId, eventCode);
}
private Map<String, Object> emailBodyObject(Integer authorizationId, Integer claimId, List<String> eventCode)
throws CareBusinessServiceException {
LOGGER.info("EmailBodyObject method starts.");
Map<String, Object> emailBody = new HashMap<String, Object>();
EmailClaimDetailsVO emailClaimDetails = new EmailClaimDetailsVO();
ClaimAuthorizationVO claimAuthVO = new ClaimAuthorizationVO();
Claim claim = new Claim();
Authorization authorization = new Authorization();
List<String> rejectReasonList = new ArrayList<>();
Provider provider = new Provider();
String providerName = null;
String claimIntimationNbr = null;
String authorizationNbr = null;
SimpleDateFormat formatter = new SimpleDateFormat(AmhiConstants.DATE_FORMAT_DD_MM_YYYY);
try {
Integer claimIntimationId = null;
if (null != claimId) {
claim = enableBusinessService.retrieveClaimDetails(claimId);
} catch(Exception e) {
}
}
DAO Layer
#Override
public Claim retrieveClaimIdRecord(Integer claimId) {
CriteriaBuilder builder = manager.getCriteriaBuilder();
CriteriaQuery<Claim> criteriaQuery = builder.createQuery(Claim.class);
Root<Claim> root = criteriaQuery.from(Claim.class);
ArrayList<Predicate> conditions = new ArrayList<>();
conditions.add(builder.equal(root.get(Claim_.claimId), claimId));
criteriaQuery.select(root).where(conditions.toArray(new Predicate[] {}));
javax.persistence.Query query = manager.createQuery(criteriaQuery);
List<Claim> claims = query.getResultList();
if(CollectionUtils.isNotEmpty(claims)){
return claims.get(0);
}
return new Claim();
}
The value is getting retrieved from DB. But I am getting above exception as mentioned.
In my case it happened when I created a bean at request level and tried to access it from another thread created using #Async annotation. The bean information was stored in the thread local of the original thread only.
Are you using something created and stored in the thread local of the base thread in the function or subsequent functions after #Async notification?
#Async creates another thread but doesn't copy the thread local of the original thread which causes the issue.
See this - https://jira.spring.io/browse/SPR-6873
I try to implement auth through AWS Cognito using aws-java-sdk-cognitoidentity and for convenience use cognitoauth classes
Authentication works fine but when I get AuthenticationResultType from respondToAuthChallengeResult it return null why that happens?
Sample:
AWSCryptoSettings cryptoParams = new AWSCryptoSettings();
AWSCognitoSession clientSession = new AWSCognitoSession(
cryptoParams, "test", "123456", USER_POOL_ID);
AWSCognitoIdentityProvider provider = AWSCognitoIdentityProviderClientBuilder.standard()
.withCredentials(new AWSStaticCredentialsProvider(new AnonymousAWSCredentials()))
.withRegion(Regions.EU_WEST_1)
.build();
InitiateAuthRequest authRequest = new InitiateAuthRequest()
.withAuthFlow(AuthFlowType.USER_SRP_AUTH)
.withClientId(CLIENT_APP_ID)
.withAuthParameters(clientSession.step1()); //step1() return Map<String,String> with parameters for auth in it
//Respond to authentication challenge
InitiateAuthResult authResult = provider.initiateAuth(authRequest);
Map<String, String> params = authResult.getChallengeParameters();
Map<String, String> srpAuthResponses = clientSession.step2(params); //step2() return also Map<String, String> with formatted parameters.
RespondToAuthChallengeRequest respondToAuthChallengeRequest = new RespondToAuthChallengeRequest()
.withChallengeName(authResult.getChallengeName())
.withClientId(CLIENT_APP_ID)
.withChallengeResponses(srpAuthResponses);
RespondToAuthChallengeResult respondToAuthChallengeResult = provider.respondToAuthChallenge(respondToAuthChallengeRequest);
//debug
System.out.println(respondToAuthChallengeResult.getChallengeName());
System.out.println(respondToAuthChallengeResult.getChallengeParameters());
System.out.println(respondToAuthChallengeResult.getAuthenticationResult());
AuthenticationResultType authenticationResultType = respondToAuthChallengeResult.getAuthenticationResult(); //there null is retruned;
Output from sout is:
NEW_PASSWORD_REQUIRED
{userAttributes={"email":"username123#example.com"}, requiredAttributes=[]}
null
I don't configure correctly user pool or something is wrong in code?
Thanks.
This seems like you have created the user through the console or through the AdminCreateUser API. The user needs to create a new password as the state says.
That's my first question, and I've researched but didnt find the answer...
I'm currently developing a REST Webservice using Resteasy. Its working fine but I've come to a doubt: there is a way to return a List OR a Object ?
Let me exemplify: I've got a method to return a LIST of SECTORS that is called after passing a token of authentication.
If the token is OK - It should return the LIST of Sectors.
If the token is not OK - It should return an error which is mapped to a class called ErroGenerico that is an OBJECT.
How can I do that ? Return the OBJECT OR the LIST ?
Make a custom exception ErroGenerico and throw it if the token is not verified.
so, method:
public List<Something> getList(String token) throw ErroGenerico {
// do stuff
}
You can try as below
//Not mandatory to create ListUser you can do without it oo just use arraylist directly
class ListUser extends ArrayList<User> {}
webservice method
#GET
#Path("getObj/{param}")
#Produces("application/json")
public Response getObj(#PathParam("param") String msg) {
ListUser responses = new ListUser();
responses.add(new User("1"));
responses.add(new User("2"));
responses.add(new User("3"));
if("list".equals(msg))
return Response.status(200).entity(responses).build();
User u=new User();
u.setName("Developer");
return Response.status(200).entity(u).build();
}
Client code
Client client = ClientBuilder.newClient();
{
String url = "http://jerseyexample-ravikant.rhcloud.com/rest/jws/getObj/list";
System.out.println(url);
Response response = client.target(url).request().get();
ObjectMapper ob = new ObjectMapper();
Object pojos = response.readEntity(Object.class);
System.out.println(pojos.getClass());
if(pojos instanceof java.util.ArrayList){
ArrayList<User> list = (ArrayList) pojos;
for (Object pojo : list) {
User user = ob.convertValue(pojo, User.class);
System.out.println(user.getName());
}
}else{
System.out.println("user");
User user = ob.convertValue(pojos, User.class);
}
//System.out.println(response);
}
You can check working service at http://jerseyexample-ravikant.rhcloud.com/rest/jws/getObj/list
Here instead of passing list you can pass anything else to get object
In addition to this answer, I've found the article and it worked fine.
resteasy response
I am writing a JUnit test case for a short method and I think I am setting all the required fields to prevent any NullPointerException but filters is always Null due to which my test doesn't go inside the loop. ILocalPostProcessFilter is an interface that is implemented by BaseExceptionPostProcessFilter which is an abstract class and this abstract class is extended by a concrete class MessageToExceptionPostProcessFilter. I don't have any asserts yet so please ignore it.
Method under test:
protected <T extends BaseServiceResponse> T processLocalPostProcessFilters(T resp, Response cResp) throws EISClientException
{
List<ILocalPostProcessFilter> filters = config.getLocalPostProcessFilters();
if(filters == null)
return resp;
T bResp = resp;
for(ILocalPostProcessFilter filter : filters)
{
bResp = filter.postProcess(resp, cResp);
}
return bResp;
}
JUnit test:
#Test
public void testProcessLocalPostProcessFilters() throws Exception {
TestClass baseClient = new TestClass(new ClientConfiguration(), "serviceURL");
CatastropheServiceResponse catastropheServiceResponse = new CatastropheServiceResponse();
CatastropheResponse entity = new CatastropheResponse();
catastropheServiceResponse.setContentLength(10);
catastropheServiceResponse.setContentType(ContentType.XML);
entity.setSource(ResponseSourceEnum.CATASTROPHE);
entity.setTransactionId("01234");
catastropheServiceResponse.setEntity(entity);
Response response = mock(Response.class);
ILocalPostProcessFilter filter = new MessageToExceptionPostProcessFilter();
((BaseExceptionPostProcessFilter) filter).setHttpStatusCode("200");
((BaseExceptionPostProcessFilter) filter).setCondition(ConditionOperator.OR);
List<ILocalPostProcessFilter> listFilter = new ArrayList<>();
listFilter.add(filter);
ClientConfiguration clientConfiguration = new ClientConfiguration();
clientConfiguration.setLocalPostProcessFilters(listFilter);
baseClient.processLocalPostProcessFilters(catastropheServiceResponse, response);
}
Not sure what needs to be done to populate filters.
Any help would be appreciated.
Thanks