Change /authentication API to pass data in request body instead of URL arguments (FINERACT-726)
This commit is contained in:
committed by
Michael Vorburger ⛑️
parent
ba6f778d85
commit
a93a6b8487
+8
-3
@@ -34,6 +34,7 @@ import java.util.Random;
|
|||||||
import java.util.TimeZone;
|
import java.util.TimeZone;
|
||||||
|
|
||||||
import com.jayway.restassured.RestAssured;
|
import com.jayway.restassured.RestAssured;
|
||||||
|
import com.jayway.restassured.http.ContentType;
|
||||||
import com.jayway.restassured.path.json.JsonPath;
|
import com.jayway.restassured.path.json.JsonPath;
|
||||||
import com.jayway.restassured.response.Response;
|
import com.jayway.restassured.response.Response;
|
||||||
import com.jayway.restassured.specification.RequestSpecification;
|
import com.jayway.restassured.specification.RequestSpecification;
|
||||||
@@ -62,7 +63,7 @@ public class Utils {
|
|||||||
public static final String TENANT_TIME_ZONE = "Asia/Kolkata";
|
public static final String TENANT_TIME_ZONE = "Asia/Kolkata";
|
||||||
|
|
||||||
private static final String HEALTH_URL = "/fineract-provider/actuator/health";
|
private static final String HEALTH_URL = "/fineract-provider/actuator/health";
|
||||||
private static final String LOGIN_URL = "/fineract-provider/api/v1/authentication?username=mifos&password=password&" + TENANT_IDENTIFIER;
|
private static final String LOGIN_URL = "/fineract-provider/api/v1/authentication?" + TENANT_IDENTIFIER;
|
||||||
|
|
||||||
public static void initializeRESTAssured() {
|
public static void initializeRESTAssured() {
|
||||||
RestAssured.baseURI = "https://localhost";
|
RestAssured.baseURI = "https://localhost";
|
||||||
@@ -116,9 +117,13 @@ public class Utils {
|
|||||||
try {
|
try {
|
||||||
logger.info("Logging in, for integration test...");
|
logger.info("Logging in, for integration test...");
|
||||||
System.out.println("-----------------------------------LOGIN-----------------------------------------");
|
System.out.println("-----------------------------------LOGIN-----------------------------------------");
|
||||||
final String json = RestAssured.post(LOGIN_URL).asString();
|
String json = RestAssured.given().contentType(ContentType.JSON)
|
||||||
|
.body("{\"username\":\"mifos\", \"password\":\"password\"}")
|
||||||
|
.expect().log().ifError().when().post(LOGIN_URL).asString();
|
||||||
assertThat("Failed to login into fineract platform", StringUtils.isBlank(json), is(false));
|
assertThat("Failed to login into fineract platform", StringUtils.isBlank(json), is(false));
|
||||||
return JsonPath.with(json).get("base64EncodedAuthenticationKey");
|
String key = JsonPath.with(json).get("base64EncodedAuthenticationKey");
|
||||||
|
assertThat("Failed to obtain key: " + json, StringUtils.isBlank(key), is(false));
|
||||||
|
return key;
|
||||||
} catch (final Exception e) {
|
} catch (final Exception e) {
|
||||||
if (e instanceof HttpHostConnectException) {
|
if (e instanceof HttpHostConnectException) {
|
||||||
final HttpHostConnectException hh = (HttpHostConnectException) e;
|
final HttpHostConnectException hh = (HttpHostConnectException) e;
|
||||||
|
|||||||
+26
-9
@@ -22,6 +22,7 @@ import java.util.ArrayList;
|
|||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
import javax.ws.rs.Consumes;
|
||||||
import javax.ws.rs.POST;
|
import javax.ws.rs.POST;
|
||||||
import javax.ws.rs.Path;
|
import javax.ws.rs.Path;
|
||||||
import javax.ws.rs.Produces;
|
import javax.ws.rs.Produces;
|
||||||
@@ -48,15 +49,22 @@ import org.springframework.security.core.Authentication;
|
|||||||
import org.springframework.security.core.GrantedAuthority;
|
import org.springframework.security.core.GrantedAuthority;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import com.google.gson.Gson;
|
||||||
|
|
||||||
import com.sun.jersey.core.util.Base64;
|
import com.sun.jersey.core.util.Base64;
|
||||||
|
|
||||||
@Path("/authentication")
|
|
||||||
@Component
|
@Component
|
||||||
@Profile("basicauth")
|
|
||||||
@Scope("singleton")
|
@Scope("singleton")
|
||||||
|
@Profile("basicauth")
|
||||||
|
@Path("/authentication")
|
||||||
@Api(value = "Authentication HTTP Basic", description = "An API capability that allows client applications to verify authentication details using HTTP Basic Authentication.")
|
@Api(value = "Authentication HTTP Basic", description = "An API capability that allows client applications to verify authentication details using HTTP Basic Authentication.")
|
||||||
public class AuthenticationApiResource {
|
public class AuthenticationApiResource {
|
||||||
|
|
||||||
|
public static class AuthenticateRequest {
|
||||||
|
public String username;
|
||||||
|
public String password;
|
||||||
|
}
|
||||||
|
|
||||||
private final DaoAuthenticationProvider customAuthenticationProvider;
|
private final DaoAuthenticationProvider customAuthenticationProvider;
|
||||||
private final ToApiJsonSerializer<AuthenticatedUserData> apiJsonSerializerService;
|
private final ToApiJsonSerializer<AuthenticatedUserData> apiJsonSerializerService;
|
||||||
private final SpringSecurityPlatformSecurityContext springSecurityPlatformSecurityContext;
|
private final SpringSecurityPlatformSecurityContext springSecurityPlatformSecurityContext;
|
||||||
@@ -74,16 +82,25 @@ public class AuthenticationApiResource {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@POST
|
@POST
|
||||||
|
@Consumes({ MediaType.APPLICATION_JSON })
|
||||||
@Produces({ MediaType.APPLICATION_JSON })
|
@Produces({ MediaType.APPLICATION_JSON })
|
||||||
@ApiOperation(value = "Verify authentication", notes = "Authenticates the credentials provided and returns the set roles and permissions allowed.")
|
@ApiOperation(value = "Verify authentication", notes = "Authenticates the credentials provided and returns the set roles and permissions allowed.")
|
||||||
@ApiResponses({@ApiResponse(code = 200, message = "", response = AuthenticationApiResourceSwagger.PostAuthenticationResponse.class), @ApiResponse(code = 400, message = "Unauthenticated. Please login")})
|
@ApiResponses({@ApiResponse(code = 200, message = "", response = AuthenticationApiResourceSwagger.PostAuthenticationResponse.class), @ApiResponse(code = 400, message = "Unauthenticated. Please login")})
|
||||||
public String authenticate(@QueryParam("username") @ApiParam(value = "username") final String username, @QueryParam("password") @ApiParam(value = "password") final String password) {
|
public String authenticate(final String apiRequestBodyAsJson) {
|
||||||
|
// TODO FINERACT-819: sort out Jersey so JSON conversion does not have to be done explicitly via GSON here, but implicit by arg
|
||||||
|
AuthenticateRequest request = new Gson().fromJson(apiRequestBodyAsJson, AuthenticateRequest.class);
|
||||||
|
if (request == null) {
|
||||||
|
throw new IllegalArgumentException("Invalid JSON in BODY (no longer URL param; see FINERACT-726) of POST to /authentication: " + apiRequestBodyAsJson);
|
||||||
|
}
|
||||||
|
if (request.username == null || request.password == null) {
|
||||||
|
throw new IllegalArgumentException("Username or Password is null in JSON (see FINERACT-726) of POST to /authentication: " + apiRequestBodyAsJson + "; username=" + request.username + ", password=" + request.password);
|
||||||
|
}
|
||||||
|
|
||||||
final Authentication authentication = new UsernamePasswordAuthenticationToken(username, password);
|
final Authentication authentication = new UsernamePasswordAuthenticationToken(request.username, request.password);
|
||||||
final Authentication authenticationCheck = this.customAuthenticationProvider.authenticate(authentication);
|
final Authentication authenticationCheck = this.customAuthenticationProvider.authenticate(authentication);
|
||||||
|
|
||||||
final Collection<String> permissions = new ArrayList<>();
|
final Collection<String> permissions = new ArrayList<>();
|
||||||
AuthenticatedUserData authenticatedUserData = new AuthenticatedUserData(username, permissions);
|
AuthenticatedUserData authenticatedUserData = new AuthenticatedUserData(request.username, permissions);
|
||||||
|
|
||||||
if (authenticationCheck.isAuthenticated()) {
|
if (authenticationCheck.isAuthenticated()) {
|
||||||
final Collection<GrantedAuthority> authorities = new ArrayList<>(authenticationCheck.getAuthorities());
|
final Collection<GrantedAuthority> authorities = new ArrayList<>(authenticationCheck.getAuthorities());
|
||||||
@@ -91,7 +108,7 @@ public class AuthenticationApiResource {
|
|||||||
permissions.add(grantedAuthority.getAuthority());
|
permissions.add(grantedAuthority.getAuthority());
|
||||||
}
|
}
|
||||||
|
|
||||||
final byte[] base64EncodedAuthenticationKey = Base64.encode(username + ":" + password);
|
final byte[] base64EncodedAuthenticationKey = Base64.encode(request.username + ":" + request.password);
|
||||||
|
|
||||||
final AppUser principal = (AppUser) authenticationCheck.getPrincipal();
|
final AppUser principal = (AppUser) authenticationCheck.getPrincipal();
|
||||||
final Collection<RoleData> roles = new ArrayList<>();
|
final Collection<RoleData> roles = new ArrayList<>();
|
||||||
@@ -111,11 +128,11 @@ public class AuthenticationApiResource {
|
|||||||
boolean isTwoFactorRequired = twoFactorUtils.isTwoFactorAuthEnabled() && !
|
boolean isTwoFactorRequired = twoFactorUtils.isTwoFactorAuthEnabled() && !
|
||||||
principal.hasSpecificPermissionTo(TwoFactorConstants.BYPASS_TWO_FACTOR_PERMISSION);
|
principal.hasSpecificPermissionTo(TwoFactorConstants.BYPASS_TWO_FACTOR_PERMISSION);
|
||||||
if (this.springSecurityPlatformSecurityContext.doesPasswordHasToBeRenewed(principal)) {
|
if (this.springSecurityPlatformSecurityContext.doesPasswordHasToBeRenewed(principal)) {
|
||||||
authenticatedUserData = new AuthenticatedUserData(username, principal.getId(),
|
authenticatedUserData = new AuthenticatedUserData(request.username, principal.getId(),
|
||||||
new String(base64EncodedAuthenticationKey), isTwoFactorRequired);
|
new String(base64EncodedAuthenticationKey), isTwoFactorRequired);
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
authenticatedUserData = new AuthenticatedUserData(username, officeId, officeName, staffId, staffDisplayName,
|
authenticatedUserData = new AuthenticatedUserData(request.username, officeId, officeName, staffId, staffDisplayName,
|
||||||
organisationalRole, roles, permissions, principal.getId(),
|
organisationalRole, roles, permissions, principal.getId(),
|
||||||
new String(base64EncodedAuthenticationKey), isTwoFactorRequired);
|
new String(base64EncodedAuthenticationKey), isTwoFactorRequired);
|
||||||
}
|
}
|
||||||
@@ -124,4 +141,4 @@ public class AuthenticationApiResource {
|
|||||||
|
|
||||||
return this.apiJsonSerializerService.serialize(authenticatedUserData);
|
return this.apiJsonSerializerService.serialize(authenticatedUserData);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+6
-6
@@ -25,16 +25,17 @@ import org.springframework.context.annotation.Profile;
|
|||||||
import org.springframework.context.annotation.Scope;
|
import org.springframework.context.annotation.Scope;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import javax.ws.rs.Consumes;
|
||||||
import javax.ws.rs.POST;
|
import javax.ws.rs.POST;
|
||||||
import javax.ws.rs.Path;
|
import javax.ws.rs.Path;
|
||||||
import javax.ws.rs.Produces;
|
import javax.ws.rs.Produces;
|
||||||
import javax.ws.rs.QueryParam;
|
import javax.ws.rs.QueryParam;
|
||||||
import javax.ws.rs.core.MediaType;
|
import javax.ws.rs.core.MediaType;
|
||||||
|
|
||||||
@Path("/self/authentication")
|
|
||||||
@Component
|
@Component
|
||||||
@Profile("basicauth")
|
|
||||||
@Scope("singleton")
|
@Scope("singleton")
|
||||||
|
@Profile("basicauth")
|
||||||
|
@Path("/self/authentication")
|
||||||
@Api(value = "Self Authentication", description = "")
|
@Api(value = "Self Authentication", description = "")
|
||||||
public class SelfAuthenticationApiResource {
|
public class SelfAuthenticationApiResource {
|
||||||
|
|
||||||
@@ -47,12 +48,11 @@ public class SelfAuthenticationApiResource {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@POST
|
@POST
|
||||||
|
@Consumes({ MediaType.APPLICATION_JSON })
|
||||||
@Produces({ MediaType.APPLICATION_JSON })
|
@Produces({ MediaType.APPLICATION_JSON })
|
||||||
@ApiOperation(value = "Verify authentication", httpMethod = "POST", notes = "Authenticates the credentials provided and returns the set roles and permissions allowed.\n\n" + "Please visit this link for more info - https://demo.openmf.org/api-docs/apiLive.htm#selfbasicauth")
|
@ApiOperation(value = "Verify authentication", httpMethod = "POST", notes = "Authenticates the credentials provided and returns the set roles and permissions allowed.\n\n" + "Please visit this link for more info - https://demo.openmf.org/api-docs/apiLive.htm#selfbasicauth")
|
||||||
@ApiResponses({@ApiResponse(code = 200, message = "OK", response = SelfAuthenticationApiResourceSwagger.PostSelfAuthenticationResponse.class)})
|
@ApiResponses({@ApiResponse(code = 200, message = "OK", response = SelfAuthenticationApiResourceSwagger.PostSelfAuthenticationResponse.class)})
|
||||||
public String authenticate(@QueryParam("username") @ApiParam(value = "username") final String username,
|
public String authenticate(final String apiRequestBodyAsJson) {
|
||||||
@QueryParam("password") @ApiParam(value = "password") final String password) {
|
return this.authenticationApiResource.authenticate(apiRequestBodyAsJson);
|
||||||
return this.authenticationApiResource.authenticate(username, password);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user