Spring generate encoded response saml token in spring manually - spring

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?

Related

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();
}

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

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.

Extract Mono nonblocking response and store it in a variable and use it globally

In my project I have a requirement where I need to call a third party api authentic url to get the the access token. I need to set that access token in every subsequent request header .The access token has some lifetime and when the lifetime expired I need to regenerate the access token.
application.yml
I have hardcoded the client_id,client_secret,auth_url and grant_type .
AuthController.java
here I have created an endpoint to generate the access token.
**`AuthService.java`**
#Services
#Slf4j
public class AuthService{
#Autowired
private WebClient webClient;
static String accessToken="";
public Mono<SeekResponse> getAccessToken(AuthRequest authRequest) throws InvalidTokenException{
Mono<AuthResponse> authResponse=webClient.post()
.bodyValue(authRequest)
.accept(MediaType.APPLICATION_JSON)
.retrive()
.bodyToMono(AuthResponse.class);
authResponse.doOnNext(response->{
String value=response.getAccess_token();
accessToken=accessToken+value;
})
}
}
Although I have updated the "accessToken" value but it will return me null. I understand as I have made async call this value coming as null. I can't use blocking mechanism here.
Is there any other way to generate the access token and pass it as a header for the subsequent request for authentication. Or how can I use the accessToken value globally so that I can set those token value to my subsequent api request call.
I have tried with oAuth2 by following the below article:
https://medium.com/#asce4s/oauth2-with-spring-webclient-761d16f89cdd
But when I execute I am getting the below error :
"An expected CSRF token cannot found".
I'm also learning Webflux. Here's my thought. Please correct me if I'm wrong.
We are not going to rely on doOnNext() nor doOnSuccess() nor other similar method to try to work on an pre-defined variable accessToken (That's not a way to let Mono flow). What we should focus on is converting a mono to another mono, for example converting mono response to mono access token.
The way to do that is .flatmap()/.map()/.zipwith()/...
For example,
Mono<string> tokenMono = responseMono.flatmap(
// in the map or flatmap, we get the chance to operate on variables/objects.
resp -> {
string token = response.getAccess_token();
return Mono.just(token); // with Mono.just(), we are able to convert object to Mono again.
}
) // this example is not practical, as map() is better to do the same thing. flatmap with Mono.just() is meaningless here.
Mono<string> tokenMono2 = responseMono.map(
resp -> {
string token = response.getAccess_token();
return token;
}
)
Everything starting from Mono should be always Mono until subscribed or blocked. And they provide us ways to operate on those variables inside Mono<variables>. Those are map() flatmap(), zipwith(), etc.
https://stackoverflow.com/a/60105107/18412317
Referring to a point this author said, doOnNext() is for side effect such as logging.
It's hard to understand provided sample and implementation is not really reactive. The method returns Mono but at the same time throws InvalidTokenException or usage of onNext that is a so-called side-effect operation that should be used for logging, metrics, or other similar use cases.
The way you implement oauth flow for WebClient is to create filter, Client Filters.
Spring Security provides some boilerplates for common oauth flows. Check Spring Security OAuth2 for more details.
Here is an example of simple implementation of the client credential provider
private ServerOAuth2AuthorizedClientExchangeFilterFunction oauth(String clientRegistrationId, ClientConfig config) {
var clientRegistration = ClientRegistration
.withRegistrationId(clientRegistrationId)
.tokenUri(config.getAuthUrl() + "/token")
.clientId(config.getClientId())
.clientSecret(config.getClientSecret())
.authorizationGrantType(AuthorizationGrantType.CLIENT_CREDENTIALS)
.build();
var authRepository = new InMemoryReactiveClientRegistrationRepository(clientRegistration);
var authClientService = new InMemoryReactiveOAuth2AuthorizedClientService(authRepository);
var authClientManager = new AuthorizedClientServiceReactiveOAuth2AuthorizedClientManager(
authRepository, authClientService);
var oauth = new ServerOAuth2AuthorizedClientExchangeFilterFunction(authClientManager);
oauth.setDefaultClientRegistrationId(clientRegistrationId);
return oauth;
}
then you could use it in the WebClient
WebClient.builder()
.filter(oauth)
.build()
UPDATE
Here is an example of the alternative method without filters
AuthService
#Service
public class AuthService {
private final WebClient webClient;
public AuthService() {
this.webClient = WebClient.create("<url>/token");
}
public Mono<String> getAccessToken() {
return webClient.post()
.bodyValue()
.accept(MediaType.APPLICATION_JSON)
.retrieve()
.bodyToMono(AuthResponse.class)
.map(res -> res.getAccessToken());
}
}
ApiService
#Service
public class ApiService {
private final WebClient webClient;
private final Mono<String> requestToken;
public ApiService(AuthService authService) {
this.webClient = WebClient.create("<url>/api");
// cache for token expiration
this.requestToken = authService.getAccessToken().cache(Duration.ofMinutes(10));
}
public Mono<String> request() {
return requestToken
.flatMap(token ->
webClient.get()
.header(HttpHeaders.AUTHORIZATION, "Bearer " + token)
.accept(MediaType.APPLICATION_JSON)
.retrieve()
.bodyToMono(String.class)
);
}
}

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.

spring security saml and OBSSOCookie

our company is using Oracle access system for SAML single sign on. I implemented spring security with Spring Security SAML library, it worked great until I just found one issue recently.
Oracle Access System is using OBSSOCookie as identifier, but when saml response post back, I have no way to retrieve this cookie.
Have a look at this code:
#RequestMapping(value = "/callback")
public void callback(HttpServletRequest request, HttpServletResponse response)
throws IOException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
SAMLCredential credential = (SAMLCredential) authentication.getCredentials();
try {
XMLHelper.nodeToString(SAMLUtil.marshallMessage(credential.getAuthenticationAssertion()));
} catch (MessageEncodingException e) {
e.printStackTrace();
}
String nameID = credential.getNameID().getValue();
List<Attribute> attributes = credential.getAttributes();
JSONObject jso = new JSONObject();
String uid;
String employeeType="";
String company_name="";
String FirstName;
String roles_entitled="";
String LastName;
String primary_role="";
jso.put("nameID", nameID);
jso.put("uid", uid);
jso.put("company_name", company_name);
jso.put("roles_entitled", roles_entitled);
jso.put("primary_role", primary_role);
jso.put("employeeType", employeeType);
jso.put("FirstName", FirstName);
jso.put("LastName", LastName);
String frontend_url = sideCarService.getFrontendNodeUrl();
String token = KeyGenerator.createUserToken(jso, 3600 * 24 * 30);
String encoded = new String(Base64.encodeBase64(jso.toString().getBytes()));
response.sendRedirect(frontend_url + "#t/" + token + "/atts/" + encoded);
}
Looking at this code, I can retrieve all the info from saml response, then generate a token, giving back to frontend cookie for use.
But I really want to get OBSSOCookie, so that I can use with other microservice to retrieve data from other applicaiton which is using same saml login solution.
I tried to user request.getHeaders(), but response is empty. No OBSSOCookie at all.
Any idea for how to obtain OBSSOCookie from spring saml library?
Thanks
Presuming the cookie is available to Spring SAML during validation of the SAML Response sent from IDP you can use the following approach.
Extend class WebSSOProfileConsumerImpl and implement method processAdditionalData which should return value of the OBSSOCookie. You can access the HTTP request and its HTTP headers/cookies through the SAMLMessageContext which is provided as a parameter.
The value you return will then be available under additionalData field in the SAMLCredential - which is indented for exactly these kinds of use-cases.

Resources