I can't figure out why I keep getting the error: Error: Could not load the default credentials. Browse to https://cloud.google.com/docs/authentication/getting-started for more information.
firebase login from my command line returns that I am already logged in and
I have configured my-app#appspot.gserviceaccount.com to be a Secret Manager Secret Accessor in the GCP IAM admin dashboard within the same project.
Here's the code I'm using:
const { SecretManagerServiceClient } = require("#google-cloud/secret-manager");
const client = new SecretManagerServiceClient();
const gcpSecretsLoader = async (secretName: string) => {
try {
const secret = await client.accessSecretVersion({
name: `projects/my-app/secrets/${secretName}/versions/latest`,
});
const payload = secret.payload.data.toString("utf8");
console.info(`Payload: ${payload}`);
} catch (err) {
console.log(err);
}
};
gcpSecretsLoader("CLIENT_ID"); // CLIENT_ID matched a secret name within the secret manager
Related
Normally, to deploy contracts to a network, we specify the private keys in accounts section of the network config, Like below, and these accounts get used in signing the transactions.
module.exports = {
defaultNetwork: "rinkeby",
networks: {
hardhat: {
},
rinkeby: {
url: "https://eth-rinkeby.alchemyapi.io/v2/1234",
accounts: [privateKey1, privateKey2, ...]
}
},
But we need to use a custom signer that will sign the transactions instead. All transactions that are part of the deployment process needs to be signed via this custom signer.
How do I do this using Hardhat/ethers.js ?
You have to modify the deployment script to attach your custom signer to the contract factory (https://docs.ethers.io/v4/api-contract.html):
async function main() {
const HelloBar = await ethers.getContractFactory("HelloBar");
const signer = createYourCustomSigner();
// attach the signer to the factory
HelloBar = HelloBar.connect(signer);
const hellobar = await HelloBar.deploy();
await hellobar.deployed();
console.log("Address:", hellobar.address);
}
main()
.then(() => process.exit(0))
.catch((error) => {
console.error(error);
process.exit(1);
});
Then run the script with:
npx hardhat run --network localhost scripts/deploy.js
I am learning MongoDb Realm from the documentation and following the examples given. My code to login is
const loginEmailPassword = async (email, password) => {
const app = Realm.App.getApp(APP_ID)
const credentials = Realm.Credentials.emailPassword(email, password)
try {
// Authenticate the user
const user = await app.logIn(credentials)
return true
} catch (err) {
console.error('Failed to log in', err)
}
return false
}
If the credentials match a current user all is good, if the don't it doesn't throw an error but generates the following in the console:
POST https://eu-west-1.aws.stitch.mongodb.com/api/client/v2.0/app/<"my Realm App ID">/auth/providers/local-userpass/login 401
Failed to log in Error: Request failed (POST https://eu-west-1.aws.stitch.mongodb.com/api/client/v2.0/app/<"my Realm App ID">/auth/providers/local-userpass/login): invalid username/password (status 401)
Can anyone please help me understand what is going on?
We are using Ionic Vue (5.4.0 - Vue3) with Capacitor and Keycloak as the Auth Provider. We have implemented the https://www.npmjs.com/package/keycloak-ionic Package which provides the Capacitor Adapter. We have set up the required deeplinks for both platforms and they are working. The app should authenticate the user in the system browser (capacitor-native adapter), save the tokens and reuse these tokens on the next appstart. It's working on android. On iOS the first startup is working but if i restart (terminating and starting again) i only see a blank screen. It's not redirecting into the secured content or showing the keycloak login page. I found out that the Safari Browser with the keycloak login is opened in the background. If i close this browser tab and start the app it's working by redirecting me to the keycloak login page.
May the browser with the opened keycloak instance be the problem?
I also tried the same with inappbrowster (capacitor adapter). The first start is working there also. If i restart the app the custom tab is opening the redirect url page without redirecting me to the secured content or to the keycloak login page.
Code Sample:
App.addListener('appUrlOpen', function (data: any) {
const slug = data.url.split('/kc1').pop()
// We only push to the route if there is a slug present
if (slug) {
router.push({ name: 'Overview' })
}
})
// init authentication
const initKeycloak = async () => {
const cachedKeycloak = new CacheUtil('keycloak')
const cachedKeycloakAccessToken = await cachedKeycloak.get('accessToken')
const cachedKeycloakRefreshToken = await cachedKeycloak.get('refreshToken')
const initOptions = { url: process.env.VUE_APP_AUTH_URL + '/auth', realm: 'mp', clientId: 'mobile', checkLoginIframe: false, onLoad: 'login-required', token: cachedKeycloakAccessToken, refreshToken: cachedKeycloakRefreshToken }
const keycloak = KeycloakIonic(initOptions)
keycloak.init({
adapter: 'capacitor-native',
pkceMethod:'S256',
onLoad: initOptions.onLoad as any,
redirectUri: process.env.VUE_APP_REDIRECT_URI
}).then((auth: any) => {
// auth and create app
if (!auth) {
console.log(auth)
} else {
const app = createApp(VueApp)
.use(IonicVue)
.use(router)
.use(store)
router.isReady().then(() => {
app.mount('#app')
})
}
}).catch((e: Error) => {
console.log('auth failed: ', e)
})
keycloak.onAuthSuccess = () => {
console.log('authenticated!')
// save tokens to device storage
cachedKeycloak.set('accessToken', keycloak.token)
cachedKeycloak.set('refreshToken', keycloak.refreshToken)
}
}
initKeycloak()
I want to register a user of the application through a REST API. I have already enrolled the admin and a user through the enrollAdmin.js and registerUser.js function but I want to call these functions through the node SDK and register users dynamically with there username (UUID) so that it's completly anonymous.
As the username I want to create a unique UUID and save that in the world state but also save that UUID on an off-chain database together with the personal information like password and name so that I can associate the personal information with the UUID.
Right know I'm confused by all the different steps I have to do to register a new user:
In what order do I have to enroll and register the user and should they all be defined in the express API or in chaincode?
This is my first approach of creating the REST Api and till now I have only defined the layout, the connection profile and wallet.
I would appreciate if somebody could help me implement the registration process in the express REST API so that an Identity for the UUID gets saved in the world state.
Thanks in advance.
server.js
'use strict';
var express = require('express');
var bodyParser = require('body-parser');
var app = express();
// Setting for Hyperledger Fabric
const { Wallets, FileSystemWallet, Gateway } = require('fabric-network');
const path = require('path');
const fs = require('fs');
const channelName = 'mychannel';
const mspOrg1 = 'Org1MSP';
const walletPath = path.join(__dirname, '..', 'wallet');
const ccpPath = path.resolve(__dirname, '..', 'connection-org1.json');
//register
app.post('/api/register', async function (req, res) {
try{
// Create a new file system based wallet for managing identities.
const walletPath = path.join(process.cwd(), 'wallet');
const wallet = new FileSystemWallet(walletPath);
console.log(`Wallet path: ${walletPath}`);
} catch (error) {
}
});
//login
app.post('/api/login', async function (req, res) {
try{
// Create a new file system based wallet for managing identities.
const walletPath = path.join(process.cwd(), 'wallet');
const wallet = new FileSystemWallet(walletPath);
console.log(`Wallet path: ${walletPath}`);
} catch (error) {
}
});
app.listen(3000, ()=>{
console.log("***********************************");
console.log("API server listening at localhost:3000");
console.log("***********************************");
});
The process of how you want it to be is simple. In the middle, the off-chain database is used as a mapping table. I wrote only the core process logic.
/api/v1/register
validation check
Validate that the user's id is unique, that the required information value is missing, that the regular expression is correct, and that there is no wrong information.
generate random UUID
Create a random, unique uuid first. npm/uuid
const UUID = uuid.v4();
register/enroll user to fabric-ca
Perform the registration process as a user of the fabric. The information that goes into this process is UUID, and the user's information will not be stored in the blockchain.
fabricUser is a newly created class, and returns the result after fabric user registration and enroll process are performed by the Enroll method.
enrollment = await fabricUser.Enroll(UUID);
await wallet.put(enrollment);
insert to database
While saving the user information in the database, map it by storing the UUID created above.
The database was created as an example, assuming mongodb.
db.collection('User').insertOne({
'uuid': UUID,
'user_id': <input_user_id>,
...
});
/api/v1/login
The login process is as follows.
I don't know what authentication/authentication method you want to use, so I'll assume a token authentication method based on auth 2.0.
Verify the validity of the necessary information required for login and whether there is any incorrect information.
get UUID
generateAuthToken is a new function that generates JWT.
let res = await db.collection("User").findOne({'user_id': `<input_user_id>` });
return generateAuthToken(res.uuid);
/api/v1/invoke
Fabric resource request process is as follows.
Token validation and resource authorization check
get userName from token
getPayload is a function that gets the payload value located at the 1st index from the token.
const rawPayload = getPayload(token);
const jsonPayload = JSON.parse(rawPayload);
return jsonPayload
get wallet & invoke chaincode
The fabricChaincode is a function that wraps the invoke process of fabric-sdk. It is a function that executes invoke by inputting identity, chaincode information, and parameters, and returns a result.
const user = await db.collection("User").findOne({'user_id': jsonPayload.user_id });
const fabricIdentity = await wallet.get(user.uuid);
const res = fabricChaincode.invoke(fabricIdentity, `<your_chaincode_info>`, `<input_chaincode_params>`)
return res;
[EDIT]
Add it for your understanding.
fabricUser.js
/*
* Copyright IBM Corp. All Rights Reserved.
*
* SPDX-License-Identifier: Apache-2.0
*/
'use strict';
const { Wallets } = require('fabric-network');
const FabricCAServices = require('fabric-ca-client');
const fs = require('fs');
const path = require('path');
async function Enroll(user_id) {
try {
// load the network configuration
const ccpPath = path.resolve(__dirname, '..', '..', 'test-network', 'organizations', 'peerOrganizations', 'org1.example.com', 'connection-org1.json');
const ccp = JSON.parse(fs.readFileSync(ccpPath, 'utf8'));
// Create a new CA client for interacting with the CA.
const caURL = ccp.certificateAuthorities['ca.org1.example.com'].url;
const ca = new FabricCAServices(caURL);
// Create a new file system based wallet for managing identities.
const walletPath = path.join(process.cwd(), 'wallet');
const wallet = await Wallets.newFileSystemWallet(walletPath);
console.log(`Wallet path: ${walletPath}`);
// Check to see if we've already enrolled the user.
const userIdentity = await wallet.get(user_id);
if (userIdentity) {
console.log(`An identity for the user ${user_id} already exists in the wallet`);
return;
}
// Check to see if we've already enrolled the admin user.
const adminIdentity = await wallet.get('admin');
if (!adminIdentity) {
console.log('An identity for the admin user "admin" does not exist in the wallet');
console.log('Run the enrollAdmin.js application before retrying');
return;
}
// build a user object for authenticating with the CA
const provider = wallet.getProviderRegistry().getProvider(adminIdentity.type);
const adminUser = await provider.getUserContext(adminIdentity, 'admin');
// Register the user, enroll the user, and import the new identity into the wallet.
const secret = await ca.register({
affiliation: 'org1.department1',
enrollmentID: user_id,
role: 'client'
}, adminUser);
const enrollment = await ca.enroll({
enrollmentID: user_id,
enrollmentSecret: secret
});
const x509Identity = {
credentials: {
certificate: enrollment.certificate,
privateKey: enrollment.key.toBytes(),
},
mspId: 'Org1MSP',
type: 'X.509',
};
await wallet.put(user_id, x509Identity);
console.log(`Successfully registered and enrolled admin user ${user_id} and imported it into the wallet`);
} catch (error) {
console.error(`Failed to register user ${user_id}: ${error}`);
process.exit(1);
}
}
module.exports = {
Enroll
}
api.js
const uuid = require('uuid');
const fabricUser = require('./fabricUser);
const UUID = uuid.v4();
let res = await fabricUser.Enroll(UUID);
console.log(res);
Is there a way to create a service webhook to register new user with Email and Password?
I can see the way via SDK but I am trying to do the same via service webhook function?
for e.g.
exports = function(payload) {
const { Stitch, AnonymousCredential } = require('mongodb-stitch-server-sdk');
var queryArg = payload.query || '';
var body = {};
if (payload.body) {
body = EJSON.parse(payload.body.text());
}
return body.email;
};
I am not able to access mongodb-stitch-server-sdk here. Am I going in the right direction?
So you won't be able to use the SDK inside of a webhook. What you could do is add the user by hitting the Stitch Admin API.
Make an API key in Atlas. Go to the user dropdown in the top right corner > Account > Public API Access. Click on "Generate", and save the API key that gets created.
Make an HTTP service in Stitch.
In your webhook, use the Admin API to authenticate and create a new user. The code will look something like:
exports = function(payload) {
const http = context.services.get("http");
return http.post({
url: "https://stitch.mongodb.com/api/admin/v3.0/auth/providers/mongodb-cloud/login",
body: JSON.stringify({
username: "<atlas-username>",
apiKey: "<atlas-apiKey>"
})
}).then(response => EJSON.parse(response.body.text()).access_token).then(accessToken => {
return http.post({
url: "https://stitch.mongodb.com/api/admin/v3.0/groups/<groupId>/apps/<appId>/users",
headers: {
Authorization: ["Bearer " + accessToken]
},
body: JSON.stringify({
email: "<email-from-payload>",
password: "<password-from-payload>"
})
});
});
};
After Comment:
const http = context.services.get("http"); needs to be the configured ServiceName instead of http as const http = context.services.get("<SERVICE_NAME>");