Retrieving API keys from a server using Next.js - reactjs

API keys are supposed to be kept secret, I have an adapter that needs you to pass the API key, in a object. How can I retrieve the API key to pass it in securely on the client?
Something sorta like this
async function connectToWallet() {
const _walletConnect = new walletEVMWalletAdapter({
apiKey: "API_KEY_HERE",
chain: BlockchainTypes.POLYGON,
})
const address = await _walletConnect.connect()
if (address) {
setAccount(address)
}
}
Now I understand if I wanted to make a request, In Next.Js i can use the API folder to keep my keys secure, but here I need to pass in the API key, to first create the connection how can I do this securely.

Related

How can we find the total number of tokens available in a wallet ? (withOut initialising Moralis) -As it is time taking

const Moralis = require('moralis').default
const {EvmChain} = require('#moralisweb3/evm-utils')
const runApp = async () => {
// WithOut Moralis initialising - I want to skip these ------(https://i.stack.imgur.com/u4cGM.jpg)
await Moralis.start({
apiKey: 'api_key_secret'
})
// ------------------
const address = '0xbf820316675F3F96beb7a47Cec34c5aEdf07BD0e'
const chain = EvmChain.GOERLI
const response = await Moralis.EvmApi.token.getWalletTokenBalances({
address,
chain
})
console.log(response.toJSON())
}
runApp()
As every detail of a smartContract is public. I don't want to use the API of a third party like Moralis as it slows the app.
Yes, you are right all the smartContract data on the blockchain is public. But it is not always easy to read this data. To read data from the blockchain you would need to run your own local rpc node or you may have to rely on another 3rd node provider or API provider to read the blockchain data.
Moralis provides the data to users through the API and it is one of the fastest ways to read real-time blockchain data.
If you don't want to use any third-party providers for reading blockchain data, one option is to run your own full RPC node. This requires setting up a server and syncing the entire blockchain to your machine. It gives you the ability to read the data directly from the blockchain. This can be a good option if you have the technical expertise and the resources to set up and maintain a full node.
But this is not an easy option nor the fastest option to choose if you are only looking to get the ERC20 token wallet balances.

How to get Stripe payment intent ID for updating payment intent for PaymentElement

Is there a canonical way to get the PaymentIntent ID in order to update a PaymentIntent? (i.e., to maintain security, etc...).
Specifically, all of the documentation and examples I can find of using Payment Element have you set up a payment intent early and only return a client_secret to the client.
export default async function createPaymentIntentHandler(req, res) {
const stripe = new Stripe(STRIPE_SECRET_KEY));
const body = JSON.parse(req.body);
const paymentIntent = await stripe.paymentIntents.create({
currency: 'USD',
amount: 100,
automatic_payment_methods: {
enabled: true,
},
});
res.status(200).send({clientSecret: paymentIntent.client_secret})
}
In order to update that (e.g., if the user changes the quantity on an order) you need the PaymentIntent ID. Now, the PaymentIntent created on the backend already has it, so you could just return it at the same time as the clientSecret:
res.status(200).send({
clientSecret: paymentIntent.client_secret,
pi_ID: paymentIntent.id
})
and have the client send that when hitting the update payment intent API. I guess the main question is, is there any reason not to do that?
Because there seem to be at least two other ways. First, although this seems like it's probably a bad idea, one could just parse it on the server from the client secret. That is, the client secret takes the form <payment_intent_id>_<secret>, so you could just continue sending only the client secret back to the client on the create request, and then extract the id when the client calls the update api with their client secret.
Second, there exists a client-side Stripe API for querying a payment intent. So, when the client wants to update the payment intent, it could
stripe
.retrievePaymentIntent('{PAYMENT_INTENT_CLIENT_SECRET}')
.then(function(result) {
// call update API
});
This latter seems like unnecessary overhead compared to just sending the ID back as part of the original create request, but maybe there's some reason this is actually preferred?

How to properly encrypt and decrypt passwords using React MongoDB and Express

