@@ -180,13 +180,15 @@ public class AccountContact implements Serializable { | |||||
final AccountAction action = message.getAction(); | final AccountAction action = message.getAction(); | ||||
final ActionTarget target = message.getTarget(); | final ActionTarget target = message.getTarget(); | ||||
if (!verified() | |||||
&& type == AccountMessageType.request | |||||
&& action != AccountAction.verify | |||||
&& target != ActionTarget.account | |||||
&& getType().isVerifiableAuthenticationType()) { | |||||
log.warn("isAllowed("+message.getAction()+"): requests to unverified contacts are not allowed, except to verify them"); | |||||
return false; | |||||
if (!verified()) { | |||||
if (type == AccountMessageType.request | |||||
&& action == AccountAction.verify | |||||
&& target == ActionTarget.account) { | |||||
log.info("isAllowed(" + message.getAction() + "): allowing request to unverified contacts to verify it"); | |||||
} else { | |||||
log.info("isAllowed(" + message.getAction() + "): requests to unverified contacts are not allowed, except to verify them"); | |||||
return false; | |||||
} | |||||
} | } | ||||
switch (action) { | switch (action) { | ||||
@@ -63,6 +63,7 @@ import static org.cobbzilla.wizard.resources.ResourceUtil.*; | |||||
public class AuthResource { | public class AuthResource { | ||||
private static final long NODE_INIT_TIMEOUT = TimeUnit.MINUTES.toMillis(2); | private static final long NODE_INIT_TIMEOUT = TimeUnit.MINUTES.toMillis(2); | ||||
private static final String DATA_ACCOUNT_NAME = "account"; | |||||
@Autowired private AccountDAO accountDAO; | @Autowired private AccountDAO accountDAO; | ||||
@Autowired private AccountPolicyDAO policyDAO; | @Autowired private AccountPolicyDAO policyDAO; | ||||
@@ -254,8 +255,18 @@ public class AuthResource { | |||||
@Context ContainerRequest ctx, | @Context ContainerRequest ctx, | ||||
@PathParam("token") String token, | @PathParam("token") String token, | ||||
NameAndValue[] data) { | NameAndValue[] data) { | ||||
final Account caller = optionalUserPrincipal(ctx); | |||||
Account caller = optionalUserPrincipal(ctx); | |||||
if (!empty(data)) { | |||||
final String accountName = NameAndValue.find(data, DATA_ACCOUNT_NAME); | |||||
final Account account = accountDAO.findById(accountName); | |||||
if (caller != null && account != null && !caller.getUuid().equals(account.getUuid())) { | |||||
return invalid("err.token.invalid"); | |||||
} | |||||
if (caller == null && account == null) { | |||||
return invalid("err.token.invalid"); | |||||
} | |||||
caller = account; | |||||
} | |||||
final AccountMessage approval = messageService.approve(caller, getRemoteHost(req), token, data); | final AccountMessage approval = messageService.approve(caller, getRemoteHost(req), token, data); | ||||
if (approval == null) return invalid("err.token.invalid"); | if (approval == null) return invalid("err.token.invalid"); | ||||
final Account account = validateCallerForApproveOrDeny(caller, approval, token); | final Account account = validateCallerForApproveOrDeny(caller, approval, token); | ||||
@@ -280,7 +291,9 @@ public class AuthResource { | |||||
final Account caller = optionalUserPrincipal(ctx); | final Account caller = optionalUserPrincipal(ctx); | ||||
final Account account = accountDAO.findById(request.getAccount()); | final Account account = accountDAO.findById(request.getAccount()); | ||||
if (account == null) return notFound(request.getAccount()); | if (account == null) return notFound(request.getAccount()); | ||||
if (caller != null && !caller.getUuid().equals(account.getUuid())) return forbidden(); | |||||
if (caller != null && !caller.getUuid().equals(account.getUuid())) { | |||||
return invalid("err.token.invalid"); | |||||
} | |||||
final AccountPolicy policy = policyDAO.findSingleByAccount(account.getUuid()); | final AccountPolicy policy = policyDAO.findSingleByAccount(account.getUuid()); | ||||
final AccountContact authenticator = policy.getAuthenticator(); | final AccountContact authenticator = policy.getAuthenticator(); | ||||
@@ -302,7 +315,7 @@ public class AuthResource { | |||||
return ok(messageService.determineRemainingApprovals(approval)); | return ok(messageService.determineRemainingApprovals(approval)); | ||||
} | } | ||||
} else { | } else { | ||||
return forbidden(); | |||||
return invalid("err.token.invalid"); | |||||
} | } | ||||
} | } | ||||
@@ -14,9 +14,10 @@ If you did not make this request or would like to cancel this request, please cl | |||||
---------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------- | ||||
---------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------- | ||||
If you DID make this request and are ready to approve this login, click the link below. | |||||
If you DID make this request and are ready to approve this login, enter this code on the | |||||
login authentication page: | |||||
{{configuration.publicUriBase}}/approve?t={{confirmationToken}} | |||||
{{confirmationToken}} | |||||
---------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------- | ||||
---------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------- | ||||
@@ -367,7 +367,6 @@ err.tgzB64.required=tgzB64 is required | |||||
err.timezone.unknown=An error ocurred trying to determine the time zone | err.timezone.unknown=An error ocurred trying to determine the time zone | ||||
err.timezone.length=Time zone is too long | err.timezone.length=Time zone is too long | ||||
err.timezone.required=Time zone is requird | err.timezone.required=Time zone is requird | ||||
err.token.invalid=Code is incorrect | |||||
err.totpKey.length=TOTP key is required | err.totpKey.length=TOTP key is required | ||||
err.type.notVerifiable=Type is not verifiable | err.type.notVerifiable=Type is not verifiable | ||||
err.type.invalid=Type is invalid | err.type.invalid=Type is invalid | ||||
@@ -62,3 +62,4 @@ field_label_policy_contact_type_authenticator=Authentication App | |||||
field_label_policy_contact_verified=Verified | field_label_policy_contact_verified=Verified | ||||
field_label_policy_contact_verify_code=Enter Verification Code | field_label_policy_contact_verify_code=Enter Verification Code | ||||
button_label_submit_verify_code=Verify | button_label_submit_verify_code=Verify | ||||
err.token.invalid=Code is incorrect |
@@ -1,3 +1 @@ | |||||
{{network.networkDomain}}: Login requested by {{contact.type}}/{{contact.info}} {{#if contact.nick}}({{contact.nick}}){{/if}} | |||||
Approve: {{configuration.publicUriBase}}/action?approve={{confirmationToken}} | |||||
Deny: {{configuration.publicUriBase}}/action?deny={{confirmationToken}} | |||||
{{network.networkDomain}}: Login requested by {{contact.type}}/{{contact.info}} {{#if contact.nick}}({{contact.nick}}){{/if}} Use code to login: {{confirmationToken}} or to deny request: {{configuration.publicUriBase}}/action?deny={{confirmationToken}} |
@@ -123,7 +123,7 @@ public abstract class ActivatedBubbleModelTestBase extends BubbleModelTestBase { | |||||
} catch (Exception e) { | } catch (Exception e) { | ||||
die("onStart: "+e, e); | die("onStart: "+e, e); | ||||
} | } | ||||
super.onStart(server); | |||||
if (!hasExistingDb) super.onStart(server); | |||||
} | } | ||||
protected CloudService getNetworkStorage(Map<String, Object> ctx, CloudService[] clouds) { | protected CloudService getNetworkStorage(Map<String, Object> ctx, CloudService[] clouds) { | ||||
@@ -1 +1 @@ | |||||
Subproject commit b79193501849222c9865e3be8484bf96327f2419 | |||||
Subproject commit 889c9e17873cd4834683fb61b0afd7cfe97045ea |