Is there any way to mask body content in Spring Rest Docs? - spring

I am using JWT authentication with Spring Security, where authentication requests have to contain the username and password in their body.
I do not want the credentials I use in the test to be displayed in Rest Docs.
This is the test in which I want to hide the credentials.
#Test
public void testAuthenticate() throws Exception {
RequestBuilder request = MockMvcRequestBuilders
.post("/authenticate")
.contentType(MediaType.APPLICATION_JSON)
.content("{\"username\": \""+username+
"\", \"password\": \"" +password+"\" }");
MvcResult result = mvc.perform(request)
.andExpect(status().isOk())
.andDo(document("{methodName}"
, preprocessRequest(prettyPrint())
,preprocessResponse(prettyPrint())
,responseFields(fieldWithPath("jwtToken").description("token"))))
.andReturn();
The documentation only talks about removing headers with preprocessRequest(), as far as I understood.
Thank you very much for your time.

Related

Spring generate encoded response saml token in spring manually

How to generate saml response token manually, like encoded string ? I have test like this
#Test
public void testSuccessCase() throws Exception {
WebSSOProfileConsumerImpl customWebSSOProfileConsumer = (WebSSOProfileConsumerImpl) webSSOProfileConsumer;
customWebSSOProfileConsumer.setResponseSkew(1111111111);
String samlToken = "PHNhbWxwOlJlc3BvbnNlIHhtbG5zOnNhbWxwPSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6cHJvdG9jb2wiIElEPSJfYzVlNmZjNmNkYmRmYTRlZTUwNmQiICBWZXJzaW9uPSIyLjAiIElzc3VlSW5zdGFudD0iMjAyMi0wOS0yOFQxMzo1MTo1Ny43NThaIiAgRGVzdGluYXRpb249Imh0dHA6Ly9sb2NhbGhvc3Qvc2FtbC9TU08iPjxzYW1sOklzc3VlciB4bWxuczpzYW1sPSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6YXNzZXJ0aW9uIj51cm46ZGV2LWc5MS1hc2s1LnVzLmF1dGgwLmNvbTwvc2FtbDpJc3N1ZXI+PHNhbWxwOlN0YXR1cz48c2FtbHA6U3RhdHVzQ29kZSBWYWx1ZT0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOnN0YXR1czpTdWNjZXNzIi8+PC9zYW1scDpTdGF0dXM+PHNhbWw6QXNzZXJ0aW9uIHhtbG5zOnNhbWw9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDphc3NlcnRpb24iIFZlcnNpb249IjIuMCIgSUQ9Il96WjBkRDF0c0VYcmgyZExMUjFpNE0xdGoyMzVmWVpLayIgSXNzdWVJbnN0YW50PSIyMDIyLTA5LTI4VDEzOjUxOjU3LjcwOVoiPjxzYW1sOklzc3Vlcj51cm46ZGV2LWc5MS1hc2s1LnVzLmF1dGgwLmNvbTwvc2FtbDpJc3N1ZXI+PFNpZ25hdHVyZSB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC8wOS94bWxkc2lnIyI+PFNpZ25lZEluZm8+PENhbm9uaWNhbGl6YXRpb25NZXRob2QgQWxnb3JpdGhtPSJodHRwOi8vd3d3LnczLm9yZy8yMDAxLzEwL3htbC1leGMtYzE0biMiLz48U2lnbmF0dXJlTWV0aG9kIEFsZ29yaXRobT0iaHR0cDovL3d3dy53My5vcmcvMjAwMS8wNC94bWxkc2lnLW1vcmUjcnNhLXNoYTI1NiIvPjxSZWZlcmVuY2UgVVJJPSIjX3paMGREMXRzRVhyaDJkTExSMWk0TTF0ajIzNWZZWktrIj48VHJhbnNmb3Jtcz48VHJhbnNmb3JtIEFsZ29yaXRobT0iaHR0cDovL3d3dy53My5vcmcvMjAwMC8wOS94bWxkc2lnI2VudmVsb3BlZC1zaWduYXR1cmUiLz48VHJhbnNmb3JtIEFsZ29yaXRobT0iaHR0cDovL3d3dy53My5vcmcvMjAwMS8xMC94bWwtZXhjLWMxNG4jIi8+PC9UcmFuc2Zvcm1zPjxEaWdlc3RNZXRob2QgQWxnb3JpdGhtPSJodHRwOi8vd3d3LnczLm9yZy8yMDAxLzA0L3htbGVuYyNzaGEyNTYiLz48RGlnZXN0VmFsdWU+bE9mVEhsVTZpOGdhNHFpalBycWlMM1IwTjdmd1h5NUU4M1MwY3EybXczRT08L0RpZ2VzdFZhbHVlPjwvUmVmZXJlbmNlPjwvU2lnbmVkSW5mbz48U2lnbmF0dXJlVmFsdWU+aW9QQng1MWp2WEllTkNBVjRLV2cvYlBMVi91ejk2UHFiYkdBODFIUjBTM3VzL3dMc0tIYk9STFRQWWxWM1V1WmJieHlYbnJ5TmcvUWlVbE44dXdURTFiTG1Bem9mM3ZkQjNXOEZ2SUZoUDdBNVF5R2VzZjZyblpmZDI0YjJhcy95cFI4UnVXYkNZK0kwSXRZOEowVVBybEJkTElJUHNiZ1J2ZXlZcUxmMXQ5T0o4c1FEWW1xWHdoYXRKRGdLR1FOOVVFbXRSdUh4OFVlbTF1Sk9RQTBhVkNUcU85VlB2Z25kRWtMSWJhbWNEQmxoTG1hanhpc2g1Q3Vtbi9Ldm9EQVo0UzJiaG9RMm10TG5BQ1dHek5NeHQ4UGNVZ25XR2VTZjMrTXF4VkxrQ3pCZkhzeXdjblRqOFhSL2c5T2haY3R5Y0c2cFF3R0tNWTRsalBUeXQvQkdRPT08L1NpZ25hdHVyZVZhbHVlPjxLZXlJbmZvPjxYNTA5RGF0YT48WDUwOUNlcnRpZmljYXRlPk1JSUREVENDQWZXZ0F3SUJBZ0lKYUFsUERjSzA2RTRVTUEwR0NTcUdTSWIzRFFFQkN3VUFNQ1F4SWpBZ0JnTlZCQU1UR1dSbGRpMW5PVEV0WVhOck5TNTFjeTVoZFhSb01DNWpiMjB3SGhjTk1qSXdPVEUyTURjME9USTNXaGNOTXpZd05USTFNRGMwT1RJM1dqQWtNU0l3SUFZRFZRUURFeGxrWlhZdFp6a3hMV0Z6YXpVdWRYTXVZWFYwYURBdVkyOXRNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDQVFFQTRib0NYcFlDczJodmRTeEdjaDVNZ0J2a1FrM0k3ZE1IN242TXZNdW9kZlJIOEl5Ym1iMHB6K2lRZytJNDZsd25xcUhobGZuRVFJQTJoVmRLWllOWXpGenRnV0VxdEcvYVhEWnFWTTJKdG52QTlNN2twU3FTdG9RM2tRNjlFN0h2WVBiYmdZUGVnakVWRFFpdjhoRk03MGVHbU9zRkRFWkk1WkpjRzlYdk8rUHZmSG5yV2laZ1kwMlhsTzM1T2xYMlljcEU4RVVjZ2FQSVRoQTVaWi9uaXVoczJubzlGS1IwbFVhRm0rOGY1eCs2Q2dEdlRBUkgxRmtnTkxENFRrNmlCMzNrTFdLY0NmRHFxLzJUdW5WbTgzZXV5bCt4aTBOVW8vL3paZlBMNlpyd2dXZ2xDYk8wVFp0eEVJUEsvaFpkbjNROXJkNnJJTmZtaEZpTmFQNlRhUUlEQVFBQm8wSXdRREFQQmdOVkhSTUJBZjhFQlRBREFRSC9NQjBHQTFVZERnUVdCQlQzVFZSU05OQVBnNlFzNmNQRjFIT1ArdTBxbHpBT0JnTlZIUThCQWY4RUJBTUNBb1F3RFFZSktvWklodmNOQVFFTEJRQURnZ0VCQUJrbDNKOHdaY0ltNGFjVUZLaEo3T0twSlBsVHoxUVVmZEViM3VPcHF0REZFOVNEOHpDbFBTYS93czRsM3FqQmtiK2JWejFuS0NJRGZudGZ5SE54ZVNIc21Mb0lnTkJhT1B5aG1XNzRlVXhVd01vZjVjT2M5MUhtYUVrYzd6VW16NHZtekZSUTE2bGo2WnV1QnBIU2Q5NGpUekRwNHpPL2J6aDNqWmhyMDlQdUhFQWJydXdNaFNHOThYNm0yU1lZcTYzS24xUER4TlNHWDltK2dTckZJK09mTVE5YS96Rkp3aVFXK3cyOTVveDh5VWptYjhTYnQxc2o4K1dFb045Zy9uZml6K2JpRXhTVkx6T3NPRFpqcFRDTmtiRmUvdkxFVW1ZRzBKcEoxSTRrelpZcnUwWEJrS3NwOFF4a1I4M056YlRCR2xCQk9IQVBsMW5pVU1Yd092dz08L1g1MDlDZXJ0aWZpY2F0ZT48L1g1MDlEYXRhPjwvS2V5SW5mbz48L1NpZ25hdHVyZT48c2FtbDpTdWJqZWN0PjxzYW1sOk5hbWVJRCBGb3JtYXQ9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjEuMTpuYW1laWQtZm9ybWF0OnVuc3BlY2lmaWVkIj5hdXRoMHw2MzI0NDZkYWQ4ZDkwYjI0NzQ4MTQ4NzQ8L3NhbWw6TmFtZUlEPjxzYW1sOlN1YmplY3RDb25maXJtYXRpb24gTWV0aG9kPSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6Y206YmVhcmVyIj48c2FtbDpTdWJqZWN0Q29uZmlybWF0aW9uRGF0YSBOb3RPbk9yQWZ0ZXI9IjIwMjItMTEtMDlUMDU6NTE6NTcuNzA5WiIgUmVjaXBpZW50PSJodHRwOi8vbG9jYWxob3N0L3NhbWwvU1NPIi8+PC9zYW1sOlN1YmplY3RDb25maXJtYXRpb24+PC9zYW1sOlN1YmplY3Q+PHNhbWw6Q29uZGl0aW9ucyBOb3RCZWZvcmU9IjIwMjItMDktMjhUMTM6NTE6NTcuNzA5WiIgTm90T25PckFmdGVyPSIyMDIyLTExLTA5VDA1OjUxOjU3LjcwOVoiPjxzYW1sOkF1ZGllbmNlUmVzdHJpY3Rpb24+PHNhbWw6QXVkaWVuY2U+dXJuOnRwLXN0YWdlLm1zaWduaWEuY29tPC9zYW1sOkF1ZGllbmNlPjwvc2FtbDpBdWRpZW5jZVJlc3RyaWN0aW9uPjwvc2FtbDpDb25kaXRpb25zPjxzYW1sOkF1dGhuU3RhdGVtZW50IEF1dGhuSW5zdGFudD0iMjAyMi0wOS0yOFQxMzo1MTo1Ny43MDlaIiBTZXNzaW9uSW5kZXg9Il9aNzltOUhhaC1ZZ0RxMkgtUlVSMEFXVEgxZlB4WTNSSiI+PHNhbWw6QXV0aG5Db250ZXh0PjxzYW1sOkF1dGhuQ29udGV4dENsYXNzUmVmPnVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDphYzpjbGFzc2VzOnVuc3BlY2lmaWVkPC9zYW1sOkF1dGhuQ29udGV4dENsYXNzUmVmPjwvc2FtbDpBdXRobkNvbnRleHQ+PC9zYW1sOkF1dGhuU3RhdGVtZW50PjxzYW1sOkF0dHJpYnV0ZVN0YXRlbWVudCB4bWxuczp4cz0iaHR0cDovL3d3dy53My5vcmcvMjAwMS9YTUxTY2hlbWEiIHhtbG5zOnhzaT0iaHR0cDovL3d3dy53My5vcmcvMjAwMS9YTUxTY2hlbWEtaW5zdGFuY2UiPjxzYW1sOkF0dHJpYnV0ZSBOYW1lPSJodHRwOi8vc2NoZW1hcy54bWxzb2FwLm9yZy93cy8yMDA1LzA1L2lkZW50aXR5L2NsYWltcy9uYW1laWRlbnRpZmllciIgTmFtZUZvcm1hdD0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOmF0dHJuYW1lLWZvcm1hdDp1cmkiPjxzYW1sOkF0dHJpYnV0ZVZhbHVlIHhzaTp0eXBlPSJ4czpzdHJpbmciPmF1dGgwfDYzMjQ0NmRhZDhkOTBiMjQ3NDgxNDg3NDwvc2FtbDpBdHRyaWJ1dGVWYWx1ZT48L3NhbWw6QXR0cmlidXRlPjxzYW1sOkF0dHJpYnV0ZSBOYW1lPSJodHRwOi8vc2NoZW1hcy54bWxzb2FwLm9yZy93cy8yMDA1LzA1L2lkZW50aXR5L2NsYWltcy9lbWFpbGFkZHJlc3MiIE5hbWVGb3JtYXQ9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDphdHRybmFtZS1mb3JtYXQ6dXJpIj48c2FtbDpBdHRyaWJ1dGVWYWx1ZSB4c2k6dHlwZT0ieHM6c3RyaW5nIj5wYXZsby5seXNvdkBtc2lnbmlhLmNvbTwvc2FtbDpBdHRyaWJ1dGVWYWx1ZT48L3NhbWw6QXR0cmlidXRlPjxzYW1sOkF0dHJpYnV0ZSBOYW1lPSJodHRwOi8vc2NoZW1hcy54bWxzb2FwLm9yZy93cy8yMDA1LzA1L2lkZW50aXR5L2NsYWltcy9uYW1lIiBOYW1lRm9ybWF0PSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6YXR0cm5hbWUtZm9ybWF0OnVyaSI+PHNhbWw6QXR0cmlidXRlVmFsdWUgeHNpOnR5cGU9InhzOnN0cmluZyI+c0BzLmNvbTwvc2FtbDpBdHRyaWJ1dGVWYWx1ZT48L3NhbWw6QXR0cmlidXRlPjxzYW1sOkF0dHJpYnV0ZSBOYW1lPSJodHRwOi8vc2NoZW1hcy54bWxzb2FwLm9yZy93cy8yMDA1LzA1L2lkZW50aXR5L2NsYWltcy91cG4iIE5hbWVGb3JtYXQ9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDphdHRybmFtZS1mb3JtYXQ6dXJpIj48c2FtbDpBdHRyaWJ1dGVWYWx1ZSB4c2k6dHlwZT0ieHM6c3RyaW5nIj5wYXZsby5seXNvdkBtc2lnbmlhLmNvbTwvc2FtbDpBdHRyaWJ1dGVWYWx1ZT48L3NhbWw6QXR0cmlidXRlPjxzYW1sOkF0dHJpYnV0ZSBOYW1lPSJodHRwOi8vc2NoZW1hcy5hdXRoMC5jb20vaWRlbnRpdGllcy9kZWZhdWx0L2Nvbm5lY3Rpb24iIE5hbWVGb3JtYXQ9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDphdHRybmFtZS1mb3JtYXQ6dXJpIj48c2FtbDpBdHRyaWJ1dGVWYWx1ZSB4c2k6dHlwZT0ieHM6c3RyaW5nIj5Vc2VybmFtZS1QYXNzd29yZC1BdXRoZW50aWNhdGlvbjwvc2FtbDpBdHRyaWJ1dGVWYWx1ZT48L3NhbWw6QXR0cmlidXRlPjxzYW1sOkF0dHJpYnV0ZSBOYW1lPSJodHRwOi8vc2NoZW1hcy5hdXRoMC5jb20vaWRlbnRpdGllcy9kZWZhdWx0L3Byb3ZpZGVyIiBOYW1lRm9ybWF0PSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6YXR0cm5hbWUtZm9ybWF0OnVyaSI+PHNhbWw6QXR0cmlidXRlVmFsdWUgeHNpOnR5cGU9InhzOnN0cmluZyI+YXV0aDA8L3NhbWw6QXR0cmlidXRlVmFsdWU+PC9zYW1sOkF0dHJpYnV0ZT48c2FtbDpBdHRyaWJ1dGUgTmFtZT0iaHR0cDovL3NjaGVtYXMuYXV0aDAuY29tL2lkZW50aXRpZXMvZGVmYXVsdC9pc1NvY2lhbCIgTmFtZUZvcm1hdD0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOmF0dHJuYW1lLWZvcm1hdDp1cmkiPjxzYW1sOkF0dHJpYnV0ZVZhbHVlIHhzaTp0eXBlPSJ4czpib29sZWFuIj5mYWxzZTwvc2FtbDpBdHRyaWJ1dGVWYWx1ZT48L3NhbWw6QXR0cmlidXRlPjxzYW1sOkF0dHJpYnV0ZSBOYW1lPSJodHRwOi8vc2NoZW1hcy5hdXRoMC5jb20vY2xpZW50SUQiIE5hbWVGb3JtYXQ9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDphdHRybmFtZS1mb3JtYXQ6dXJpIj48c2FtbDpBdHRyaWJ1dGVWYWx1ZSB4c2k6dHlwZT0ieHM6c3RyaW5nIj5IalRVZHNuY1ZVMXdaVXZERWxUVWJVQ0NsbkEwV3RoSjwvc2FtbDpBdHRyaWJ1dGVWYWx1ZT48L3NhbWw6QXR0cmlidXRlPjxzYW1sOkF0dHJpYnV0ZSBOYW1lPSJodHRwOi8vc2NoZW1hcy5hdXRoMC5jb20vY3JlYXRlZF9hdCIgTmFtZUZvcm1hdD0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOmF0dHJuYW1lLWZvcm1hdDp1cmkiPjxzYW1sOkF0dHJpYnV0ZVZhbHVlIHhzaTp0eXBlPSJ4czphbnlUeXBlIj5GcmkgU2VwIDE2IDIwMjIgMDk6NTA6MTggR01UKzAwMDAgKENvb3JkaW5hdGVkIFVuaXZlcnNhbCBUaW1lKTwvc2FtbDpBdHRyaWJ1dGVWYWx1ZT48L3NhbWw6QXR0cmlidXRlPjxzYW1sOkF0dHJpYnV0ZSBOYW1lPSJodHRwOi8vc2NoZW1hcy5hdXRoMC5jb20vZW1haWxfdmVyaWZpZWQiIE5hbWVGb3JtYXQ9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDphdHRybmFtZS1mb3JtYXQ6dXJpIj48c2FtbDpBdHRyaWJ1dGVWYWx1ZSB4c2k6dHlwZT0ieHM6Ym9vbGVhbiI+ZmFsc2U8L3NhbWw6QXR0cmlidXRlVmFsdWU+PC9zYW1sOkF0dHJpYnV0ZT48c2FtbDpBdHRyaWJ1dGUgTmFtZT0iaHR0cDovL3NjaGVtYXMuYXV0aDAuY29tL25pY2tuYW1lIiBOYW1lRm9ybWF0PSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6YXR0cm5hbWUtZm9ybWF0OnVyaSI+PHNhbWw6QXR0cmlidXRlVmFsdWUgeHNpOnR5cGU9InhzOnN0cmluZyI+czwvc2FtbDpBdHRyaWJ1dGVWYWx1ZT48L3NhbWw6QXR0cmlidXRlPjxzYW1sOkF0dHJpYnV0ZSBOYW1lPSJodHRwOi8vc2NoZW1hcy5hdXRoMC5jb20vcGljdHVyZSIgTmFtZUZvcm1hdD0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOmF0dHJuYW1lLWZvcm1hdDp1cmkiPjxzYW1sOkF0dHJpYnV0ZVZhbHVlIHhzaTp0eXBlPSJ4czpzdHJpbmciPmh0dHBzOi8vcy5ncmF2YXRhci5jb20vYXZhdGFyL2IwYWY5ZTljMWMwYWNmMWRjOTNkNGRjOWQ2YmNhZmIxP3M9NDgwJmFtcDtyPXBnJmFtcDtkPWh0dHBzJTNBJTJGJTJGY2RuLmF1dGgwLmNvbSUyRmF2YXRhcnMlMkZzLnBuZzwvc2FtbDpBdHRyaWJ1dGVWYWx1ZT48L3NhbWw6QXR0cmlidXRlPjxzYW1sOkF0dHJpYnV0ZSBOYW1lPSJodHRwOi8vc2NoZW1hcy5hdXRoMC5jb20vdXBkYXRlZF9hdCIgTmFtZUZvcm1hdD0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOmF0dHJuYW1lLWZvcm1hdDp1cmkiPjxzYW1sOkF0dHJpYnV0ZVZhbHVlIHhzaTp0eXBlPSJ4czphbnlUeXBlIj5XZWQgU2VwIDI4IDIwMjIgMTM6NDg6MjUgR01UKzAwMDAgKENvb3JkaW5hdGVkIFVuaXZlcnNhbCBUaW1lKTwvc2FtbDpBdHRyaWJ1dGVWYWx1ZT48L3NhbWw6QXR0cmlidXRlPjxzYW1sOkF0dHJpYnV0ZSBOYW1lPSJodHRwOi8vc2NoZW1hcy5hdXRoMC5jb20vaWRlbnRpZmllciIgTmFtZUZvcm1hdD0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOmF0dHJuYW1lLWZvcm1hdDp1cmkiPjxzYW1sOkF0dHJpYnV0ZVZhbHVlIHhzaTp0eXBlPSJ4czpzdHJpbmciPmF1dGgwfDYzMjQ0NmRhZDhkOTBiMjQ3NDgxNDg3NDwvc2FtbDpBdHRyaWJ1dGVWYWx1ZT48L3NhbWw6QXR0cmlidXRlPjwvc2FtbDpBdHRyaWJ1dGVTdGF0ZW1lbnQ+PC9zYW1sOkFzc2VydGlvbj48L3NhbWxwOlJlc3BvbnNlPg==";
ResultActions perform = this.mockMvc.perform(post("/saml/SSO")
.param("SAMLResponse", samlToken)
.contentType(MediaType.APPLICATION_FORM_URLENCODED));
MvcResult mvcResult = perform.andReturn();
MockHttpServletResponse response = mvcResult.getResponse();
String redirectedUrl = response.getRedirectedUrl();
ResultActions resultActions = perform.andDo(print());
assertThat(redirectedUrl, containsString(authServiceUrl));
}
where I used samlToken which configured for me resource auth0 debug saml opportunity and I set setResponseSkew for use this tken during 111111111 seconds, but this is hard hack and looks like not right solution, so how I can generate this token manually in code like this create some object of clas and then execute some encode function for generate samlToken and use it?

I am getting 401 when I try to get authtoken from using mockMVC in my Junit test

I am using keycloak and oauth2.
I want to test my rest controllers from my unit tests.
when I try to get access token from keycloack end point, I get 401. Not sure where I am going wrong. Tried TCPMON to see the actual HTTP req sent, but it just did not show connection, I still got 401!
the code to get access token is
private String obtainAccessToken(String username, String password) throws Exception {
MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
params.add("grant_type", "password");
params.add("client_id", "my-app");
params.add("client_secret", "a9eb-4373-947b-8ec8722a1558");
params.add("username", username);
params.add("password", password);
System.out.println("---------------------------> ***********");
ResultActions result
= mockMvc.perform(post("https://aurumserver.com:9050/auth/realms/mymn/protocol/openid-connect/token")
.params(params)
.with(httpBasic("my-app","a9eb-4373-947b-8ec8722a1558"))
.accept("application/json;charset=UTF-8"))
.andExpect(status().isOk())
.andExpect(content().contentType("application/json;charset=UTF-8"));
System.out.println("----------------------- > " +result);
String resultString = result.andReturn().getResponse().getContentAsString();
JacksonJsonParser jsonParser = new JacksonJsonParser();
return jsonParser.parseMap(resultString).get("access_token").toString();
}

Integration testing user update controller with MockMvc

I am trying to test to see if the logic behind the user update controller is functioning correctly by creating some simple integration tests using MockMvc.
I am updating users credentials, for security reasons the password doesn't get returned in the response dto, this way I can limit the amount a password is exchanged from the client and the server.
The problem is, how do I test that the password was actually updated before the test is rolled back?
I tried manually performing a login before the test is finished, and if the login fails with the original credentials, the password was updated.
The simple part of the test is straight forward:
#Test
void WhenUserIsAdmin_UserCanUpdateAllFields() throws Exception {
updatedUser.setPassword("newPassword");
String jsonString = mapper.writeValueAsString(updatedUser);
MockHttpServletRequestBuilder builder = TestRequestFactory.authorizationFactoryPUT(URI, "admin");
mockMvc.perform(builder.contentType(MediaType.APPLICATION_JSON).content(jsonString))
.andExpect(status().isOk())
.andExpect(MockMvcResultMatchers.jsonPath("$.firstName").value("admin2"))
.andExpect(MockMvcResultMatchers.jsonPath("$.surnamePaternal").value("admin2"))
.andExpect(MockMvcResultMatchers.jsonPath("$.surnameMaternal").value("admin2"))
.andExpect(MockMvcResultMatchers.jsonPath("$.roleName").value("User"))
.andExpect(MockMvcResultMatchers.jsonPath("$.roleType").value("ROLE_USER"))
.andExpect(MockMvcResultMatchers.jsonPath("$.created").isNotEmpty());
}
and the Factory looks like this
public static MockHttpServletRequestBuilder authorizationFactoryPUT(String url, String user)
throws JsonProcessingException {
return MockMvcRequestBuilders.put(url)
.header(HttpHeaders.AUTHORIZATION, doLogin(user, user));
}
static String doLogin(String user, String pass) throws JsonProcessingException {
LoginRequest loginRequest = new LoginRequest(user, pass);
String resultAsJsonString = restTemplate.postForEntity(loginServer + "/login", loginRequest, String.class).getBody();
LoginResponse loginResponse = mapper.readValue(Objects.requireNonNull(resultAsJsonString), LoginResponse.class);
return loginResponse.getTokenType() + " " + loginResponse.getAccessToken();
}
and inside of the same test I tried
LoginRequest loginRequest = new LoginRequest(user, pass);
String resultAsJsonString = restTemplate.postForEntity(loginServer + "/login", loginRequest, String.class).getBody();
LoginResponse loginResponse = mapper.readValue(Objects.requireNonNull(resultAsJsonString), LoginResponse.class);
and if the response fails whilst mapping or the http response code is a 401. Then all is ok, but it seems like the data is never persisted to the database.
I guess you have test case with #Transactional on top this means that this transaction will never be commited as this is #Test.
So when you make http call by restTemplate the transaction is not commited and the changes will not be visible for the /logIn endpoint. (this is normal http request and is not bounded with the #Test #Transactional)
You can use mockmvc instead of RestTemplate to call login endpoint and assert the results. Both mockmvc will be bounded by same transaction and changes will be visible.
EDIT
In case /login is not part of this service than you should user repository to get password from db at some point. repo.findUserByFirstName maybe and verify what you need. Since this call will be in same transaction the result will be valid also.

Make Angular client login to Spring backend with JWT

I added JWT to my Spring backend following this guide: https://auth0.com/blog/securing-spring-boot-with-jwts/
When I send a PUT request using a software like Postman everything works fine, but as soon as I'm trying to login with my Angular client the data in the HttpServletRequest is empty.
I check the data in the attemptAuthentication method of the JWTLoginFilter in the following way:
#Override
public Authentication attemptAuthentication(HttpServletRequest req, HttpServletResponse res)
throws AuthenticationException, IOException, ServletException {
String reqBody = req.getReader().lines().collect(Collectors.joining(System.lineSeparator()));
// this appears to be empty on angular client calls
System.out.println(reqBody);
ObjectMapper objectMapper = new ObjectMapper().configure(Feature.AUTO_CLOSE_SOURCE, true)
.enable(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT);
AccountCredentials creds = objectMapper.readValue(reqBody, AccountCredentials.class);
return getAuthenticationManager().authenticate(new UsernamePasswordAuthenticationToken(creds.getUsername(),
creds.getPassword(), Collections.emptyList()));
}
I'm sending the request out of the client like this:
const user = {
username: "asdf",
password: "asdf"
};
// imported from '#angular/http'
const headers = new Headers({
'Content-Type': 'application/json'
});
const body = JSON.stringify(user);
return this.http
.put("http://localhost:8080/api/login", body, {headers})
.toPromise()
.then(response => response.json().data as User)
.catch(this.handleError);
My suggestion would be that I'm sending the request body in a wrong way, but I can't see, what I'm doing wrong.
I tried:
sending the body as a regular JS object
sending it wrapped in another object
sending it as a JSON string as shown in the example
using POST instead of PUT (although it works with PUT in Postman)
changing the Content-Type Header to other values
None of this made any data appear in the backend.
If you need more information about anything, please ask me.
I got it.
I needed to allow CORS also on my HttpSecurity object as following:
#Configuration
#EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.cors()
.and()
.so()
.on();
}
}
I'm not really sure, why the requests I sent with Postman could get received without CORS enabled in my HttpSecurity, but nevertheless it's working now.
I hope I can help others with this in future.
This might be the reason, Spring OAuth 2 normally expect a POST request with URL encoded username and password. So try something like this.
return this.http.post(Url, "grant_type=password&username=" + username + "&password=" + password)
I'm not 100% sure if this the case as mine was a Spring-MVC, but I expect it to be very similar.

Spring 3.2 REST API add cookie to the response outside controller

I'm using Spring 3.2.4 and Spring Security 3.2.3 to handle RESTful API call to "get security token" request that returns the token (which would be used to secure subsequent requests to the service). This is a POST request which has a body with username and password and is processed in the controller:
#RequestMapping(method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
#ResponseBody
public SessionTokenResponse getSessionToken(#RequestBody Credentials credentials, ModelAndView interceptorModel) throws AccessException {
final String token = webGate.getSessionTokenForUser(credentials.getUsername(), credentials.getPassword());
LOGGER.debug("Logged in user : " + credentials.getUsername());
interceptorModel.addObject(SessionConstants.INTERCEPTOR_MODEL_TOKEN_KEY, token); // Used by post-processing in interceptors, e.g. add Cookie
return new SessionTokenResponse(ResponseMessages.SUCCESS, token);
}
After the controller has successfully finished processing the request I would like to add a cookie with the token to the response.
I tried HandlerInterceptorAdapter implementation, but I cannot find the way to the the 'token' from the response or ModelAndView:
#Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView interceptorModel) throws Exception {
final String token = (String) interceptorModel.getModel().get(SessionConstants.INTERCEPTOR_MODEL_TOKEN_KEY);
if (token != null) {
final Cookie obsso = new Cookie(cookieName, token);
obsso.setPath(cookiePathUri);
obsso.setDomain(cookieDomain);
obsso.setMaxAge(cookieMaxAge);
response.addCookie(obsso);
}
}
The interceptorModel is null .
It seems that Spring MVC doesn't provide it to the postHandle since the #ResponseBody has been already resolved and there is no need for the ModelAndView anymore (this is just my assumption based on the debugging).
What is the correct way of achieving that (add cookie to the response) outside the controller in the interceptor or maybe listener?
To retrieve the token you can use the request object
request.setAttribute(SessionConstants.INTERCEPTOR_MODEL_TOKEN_KEY, token);
and then in the postHandle
String token = ( String ) request.getAttribute(SessionConstants.INTERCEPTOR_MODEL_TOKEN_KEY);
However I don't think you can add a cookie to the response object in postHandle as the response is already committed.
Perhaps you could store the token information on the servlet context instead.
In your controller, add the token information to the servlet context.
Then implement preHandle, so that every api call can check if token for that user exists on servlet context, if so you can add cookie to the response.

Resources