Currently I am working in dev env on my local machine where I am storing passwords in plain text using MongoDB. I am using express-jwt along with jsonwebtoken for passing user data and authentication. I've researched bcryptjs and bcrypt and I would like to implement whichever is best for React, and Express, for passing hashed passwords to the database from the client. I have found resources for server side, but nothing for client side.
My question is then, what is the methodology for properly saving encrypted passwords on my server when they are passed from a client? How do I encrypt passwords client side then authenticate server side?
I have read some articles saying there is no need to encrypt client side due to ssl, but others say there is an absolute need to encrypt client side. What is the correct way, and how can I implement it on my React application?
Using Bcryptjs, Express and MongoDB:
There is no need to encrpyt client side, you can pass the password as plain text to the server using a post request (through a form usually).
Assuming you have a 'user' schema which looks similar to this:
const userSchema = new mongoose.Schema({
email:{type:String,required:true,unique:true},
password:{type:String,required:true}
},{collection:'users'}
const User= mongoose.model("User",userSchema);
)
On register/sign up in the server, where you handle the request you would hash the user's password like so:
app.post('/signup',async (req,res)=>{
// geting our data from frontend
const {email,password:plainTextPassword}=req.body;
// encrypting our password to store in database
const password = await bcrypt.hash(plainTextPassword,salt);
try {
// storing our user data into database
const response = await User.create({
email,
password
})
return res.redirect('/');
} catch (error) {
console.log(JSON.stringify(error));
if(error.code === 11000){
return res.send({status:'error',error:'email already exists'})
}
throw error
}
})
4.Upon login request (which will also be a post through a form o the client), you will compare the passwords using bcrpyt.compare() function, and if successful, assign a JWT to the user like so, this method assumes the token will be stored in the Cookies.
const verifyUserLogin = async (email,password)=>{
try {
const user = await User.findOne({email}).lean()
if(!user){
return {status:'error',error:'user not found'}
}
if(await bcrypt.compare(password,user.password)){
// creating a JWT token
token = jwt.sign({id:user._id,username:user.email,type:'user'},JWT_SECRET,{ expiresIn: '2h'})
return {status:'ok',data:token}
}
return {status:'error',error:'invalid password'}
} catch (error) {
console.log(error);
return {status:'error',error:'timed out'}
}
}
// login
app.post('/login',async(req,res)=>{
const {email,password}=req.body;
// we made a function to verify our user login
const response = await verifyUserLogin(email,password);
if(response.status==='ok'){
// storing our JWT web token as a cookie in our browser
res.cookie('token',token,{ maxAge: 2 * 60 * 60 * 1000, httpOnly: true }); // maxAge: 2 hours
res.redirect('/');
}else{
res.json(response);
}
})
I didn't address the front end, because it only includes basic POST request forms in react, there is no need for any special methods or processing on the client-side.
hope it helps.
edit, hashing client-side:
There is a debate about this, and in some protocols, it's even required to hash passwords on the client-side, in short, because SSL already encrypts everything that moves from client to server hashing on the client-side is pretty pointless and is not widely accepted today, even # big companies. Bottom line, the added security is neglectable, and is not worth the trouble and exposing hashing logic to the client side
You don't decrypt passwords. You ask the user for the password, then you hash it and compare it to the stored hash one you saved. If they're the same, then (assuming you have a secure hashing algorithm) the unencrypted versions must be the same also.

How to prevent my secret data (e.g. from 'man in the middle attacks') while sending them in a request between Frontend and Backend?

I want to prevent my secret data (e.g. 'password') while sending them in my requests.
I'm using React on Frontend and MongoDB on Backend side.
Actually, I'm registering a user to database with his salted and hashed password like this:
userSchema.pre('save', async function (next) {
if (!this.isModified('password')) {
next()
}
const salt = await bcrypt.genSalt(10);
console.log('this.password: ', this.password);
// password coming form Frontend is not still protected here, like '1234'
this.password = await bcrypt.hash(this.password, salt);
// password is protected like '$2a$10$gxNPkFvqRIFZPyMsB.Dmf.G52yQntT3LxJQHuteCaSZCpUZ0RPkdm'
})
But I want to protect the sensitive data also on the way (for example from 'man in the middle attacks').
So, how should I implement the sending of user password as protected, or what is the best experienced way to do it?
Thanks.
Use asymmetric encryption.
Generate a public-private key pair, encrypt the password with the public key on the frontend, send the ciphertext to the backend, decrypt with the private key on the backend.

How do I set up Azure API Management to accept POST with form data fields and pass them through to a legacy API

I have a legacy API that is expecting to be called by POST of a form with 3 form fields (each containing a string). I would like to wrap this call in the Azure API Management.
I'm hoping I've missed something basic, but I assumed that the API service would pass through what it received to my legacy API.
I created:
- an api
- an operation (POST)
- a backend service
- credentials to login to backend service
I can call the service through either the test link or through postman. It definitely is hitting the backend API - but it doesn't seem to be passing my multi-part form fields with it.
Do I need to create a representation?
Any links to guidance?
I have done a similar thing for setting up a token API which communicates with AAD API and it accepts the form data. I accept the ClientId and ClienSecret in my APIM exposed API as input. e.g.
{
"ClientID":"",
"ClientSecret": ""
}
This is passed to the backend as shown below
<set-backend-service base-url="https://login.microsoftonline.com/someguid/oauth2/v2.0" />
<set-header name="Content-Type" exists-action="override">
<value>application/x-www-form-urlencoded</value>
</set-header>
<set-body>#{
JObject request = JObject.Parse(context.Request.Body.As<string>(preserveContent:true));
string clientId = (string)request?["ClientId"];
string clientSecret = (string)request?["ClientSecret"];
string scope = "api://someguid/.default";
string grantType = "client_credentials";
string response = $"client_id={clientId}&client_secret={clientSecret}&scope={scope}&grant_type={grantType}";
return response;
}</set-body>

Resources