I'm working on an authentication plugin that uses JWT parsing to get details and update the user in Mesh.
I'd like to also create a new node and attach it to the User in Mesh, using the user.setNodeReference()
// Is this how I associate a User to a node?
The problem is when I return the mapping result, if I create the user profile node, I see the mapToken()
method invoked again with the same token as before, like it's looping. I've found this is due to the 'retry' capabilities in the router
If I dont attach a node to the user.nodeReference()
then it proceeds as expected.
Thoughts?
@Override
public MappingResult mapToken(HttpServerRequest req, String uuid, JsonObject token) {
MappingResult result = new MappingResult();
if (uuid == null) {
log.info("First time login of the user");
} else {
log.info("Already synced user is logging in.");
}
log.info("Mapping user in plugin");
printToken(token);
String username = extractUsername(token).get();
UserUpdateRequest user = new UserUpdateRequest();
user.setUsername(username);
user.setEmailAddress(username);
user.setFirstname(token.getString("firstname", "firstname"));
user.setLastname(token.getString("lastname", "lastname"));
// TODO: Stop the infinite loop
if (uuid == null) {
log.info("Creating profile node");
user.setNodeReference(createProfileNode(username, token));
} else {
log.info("Updating profile node");
//updateProfileNode(uuid, token);
}
result.setUser(user);
...
}
private ExpandableNode createProfileNode(String username, JsonObject token) {
NodeCreateRequest nodeCreateRequest = new NodeCreateRequest()
.setLanguage("en")
.setSchemaName(getConfig().getProfileSchema())
.setParentNodeUuid(getConfig().getProfileParentUuid());
FieldMap fields = nodeCreateRequest.getFields();
fields.putString("name", username);
fillProfileFieldMappedValues(fields, token);
nodeCreateRequest.setFields(fields);
return this.adminClient.createNode(getConfig().getProjectName(), nodeCreateRequest).blockingGet();
}
Update
I checked the jti & iat - the token contains both.
I thought maybe if I subscribe to the USER_CREATED event, I could add a profile node after the user is created.
But I don't see this ever executed. I may be incorrectly subscribing to the local event bus.
getRxVertx().eventBus().localConsumer(MeshEvent.USER_CREATED.getAddress()).handler((message) -> {
try {
String uuid = JsonUtil.getMapper().readTree(message.body().toString()).get("uuid").asText();
adminClient().findUserByUuid(uuid).toSingle().doAfterSuccess(u -> {
u.setNodeReference(createProfileNode(u.getUuid()).getBody());
}).doOnError(e -> {
log.error("Failed to create user profile node: {}", e);
});
} catch (IOException e) {
log.error("Failed to deserialize user: {}", e);
}
});
Also, I don't need to set the user.setNodeReference()
to reproduce the error, I only need to try creating a new node in the mapToken
method. It will retry creating the user 10x then error out with an http 500.
I'll turn up logging to see if I can get more details.
Update I've found that if I create the user first in the mapToken
function, then create a node for the profile, I can add it to the user.setNodeReference()
but I never see the node in the content browser [I create it at `{project}/profiles/{userProfileNode}], and I'm not able to see the node reference when I retrieve the user.
But the logs show the node was created successfully.
Does your token contain a token Id? (jti or iat). Mesh will use one of these values to determine whether the key mapping needs to be re-run for the token. The idea behind this is to avoid bogus mapping calls for tokens that have not changed. I suspect your token does not pass this check and will be passed always to the mapper plugin.
I might be able to give you more hints if I could see some logs.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.