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

Documentation and support for WebCrypto #108

Open
macintoshhelper opened this issue Aug 3, 2021 · 2 comments
Open

Documentation and support for WebCrypto #108

macintoshhelper opened this issue Aug 3, 2021 · 2 comments

Comments

@macintoshhelper
Copy link

Hi, WebCrypto usage will generally require the usage of asynchronous APIs. The oauth.authorize function does not support promises for the signature hash function.

I've opened a PR over at #107 which should resolve this, and after that, documentation could be added to the README for a WebCrypto example to replace the CryptoJS, potentially resolving #97

Ref #107

@johtso
Copy link

johtso commented Apr 21, 2022

@macintoshhelper hey, did you ever get WebCrypto signing working?

I spent a bunch of hours trying to write a signature function to use with your fork, but I could never get the signature to validate..

This is the non-working code I ended up with:

import OAuth from 'oauth-1.0a';

const CALLBACK_URL = "https://localhost:3000/oauth/callback";

const encoder = new TextEncoder();

async function signData(baseString: string, keyString: string) {
  return await crypto.subtle.importKey(
    'raw',
    encoder.encode(keyString),
    { name: 'HMAC', hash: 'SHA-1' },
    false,
    ['sign']
  ).then(key => {
    return crypto.subtle.sign(
      "HMAC",
      key,
      encoder.encode(baseString)
    );
  }).then(signature => {
    let b = new Uint8Array(signature);
    // base64 digest
    return btoa(String.fromCharCode(...b));
  });
}

export async function getRequestToken(consumerKey: string, consumerSecret: string) {
  const url = "https://www.flickr.com/services/oauth/request_token";
  const token = {
    key: consumerKey,
    secret: consumerSecret
  }
  const oauth = new OAuth({
    consumer: token,
    signature_method: 'HMAC-SHA1',
    hash_function: signData,
  });
  const requestData = {
    url,
    method: 'GET',
    data: {
      oauth_callback: CALLBACK_URL
    }
  };

  const authorisedRequest = await oauth.authorizeAsync(requestData, token);
  let params = new URLSearchParams();
  for (let [key, value] of Object.entries(authorisedRequest)) {
    params.append(key, value as string);
  }
  const response = await fetch(requestData.url + `?${params}`, {
    method: requestData.method,
  });

  const body = await response.text();
  const parsedBody = oauth.deParam(body);
  return parsedBody;
}

@lumnn
Copy link

lumnn commented Nov 27, 2023

I've got this working with following code and pull request #118

const oauth = new OAuth({
  consumer: {
    key,
    secret
  },
  signature_method: 'HMAC-SHA256',
  async hash_function(baseString, key) {
    // encoder to convert string to Uint8Array
    var enc = new TextEncoder();

    const cryptKey = await crypto.subtle.importKey(
      'raw',
      enc.encode(key),
      { name: 'HMAC': hash: 'SHA-256' },
      false,
      ['sign', 'verify'],
    )

    const signature = await crypto.subtle.sign(
      { name: 'HMAC': hash: 'SHA-256' },
      cryptKey,
      enc.encode(baseString)
    )

    let b = new Uint8Array(signature);
    // base64 digest
    return btoa(String.fromCharCode(...b));
  }
})

const auth = await oauth.authorize(
  {
    method: method.toUpperCase(),
    url,
  },
  {
    key: this.options.accessToken,
    secret: this.options.tokenSecret
  }
)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants