in sources/src/main/java/com/google/solutions/jitaccess/web/proposal/AbstractProposalHandler.java [64:142]
abstract void onOperationProposed(
@NotNull JitGroupContext.JoinOperation operation,
@NotNull Proposal proposal,
@NotNull ProposalHandler.ProposalToken token,
@NotNull URI actionUri
) throws AccessException, IOException;
/**
* Notify relevant users about the completion of a proposal.
*/
abstract void onProposalApproved(
@NotNull JitGroupContext.ApprovalOperation operation,
@NotNull Proposal proposal
) throws AccessException, IOException;
//---------------------------------------------------------------------------
// ProposalHandler.
//---------------------------------------------------------------------------
@Override
public @NotNull ProposalHandler.ProposalToken propose(
@NotNull JitGroupContext.JoinOperation joinOperation,
@NotNull Function<String, URI> buildActionUri
) throws AccessException {
var proposal = joinOperation.propose(
Instant.now().plus(this.options.tokenExpiry));
Preconditions.checkArgument(
!proposal.recipients().isEmpty(),
"Recipients must not be empty");
Preconditions.checkArgument(
!proposal.recipients().contains(proposal.user()),
"Recipients must not contain the requesting user");
//
// Encode all inputs into a token and sign it.
//
var inputs = new GenericJson();
proposal.input()
.entrySet()
.forEach(p -> inputs.set(p.getKey(), p.getValue()));
var jwtId = new byte[6];
this.jwtIdGenerator.nextBytes(jwtId);
var payload = new JsonWebToken.Payload()
.setJwtId(Base64.getEncoder().encodeToString(jwtId))
.set(Claims.RECIPIENT, proposal.recipients()
.stream()
.sorted()
.map(PrincipalId::toString)
.toArray())
.set(Claims.GROUP_ID, joinOperation.group().toString())
.set(Claims.USER_ID, proposal.user().toString())
.set(Claims.INPUT, inputs);
try {
var signedToken = this.tokenSigner.sign(
payload,
proposal.expiry());
var proposalToken = new ProposalToken(
signedToken.token(),
proposal.recipients(),
signedToken.expiryTime());
onOperationProposed(
joinOperation,
proposal,
proposalToken,
buildActionUri.apply(proposalToken.value()));
return proposalToken;
}
catch (AccessException | IOException e) {
throw new AccessDeniedException(
"Creating a proposal failed", e);
}
}