Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Validate Attestation Requests #1468

Merged
merged 15 commits into from
Oct 30, 2019

Conversation

nambrot
Copy link
Contributor

@nambrot nambrot commented Oct 24, 2019

Description

This PR adds more validation of attestation requests. Specifcally it checks for:

  • well formed requests
  • validity of the requests on the Attestations contracts
  • check if we already sent the SMS before

Tested

  • Ran locally with attestation requests on integration

Related issues

(await existingAttestationRequest(request.phoneNumber, request.account, request.issuer)) !==
null
) {
throw new Error('Attestation already sent')
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So this implies users cannot request another delivery if the SMS did not arrive?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correct, not at this moment, though we could consider circumstances in which the user could re-request.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Re-requesting is a pretty useful debugging tool for verification atm. I'd say (anecdotally) half the time I get 2/3, the third comes if I retry verification. So a better alternative here would be a retry threshold, which could be just 1 time for now. But I understand that's a fair bit more complexity here so open to deferring that to another PR if you prefer

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would prefer to keep this out for another PR. Raised #1502 for it.

const attestationCode = signAttestation(req.body.phoneNumber, req.body.account)
const textMessage = createAttestationTextMessage(attestationCode)
export async function handleAttestationRequest(
_req: express.Request,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why the underscore?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In typescript (and many other languages), a leading underscore indicates the parameter not being used. Not prefixing is I believe a lint violation (or maybe even compiler?)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

huh, didn't know that!

attestationRequest.account,
attestationRequest.issuer
)
await retryAsyncWithBackOff(sendSms, 10, [attestationRequest.phoneNumber, textMessage], 1000)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: wrapping the phone number and txt message in an array seems odd to me

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's our current interface into retryAsyncWithBackOff which I don't think we have much alternative to unless we convert all our functions to only take one argument?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if we make change to signature to move up the delay param and then have ...args for the rest, we won't need to wrap the params. But it's nbd

success: false,
error: 'Something went wrong while attempting to send SMS, try again later',
})
.status(422)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

did you mean to include this here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did not!

account: string,
issuer: string
): Promise<AttestationStatic | null> {
const AttestationTable = await Attestation(sequelize!)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't know anything about sequelize, just wondering if it'd be better to cache this AttestationTable object instead of recreating it? maybe a non-issue

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I personally don't like global caching too much so eventually there should probably be a cache manager, but I figured for now it's no big deal

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you but it above in the global scope, it's not actually global caching, it's module level caching, which is totally fine. If you don't export the cache var, it won't pollute your global scope. I think the bias against is mostly a holdover from browser days when the polluting the global scope was a big issue.
But yeah really nbd, just a thought.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I changed it to module level caching!

@@ -0,0 +1,36 @@
'use strict'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks like a compiled file. Why is this here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's a generated file by sequelize scaffold. It looks like it is supposed to give unified access to all the models, but since we are not using that, I will remove the file

import { either, isLeft } from 'fp-ts/lib/Either'
import * as t from 'io-ts'

export function parseRequest<T>(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this some kind of fp-ts pattern? This structure of a function that returns a function which uses another function as a param seems more complex than it has to be.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I actually tried to minimize the style impact of fp-ts here, so this should mostly be a single-level function composition. Basically, when one writes an express handler, a developer would have to do some amount of logic to validate that the request has the right payload, types, etc.

To avoid that duplicated logic, a developer could use parseRequest(RequestType, processor) to receive the parsed request as a third argument. So IMO you get the benefit of declarative routes in https://github.com/celo-org/celo-monorepo/pull/1468/files#diff-8b9f369026f23d51728f7ad563386fdcR22, while the actual request handler has to not deal with the validation of the request payload and can just rely on it been validated by parseRequest https://github.com/celo-org/celo-monorepo/pull/1468/files#diff-881b8cc344bdb8ee0e96c73fb379ee6fR94

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay seems reasonable. I guess I may just have been thrown off by the names them. Maybe handler is a more conventional name for processor and createValidatedHandler is a more accurate name than parseRequest? Unless these are fp-ts terms

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nope, they are just @nambrot™ , so changed them to your suggestion!

@nambrot nambrot requested a review from cmcewen as a code owner October 26, 2019 01:08
request.issuer
)

console.info(state)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nope (at least not in this form)

import { either, isLeft } from 'fp-ts/lib/Either'
import * as t from 'io-ts'

export function parseRequest<T>(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay seems reasonable. I guess I may just have been thrown off by the names them. Maybe handler is a more conventional name for processor and createValidatedHandler is a more accurate name than parseRequest? Unless these are fp-ts terms

@codecov
Copy link

codecov bot commented Oct 28, 2019

Codecov Report

Merging #1468 into master will decrease coverage by 8.41%.
The diff coverage is 50%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master    #1468      +/-   ##
==========================================
- Coverage   73.74%   65.33%   -8.42%     
==========================================
  Files         277      271       -6     
  Lines        7420     8181     +761     
  Branches      660      501     -159     
==========================================
- Hits         5472     5345     -127     
- Misses       1836     2716     +880     
- Partials      112      120       +8
Flag Coverage Δ
#mobile 65.33% <50%> (-8.42%) ⬇️
Impacted Files Coverage Δ
packages/mobile/src/tokens/saga.ts 87.83% <50%> (-2.02%) ⬇️
packages/mobile/src/web3/selectors.ts 80% <0%> (-20%) ⬇️
packages/mobile/src/alert/reducer.ts 60% <0%> (-12.73%) ⬇️
packages/mobile/src/import/reducer.ts 42.85% <0%> (-12.7%) ⬇️
packages/mobile/src/utils/dynamicLink.ts 64.7% <0%> (-12.22%) ⬇️
packages/mobile/src/networkInfo/reducer.ts 60% <0%> (-11.43%) ⬇️
packages/mobile/src/home/reducers.ts 50% <0%> (-10%) ⬇️
packages/mobile/src/app/reducers.ts 33.33% <0%> (-9.53%) ⬇️
packages/mobile/src/invite/JoinCelo.tsx 72.72% <0%> (-8.97%) ⬇️
packages/mobile/src/exchange/reducer.ts 66.66% <0%> (-8.34%) ⬇️
... and 261 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 578a8e2...8358842. Read the comment docs.

@nambrot nambrot assigned jmrossy and unassigned nambrot and mcortesi Oct 28, 2019
@jmrossy jmrossy assigned nambrot and unassigned jmrossy Oct 30, 2019
@nambrot nambrot added the automerge Have PR merge automatically when checks pass label Oct 30, 2019
@celo-ci-bot-user celo-ci-bot-user merged commit 51c359d into master Oct 30, 2019
@celo-ci-bot-user celo-ci-bot-user deleted the nambrot/attestation-service-validation branch October 30, 2019 22:09
aaronmgdr added a commit that referenced this pull request Nov 2, 2019
* master: (62 commits)
  Fix e2e on CI (#1537)
  Allow a specified address to disable/enable the Exchange  (#1467)
  Avoid re-encrypting key files with yarn keys:encrypt command (#1560)
  Support protocol hotfixing (#613)
  Point e2e tests back (#1562)
  Refactor to Accounts.sol (#1392)
  Add selectIssuers Transaction (#1327)
  [Wallet] Get React Native Hot Reloading Working (#1551)
  Unify to prefix messages for signing (#1473)
  [Wallet] Improve error handling around account creation and keystore ops (#1497)
  Add CI test for checking licenses and misc package.json cleanup (#1550)
  [Wallet] Implement SMS invite on iOS (#1541)
  CI: brings back to master (#1554)
  Validators: uses Ethereum address for proof of possession (#1494)
  Validate Attestation Requests (#1468)
  Rename hosted node references to forno (#1511)
  Bump rubyzip from 1.2.3 to 1.3.0 in /packages/mobile (#1508)
  Added txpool family to geth apis. Sorted geth cmd options (#1462)
  [Wallet] Fix yarn dev command for running android (#1534)
  [Wallet] iOS info plist changes and version bump (#1539)
  ...

# Conflicts:
#	yarn.lock
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
automerge Have PR merge automatically when checks pass
Projects
None yet
4 participants