TTLabs / EvaporateJS

Javascript library for browser to S3 multipart resumable uploads
1.82k stars 206 forks source link

Can I use AWS STS token instead of signAuth link? #402

Open xhe opened 6 years ago

xhe commented 6 years ago

Hi, Hope this is a quick question. Currently our company is changing from regular signerURL (sign auth solution) to using AWS STS (Security Token Service). My question is is that possible to use the session token in evaporateJS instead of passing signerURL? Thanks

jakubzitny commented 6 years ago

Yes, use customAuthMethod as mentioned in [wiki](https://github.com/TTLabs/EvaporateJS/wiki/Evaporate.create()).

xhe commented 6 years ago

Nice, will take a look. Thanks

On Wed, Mar 28, 2018 at 4:36 AM, Jakub Žitný notifications@github.com wrote:

Yes, use customAuthMethod as mentioned in wiki https://github.com/TTLabs/EvaporateJS/wiki/Evaporate.create().

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/TTLabs/EvaporateJS/issues/402#issuecomment-376855508, or mute the thread https://github.com/notifications/unsubscribe-auth/AAN4cyfy1uLT0oENobkOQiLQYHzxCHccks5ti3WtgaJpZM4SwqdL .

shivalkondwar commented 5 years ago

Hi @xhe @jakubzitny can you please share how you used customAuthMethod instead of signerUrl.

jakubzitny commented 5 years ago

Something like this @shivalkondwar

import { createHmac, createHash } from 'crypto'

// NOTE: alternative with node-forge
// import { hmac, md, util as forgeUtil } from 'node-forge'

const HASHING_ALG_SIGNING = 'sha1'
const HASHING_ALG_DIGEST = 'md5'
const OUTPUT_ENCODING = 'base64'

static signRequest(request, secret) {
    // NOTE: alternative
    // const hmacCreator = hmac.create()
    // hmacCreator.start(HASHING_ALG_SIGNING, secret)
    // hmacCreator.update(request)
    // const signedRequest = hmacCreator.digest().data
    // const signedRequestInBase64 = forgeUtil.encode64(signedRequest)

    // NOTE: with node's crypto
    const signedRequest = createHmac(HASHING_ALG_SIGNING, secret).update(request)
    const signedRequestInBase64 = signedRequest.digest(OUTPUT_ENCODING)

    return signedRequestInBase64
}

// NOTE: This is a function that generates customAuthMethod
const createCustomAuthMethod = (tmpSecretKey) => {
    return (signParams, signHeaders, stringToSign, signatureDateTime, canonicalRequest) => {
      // NOTE: RequestUrlParam string starts with ?to_sign= url parameter.
      //   We need to get rid of that. RequestUrlParam also ends with &date=
      //   url parameter. This also not part of the actual request to sign.
      const decodedStringToSign = decodeURIComponent(stringToSign)
      const signedRequest = signRequest(
        decodedStringToSign,
        tmpSecretKey
      )

      return Promise.resolve(signedRequest)
    }
}
12three commented 4 years ago

Is it ok to use a secret key on client side?

jakubzitny commented 4 years ago

Is it ok to use a secret key on client side?

Not really @12three, but if you use proper separation of uploads and roles on s3 it might be OK. You can create a separate IAM and a temporary key+secret pair for a specific upload, this key+secret will only be able to upload to a specific subfolder/path in your bucket and only for a limited time (say 1 hour, depending on what kind of data you're uploading), and during the signing phase, you provide the pair to the client, it will handle the signature and upload stuff, and you invalidate the pair on backend after successful upload.

Now, this is only preferred for cases where it's needed, like uploading stuff via Electron where you need more customizations, or if you don't have a possibility to edit your backend API. If you can though, you should use the signerUrl.