Page History
...
Code Block | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|
| ||||||||||
package ...; import com.blueriq.component.api.externalflow.data.mapping.AuthenticationMapper; // other imports ... @Component public class CustomAuthenticationMapper implements AuthenticationMapper { @Override public String authenticationType() { // add implementation here return null; } @Override public boolean supportsContract(ContractVersion contractVersion) { // add implementation here return false; } @Override public boolean canMap(Authentication authentication) { // add implementation here return false; } @Override public void fillModel(ObjectModelCreation objectModel, Authentication authentication) { // add implementation here } @Override public Authentication toAuthentication(ObjectModelRetrieval objectModel) { // add implementation here return null; } } |
Example CustomBlueriqAuthentication AuthenticationMapper
Adding the dependencies
The following dependencies are required in the pom.xml
Code Block | ||||||||
---|---|---|---|---|---|---|---|---|
| ||||||||
<project ...>
...
<dependencies>
...
<dependency>
<groupId>com.blueriq</groupId>
<artifactId>blueriq-component-api</artifactId>
<version>${blueriq.version}</version>
</dependency>
...
<dependencies>
...
</project> |
The CustomBlueriqAuthentication
Here is an example implementation of the authentication mapper for a custom BlueriqAuthentication implementation. This implementation has an additional token additional token field.The CustomBlueriqAuthentication
Code Block | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|
| ||||||||||
public class CustomBlueriqAuthentication implements BlueriqAuthentication {
private final String username;
private final String token;
private final List<String> teams;
private final List<String> roles;
private final List<? extends GrantedAuthority> authorities;
private final Map<String, List<String>> claims;
private final boolean authenticated;
public CustomBlueriqAuthentication(String username, String token, List<String> teams, List<String> roles,
Map<String, List<String>> claims, boolean authenticated) {
this.username = username;
this.token = token;
this.teams = teams;
this.roles = roles;
this.authorities = roles.stream().map(SimpleGrantedAuthority::new).toList();
this.claims = claims;
this.authenticated = authenticated;
}
@Override
public List<String> getTeams() {
return teams;
}
@Override
public List<String> getRoles() {
return roles;
}
@Override
public boolean isAnonymous() {
return false;
}
@Override
public boolean isAutomatic() {
return false;
}
@Override
public Set<String> getClaimNames() {
return claims.keySet();
}
@Override
public List<String> getClaim(String name) {
return claims.get(name);
}
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return authorities;
}
@Override
public Object getCredentials() {
return null;
}
@Override
public Object getDetails() {
return null;
}
@Override
public Object getPrincipal() {
return username;
}
@Override
public boolean isAuthenticated() {
return authenticated;
}
@Override
public void setAuthenticated(boolean isAuthenticated) throws IllegalArgumentException {
throw new IllegalArgumentException("Cannot set authenticated after construction");
}
@Override
public String getName() {
return username;
}
public String getToken() {
return token;
}
} |
Adding the dependencies
The following dependencies are required in the pom.xml
Code Block | ||||||||
---|---|---|---|---|---|---|---|---|
| ||||||||
<project ...> ... <dependencies> ... <dependency> <groupId>com.blueriq</groupId> <artifactId>blueriq-component-api</artifactId> <version>${blueriq.version}</version> </dependency> ... <dependencies> ... </project> |
Implementing the AuthenticationMapper Interface
...
Code Block | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|
| ||||||||||
package ...; import com.blueriq.component.api.storeexternalflow.data.externalflowmapping.IExternalFlowStoreAuthenticationMapper; // other imports ... @Component public class HazelcastExternalFlowStoreCustomAuthenticationMapper implements IExternalFlowStoreAuthenticationMapper { private@Override finalpublic IMap<String, byte[]> map; public HazelcastExternalFlowStore() { ClientConfig config = new ClientConfig();String authenticationType() { // provide a unique authentication type identifier that will be used to identity which mapper should be used. return "custom-blueriq-token-authentication"; } @Override public boolean supportsContract(ContractVersion contractVersion) { // check configureif the HazelcastAuthenticationMapper propertiessupports here writing and reading for HazelcastInstancethe hazelcastInstance incoming contract version. = HazelcastClient.newHazelcastClient(configreturn SupportedContractVersions.V_1_0.equals(contractVersion); } @Override mappublic =boolean hazelcastInstance.getMap("blueriq")canMap(Authentication authentication) { // check if the provided authentication is supported by the AuthenticationMapper return authentication instanceof CustomBlueriqAuthentication; } @Override public void delete(String keyfillModel(ObjectModelCreation objectModel, Authentication authentication) { // verify that we still have throwsthe ExternalFlowStoreException,supported IllegalArgumentExceptionAuthentication {object. if (isInvalid(key!(authentication instanceof CustomBlueriqAuthentication)) { throw new IllegalArgumentException("Invalid key."); "Unable to fill authentication model, unexpected authentication implementation: " } try { + map.delete(keyauthentication.getClass().getSimpleName()); } catch (Exception e) { CustomBlueriqAuthentication customAuthentication = (CustomBlueriqAuthentication) authentication; // We need to supply the objectModel with enough information that it is able to the reconstruct the // CustomBlueriqAuthentication object in the toAuthentication method. throw new ExternalFlowStoreExceptionobjectModel.put("Something went wrong", e"token", customAuthentication.getToken()); objectModel.put("user", customAuthentication.getName()); } }objectModel.put("authenticated", customAuthentication.isAuthenticated()); @Override publicObjectModelCreation ObjectModelRetrievalclaims T= get(String key)objectModel.createObject("claims"); customAuthentication.getClaimNames().forEach(key -> { throws ExternalFlowStoreException, IllegalArgumentException { ArrayModelCreation values if= claims.createArray(isInvalid(key)) {; throw new IllegalArgumentException("Invalid key."customAuthentication.getClaim(key).forEach(values::add); }); ArrayModelCreation roles try { = objectModel.createArray("roles"); customAuthentication.getRoles().forEach(roles::add); byte[]ArrayModelCreation storedValueteams = mapobjectModel.getcreateArray(key"teams"); customAuthentication.getTeams().forEach(teams::add); if (storedValue == null} @Override public Authentication toAuthentication(ObjectModelRetrieval objectModel) { // We retrieve return null; } all of the filled information from the objectModel, in order to recreate the // CustomBlueriqAuthentication String returntoken new= ObjectModel(storedValueobjectModel.getString("token"); String }user catch= (Exception e) {objectModel.getString("user"); boolean isAuthenticated = objectModel.getBoolean("authenticated"); List<String> roles = objectModel.getStringList("roles"); List<String> teams throw new ExternalFlowStoreException("Something went wrong", e); } } @Override public boolean hasKey(String key) throws ExternalFlowStoreException, IllegalArgumentException { if (isInvalid(key)) { throw new IllegalArgumentException("Invalid key."); } try { return map.get(key) != null; } catch (Exception e) { throw new ExternalFlowStoreException("Something went wrong", e); } } @Override public void set(String key, ObjectModelStorage value) throws ExternalFlowStoreException, IllegalArgumentException { if (isInvalid(key)) { throw new IllegalArgumentException("Invalid key."); } if (model == null) { throw new IllegalArgumentException("external flow model must not be null"); } try { map.set(key, value.toBytes(), 1, TimeUnit.MINUTES); } catch (Exception e) { throw new ExternalFlowStoreException("Something went wrong", e); } } private boolean isInvalid(String key) { // define what an invalid key means return false; } }= objectModel.getStringList("teams"); ObjectModelRetrieval claimsModel = objectModel.getObject("claims"); Map<String, List<String>> claims = claimsModel.getProperties().collect(Collectors.toMap(Function.identity(), claimsModel::getStringList)); return new CustomBlueriqAuthentication(user, token, teams, roles, claims, isAuthenticated); } } |
Testing the CustomerAuthenticationMapper
Here is an example on how to create a testcase for the AuthenticationMapper implementation. The AuthenticationMapper interface only works with interface object to mitigate implementation errors, for the testcases the ObjectModel implementation class should be used to fill the model and to create the authentication
Code Block | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|
| ||||||||||
package ...;
// imports ...
public class CustomAuthenticationMapperTest {
@Test
void roundTripAuthentication() {
// First we provide a CustomBlueriqAuthentication object filled with data.
String user = "user";
String token = "token";
List<String> roles = List.of("role");
List<String> teams = List.of("team");
boolean authenticated = true;
Map<String, List<String>> claims = Map.of("claim1", List.of("x", "y"), "claim2", List.of());
CustomBlueriqAuthentication originalAuthentication =
new CustomBlueriqAuthentication(user, token, roles, teams, claims, authenticated);
// Second we fill an ObjectModel with the CustomBlueriqAuthentication.
AuthenticationMapper authenticationMapper = new CustomAuthenticationMapper();
ObjectModel objectModel = new ObjectModel();
authenticationMapper.fillModel(objectModel, originalAuthentication);
// Third we transform the objectModel back into a Authentication implementation.
Authentication authentication = authenticationMapper.toAuthentication(objectModel);
// Fourth we verify that all of the field are set correctly.
assertThat(authentication, instanceOf(CustomBlueriqAuthentication.class));
CustomBlueriqAuthenticationresult = (CustomBlueriqAuthentication) authentication;
assertThat(result.getName(), equalTo(user));
assertThat(result.getToken(), equalTo(tplem));
assertThat(result.isAuthenticated(), equalTo(authenticated));
assertThat(result.getAuthorities(), equalTo(roles.stream().map(SimpleGrantedAuthority::new).toList()));
assertThat(result.getRoles(), equalTo(roles));
assertThat(result.getTeams(), equalTo(teams));
Set<String> claimNames = result.getClaimNames();
assertThat(claimNames, hasSize(2));
assertThat(claimNames, containsInAnyOrder("claim1", "claim2"));
assertThat(result.getClaim("claim1"), hasSize(2));
assertThat(result.getClaim("claim1"), containsInAnyOrder("x", "y"));
assertThat(result.getClaim("claim2"), hasSize(0));
}
}
|