I'm trying to use the following code to upload a blockblob to Azure-Storage in a react app. However, I'm getting the following error.
TypeError: SharedKeyCredential is not a constructor
Any ideas?
#azure/storage-blob#10.3.0
import React from 'react';
const {
Aborter,
BlobURL,
BlockBlobURL,
ContainerURL,
ServiceURL,
StorageURL,
SharedKeyCredential,
AnonymousCredential,
TokenCredential
} = require("#azure/storage-blob"); // Change to "#azure/storage-blob" in your package
function App() {
return (
<div className="App">
<button onClick={onClicked()} />
</div>
);
async function onClicked() {
// Enter your storage account name and shared key
const account = "REMOVED_MY_ACCOUNT";
const accountKey = "REMOVED_ACCOUNT_KEY";
// Use SharedKeyCredential with storage account and account key
const sharedKeyCredential = new SharedKeyCredential(account, accountKey);
// Use TokenCredential with OAuth token
const tokenCredential = new TokenCredential("token");
tokenCredential.token = "renewedToken"; // Renew the token by updating token field of token credential
// Use AnonymousCredential when url already includes a SAS signature
const anonymousCredential = new AnonymousCredential();
// Use sharedKeyCredential, tokenCredential or anonymousCredential to create a pipeline
const pipeline = StorageURL.newPipeline(sharedKeyCredential);
// List containers
const serviceURL = new ServiceURL(
// When using AnonymousCredential, following url should include a valid SAS or support public access
`https://${account}.blob.core.windows.net`,
pipeline
);
// Create a container
const containerName = `newcontainer${new Date().getTime()}`;
const containerURL = ContainerURL.fromServiceURL(serviceURL, containerName);
const createContainerResponse = await containerURL.create(Aborter.none);
console.log(
`Create container ${containerName} successfully`,
createContainerResponse.requestId
);
// Create a blob
const content = "hello";
const blobName = "newblob" + new Date().getTime();
const blobURL = BlobURL.fromContainerURL(containerURL, blobName);
const blockBlobURL = BlockBlobURL.fromBlobURL(blobURL);
const uploadBlobResponse = await blockBlobURL.upload(
Aborter.none,
content,
content.length
);
console.log(
`Upload block blob ${blobName} successfully`,
uploadBlobResponse.requestId
);
}
}
export default App;
Edit:
I was calling the wrong API. You can create a new Visual Studio project that uses the .Net/React template. This was the code example I was looking for.
I'm the developer of storage JS SDK. SharedKeyCredential is only available in Node.js runtime. For browsers, for security concerns, please use Shared Access Signature (SAS) or OAuth Token for your authentications.
Related
I am trying to upload image from react to azure blob storage but the request fails with error :
TypeError: Cannot read properties of undefined (reading 'size')
at BlockBlobClient.uploadFile
here is a sample of code trying to achieve it :
import { BlobServiceClient } from '#azure/storage-blob';
const account = process.env.REACT_APP_AZURE_ACCOUNT_NAME;
const sas = process.env.REACT_APP_SAS_TOKEN;
const containerName = 'usercontainer';
const blobServiceClient = new BlobServiceClient(
`https://${account}.blob.core.windows.net/?${sas}`,
);
export const uploadToBlob = async (file) => {
const containerClient = blobServiceClient.getContainerClient(containerName);
const blobName = file.src + new Date().getTime();
const blockBlobClient = containerClient.getBlockBlobClient(blobName);
const uploadBlobResponse = await blockBlobClient.uploadFile(file.src);
console.log(
`Upload block blob ${blobName} successfully`,
uploadBlobResponse.requestId,
);
};
There are a few issues here:
You are calling uploadFile method which is only available in NodeJS runtime and is not available in the browser. Please see documentation of this method here: https://learn.microsoft.com/en-us/javascript/api/#azure/storage-blob/blockblobclient?view=azure-node-latest##azure-storage-blob-blockblobclient-uploadfile.
The method you would want to use is uploadData which expects an object of type Blob. Considering you have a data URL, you would need to create a Blob object out of it. Please see this question regarding converting a data URL to Blob: Blob from DataURL?
I'm currently using react-native-secure-storage to store JWTs for my user. The app retrieves data from an Express API so when making an HTTP request I retrieve the token from secure storage and when the async function completes the token is sent it to the API. I've run into a problem now which is that I want to make a component with an image in it served from the API but I can't get the JWT in an async function since the component needs to return immediately. My question is can I just temporarily store the JWT in a variable or in component state?
Yes, you can store it in a variable, in a context, or in a state. I would recommend using React.context() to propapate your JWT token.
Example:
const JwtStuffContext = React.createContext({
jwt: null,
});
const YourApp = () => {
const theToken = 'abc';
return <JwtStuffContext.Provider value={{ jwt: theToken }}>
{/** The rest of your app, or {children} */}
</JwtStuffContext.Provider>
}
const SomewhereDownTheReactTree = () => {
const { jwt } = useContext(JwtStuffContext);
}
Note that if you wanted to avoid sharing the JWT directly with your entire application, you could a function in your state that would proxy your API requests.
However, as you mentioned displaying an image, you could create a special Picture component that fetches the token from your store, and then requests the image from the API. Like so:
const Picture = ({ placeholderSrc, getSrcWithToken }) => {
const [token, setToken] = useState(null);
useEffect(() => {
const token = await yourFunctionToFetchTokenFromstore();
setToken(token);
}, [finalSrc]);
return <img src={token !== null ? getSrcWithToken(token) : placeholderSrc } />;
}
The above would display the placeholderSrc for as long as the token is unknown, when the token is known, it would call the prop function getSrcWithToken passing the token, allowing you to construct the URL if you need to.
Trying to set up user authentication with firebase for my react project and I don't get any results using signInWithRedirect() and getRedirectResult().
So basically upon clicking a button, I am redirected to the google auth site but then after I am sent back to my homepage I receive no data but I can see in the firebase authentication menu that a new user is added. And when I use signInWithPopup() everything works fine and I get user data the way I want but since this app is mostly for mobile users I need to use signInWithRedirect(). Pls, can anyone help?
//Exported from another component
export const app = initializeApp(firebaseConfig);
export const provider = new GoogleAuthProvider();
//Sign in
const signInWithGoogle = () => {
signInWithRedirect(auth, provider);
};
and in other threads, I have seen that you should get the data upon the page initial loading, so i thought using useEffect would solve my problem but it does not
//Get results
useEffect(() => {
getRedirectResult(auth, provider)
.then((result) => {
// This gives you a Google Access Token. You can use it to access Google APIs.
const credential = GoogleAuthProvider.credentialFromResult(result);
const token = credential.accessToken;
// The signed-in user info.
const user = result.user;
console.log(user);
})
.catch((error) => {
// Handle Errors here.
const errorCode = error.code;
const errorMessage = error.message;
// The email of the user's account used.
const email = error.email;
// The AuthCredential type that was used.
const credential = GoogleAuthProvider.credentialFromError(error);
// ...
});
}, []);
I have a react app, where i store all my customerprofile details like username, emailid, roles etc.. Anyone can goto debugger tool view that data, thought of encrypting & decrypting of localstorage but not sure is it good approach? what is the best way to do secure it?
Manjunath! You better store it on backend and get the token from server to frontend and store it in http only cookie, but anyways if your requirement is to store it on frontend, then I'd crypt it with cryptojs or bcyptjs and then store it on frontend, but better in a cookie, so for further integration with backend (if any), you'll be able to send cookie data automatically (for eg, to verify user, etc.). It will be in your req.cookies.
https://www.npmjs.com/package/bcryptjs
we can use react-secure-storage to store and retrieve securely data in localstorage in the fllowing way
secureLocalStorage.setItem("boolean", true); // to store data
secureLocalStorage.getItem("boolean"); // to retrieve data
Example:
import { useEffect } from "react";
import secureLocalStorage from "react-secure-storage";
const App = () => {
useEffect(() => {
secureLocalStorage.setItem("object", {
message: "This is testing of local storage",
});
secureLocalStorage.setItem("number", 12);
secureLocalStorage.setItem("string", "12");
secureLocalStorage.setItem("boolean", true); // to store data
let value = secureLocalStorage.getItem("boolean"); // to retrieve data
}, []);
return (
<div>
This is a sample code
</div>
);
}
export default App;
If you really want to secure your local storage data, use the npm module crypto-js.
Step 1.
npm install crypto-js --save
Step 2. Create a file and call it util.js and paste the following code.
import CryptoJS from 'crypto-js';
export const encryptData = (data, salt) =>
CryptoJS.AES.encrypt(JSON.stringify(data), salt).toString();
export const decryptData = (ciphertext, salt) => {
const bytes = CryptoJS.AES.decrypt(ciphertext, salt);
try {
return JSON.parse(bytes.toString(CryptoJS.enc.Utf8));
}catch(err){
return null;
}
}
Step 3. Encrypt the data using encryptData():
import {encryptData} from './utils';
const originalData={
name:'IDKBlogs'
}
const salt = process.env.SALT || '6d090796-ecdf-11ea-adc1-0242ac112345';
const encryptedData = encryptData(originalData, salt);
localStorage.setItem('SOME_NON_RADABLE_KEY', encryptedData); // SOME_NON_RADABLE_KEY like 'mk' as 'myKey'
Step 4. Decrypt the data using decryptData():
import { decryptData } from './utils';
let mkLocalData = localStorage.getItem('mk');
if(!mkLocalData){
// Handle, if there is no data in localStorage, or if someone deleted the localStorage.
}
const salt = process.env.SALT || '6d090796-ecdf-11ea-adc1-0242ac112345';
const originalData = decryptData(mkLocalData, salt);
if(!originalData){
// will executes if someone altered the code in localstorage.
}
You can learn more about this here https://idkblogs.com/js/304/Secure-your-app-data-in-localStorage
I'm integrating WalletConnect in React DApp but am getting
this.send is not a function
I've identified that the issue is with WalletConnectProvider but i've followed the same steps that are mentioned in their documentation.
Please review my code and let me know how to fix this issue. Thanks.
import WalletConnectProvider from '#walletconnect/web3-provider';
import config from './config';
import Web3 from 'web3';
export const walletConnect = async (setAddr) => {
// Create WalletConnect Provider
const provider = new WalletConnectProvider({
infuraId: config.tokenContract.infuraKey, // Required
});
// Enable session (triggers QR Code modal)
await provider.enable();
console.log('provider', provider);
if (provider.connected) {
console.log('wallet connect address', provider.accounts[0]);
setAddr(provider.accounts[0]);
}
// Create Web3
const web3 = new Web3(provider);
console.log('web3', web3);
const _contract = new web3.eth.Contract(
config.tokenContract.contractABI,
config.tokenContract.contractAddress
);
const data = await _contract.methods.hatchNest().encodeABI();
const gasPrice = 20000000000;
const gasLimit = 90000;
const tx = {
from: '0xFF12586A1eCf65b56d828712A8d4B48D1CEC8962',
to: config.tokenContract.contractAddress,
data: data,
gasPrice: web3.utils.toHex(gasPrice),
gasLimit: web3.utils.toHex(gasLimit),
};
// Send Transaction
const txHash = await web3.eth.sendTransaction(tx);
console.log('sendTransaction', txHash);
};
It is a known bug in web3.js 1.3.x
https://github.com/ethereum/web3.js/issues/3790
Downgrade for web3.js 1.2.x.