Existing React/Node project - adding AWS authentication - node.js

Premise: I'm a newbie, so I'm aware that some of my questions or issues might sound obvious to the more experienced.
My situation is: I have an existing React frontend and Node backend. I need to add authentication to my app, so that I can provide login (and future registration) for my colleagues. We use AWS resources and there is an existing user pool in Cognito.
How do I go about doing this?
I've done some research and everything points me to AWS Amplify, but I've found the existing resources very confusing. Amplify seems to create a new, separate backend when I run amplify init, but I need to stick with the existing one.
Basically, all I need is the authentication piece, I don't want to use anything else from Amplify itself.
Apologies in advance if I might have missed something obvious. Thanks.

I have solved this exact situation with the Amplify library.
You can utilize the Authenticator component from #aws-amplify/ui-react where the docs are here.
In the most simple form, it would look like this:
import { Authenticator } from "#aws-amplify/ui-react";
import Amplify from "aws-amplify";
Amplify.configure(awsExports);
const App = () => {
return (
<Authenticator>
{/* Pass app entry as children */}
{({ signOut, user }) => <Home signOut={signOut} user={user} />}
</Authenticator>
);
};
//Object holding AWS auth config
//This is a seperate file which is imported
export const awsExports = {
Auth: {
mandatorySignIn: true,
region: "YOUR REGION",
userPoolId: "COGNITO_POOL_ID",
userPoolWebClientId: "COGNITO_CLIENT_ID",
},
};
So in my app, I only use this Authenticator component which does all of the interactions with the cognito pool and nothing else from Amplify. There's a number of different props you can pass into the Authenticator component so certainly review the docs.

Related

How to make a private call when using SSR Nuxt?

I am writing a headless solution for a WordPress website and noticed that for one particular endpoint, I need to authenticate to pull some data that will be used publicly. But, I'm concerned that where I'm using it will expose it to the web.
In my store/index.js I use the nuxtServerInit action method to execute some actions and I pass them some objects they need to fulfill their tasks:
async nuxtServerInit ({ dispatch }, { $axios, app }) {
await dispatch('initialize', { $axios, app })
},
$axios is passed because it will be used to query the API, and app is passed to help build the options to authenticate the request.
Is this a security vulnerability in Nuxt SSR? I think it is. If so, where are the only valid areas you can use secrets? asyncData ()?
If you're using SSR, you can use the privateRuntimeConfig runtime object and pass your secret in the nuxt.config.js file
export default {
privateRuntimeConfig: {
apiSecret: process.env.API_SECRET
}
}
If you read the documentation of nuxtServerInit, you can see that
Vuex action that is called only on server-side to pre-populate the store
Since this method is server-side only, you can use apiSecret (in my example) and it should be totally fine security-wise.
PS: Keep in mind that everything beyond what is generated on the server (hence, with NodeJS or nuxtServerInit) is "public". So your VueJS's client code lifecycle hooks are public: mounted(), fetch(), asyncData() because they will be visible on your browser's devtools.
Also, should your endpoint be that critical? If so, nuxtServerInit is the good way to go. If you need to fetch some more data in a "private way", you'll need to proxy it through some backend to hide the sensitive info and retrieve only the useful public data.

Firebase not adding data to Realtime database in React

I was following along this tutorial to connect Firebase using react hooks. I followed everything but I am having a problem interacting with the real-time database on my project. For example, when I tried to insert data into the database, it doesn't make any changes it just shows null; I tried to see if it was other problems, tried it with different accounts, creating new projects, but nothing seems to work.
My App.js looks like this:
import React from "react"
import "./App.css"
import firebase from "./firebase"
function App() {
firebase
.firestore()
.collection("notes")
.add({
title: "Working",
body: "This is to check the Integration is working",
});
return (
<div className="App">
<h2>Note Taking App</h2>
<p>using React Hooks and Firebase</p>
<h3>Notes : </h3>
</div>
)
}
export default App
I checked the rules for the realtime database on firebase, and it shows:
{
"rules": {
".read": "now < 1610427600000", // 2021-1-12
".write": "now < 1610427600000", // 2021-1-12
}
}
My app runs properly, but on the console, since I was logging the XHRHttpRequests, it shows something is failing on the GET request.
It is a newly created project and I only changed the App.js and added firebase.js that looks exactly like the one in the guide.
The security rules you show are for the Firebase Realtime Database, but the code you have is accessing Cloud Firestore. While both databases are part of Firebase, they are completely separate and have different APIs.
To write to the Realtime Database would look something like this:
firebase
.database()
.ref("notes")
.push({
title: "Working",
body: "This is to check the Integration is working",
});

How to delete user from Auth0 on Next.js?

I can login and logout users on Next.js after reading these resources amongst others:
The Ultimate Guide to Next.js Authentication with Auth0
#auth0/nextjs-auth0 library
API Call Example
SPA + API: Node.js Implementation for the API
But nowhere could I find out if I can delete users using the auth0/nextjs-auth0 library.
I also looked into the module's handlers here.
Am I right to think there is no way to delete a user using the #auth0/nextjs-auth0 library?
If yes, what is the most preferred way to delete a user? I'd like to allow users to click a button in the browser to delete themselves from Auth0.
At this point, I'm thinking of using node-auth0 library to do it following this solution:
management.users.delete({ id: USER_ID }, function (err) {
if (err) {
// Handle error.
}
// User deleted.
});
But it requires a node back end, which I sort of wanted to avoid. Even so, is this the best solution or are there better ones? The Auth0 ecosystem is quite sprawling.
Edit 27 Oct 2020: Will try using node-auth0 library in "serverless" function in Next.js to allow user to delete their account over the weekend. Secrets are hidden with Next's runtime configuration. If this is not the best way to do it, please let me know. Thanks.
I believe you mean logging out a user by "deleting a user". Because If you want to delete a user from the database, you have to have node server which handles the db connection. If you want to log out the user, in "pages/api/v1" create a logout.js. in next.js, serverless functions or api functions are written in "pages/api".
import auth0 from "/utils/auth0";
// auth0 file is where you set the configuration for the auth0.
export default async function logout(req,res) {
try {
await auth0.handleLogout(req, res);
} catch (error) {
console.error(error);
res.status(error.status || 400).end(error.message);
}
}

How to retrieve firebase api key from my nodejs backend?

I'm building a React app that will use Firebase Auth. I was storing my API key inside the .env file but I've read in the React docs that it is not safe, so I have created a custom and private route on my NodeJS server that is a simple GET request which sends me the data that I need(key, projectid, etc). And I think this is the safest way to do it, right?
Now I'm trying to get this data from my backend and I'm able to do it using console.log for example but I'm unable to integrate it with Firebase function. It keeps saying that it is undefined.
This is what I have tried so far:
import * as firebase from 'firebase/app';
import 'firebase/auth';
const API_URL = process.env.REACT_APP_API_URL;
let res;
export async function getFirebaseKeys() {
const response = await fetch(`${API_URL}/api/get`);
res = response.json();
}
getFirebaseKeys();
//I have also tried to use firebase.OnLog but no success.
//I have also tried to wrap firebase.initializeApp and my fetch in a function but it breaks
const app = firebase.initializeApp({
apiKey: res.apiKey,
authDomain: res.domain,
databaseURL: res.database,
projectId: res.projectId,
storageBucket: res.storageBucket,
messagingSenderId: res.senderId,
});
export default app;
This is my first project with Firebase and React so I'm sorry if i have missed something obvious.
What you're trying to do now is not really any safer than putting the Firebase config in the source (where it's intended to go). Hiding it behind a GET just makes people go through another step to get a hold of it if they want it.
There's nothing unsafe about putting the Firebase config in the hands of the public, as long as you are also signing in users with Firebase Authentication, and using security rules to determine who can access what data in the project.
Just do whatever is most convenient - security is not the issue here.
See also: Is it safe to expose Firebase apiKey to the public?

How to use keycloak with NestJS properly

I need to use keycloak with NestJS and GrapphQL (type-graphql). There are some guides for using it with pure Express, but I'd prefer using with NestJS auth pattern. Can someboby give any suggestion?
This is a kind of an old question, but since I just went through implementing it, I would like to point to a great tutorial Protecting your NestJS API with Keycloak. It does not use passport, but is simply call the OpenId Connect UserInfo endpoint on Keycloak: https://openid.net/specs/openid-connect-core-1_0.html#UserInfo.
I find it very easy to add to an application, very easy to follow, and generally very well usable (comparing to an unnamed SaaS application I was using before).
async authenticate(accessToken: string): Promise<User> {
const url = `${this.baseURL}/realms/${this.realm}/protocol/openid-connect/userinfo`;
try {
const response = await this.httpService.get<KeycloakUserInfoResponse>(url, {
headers: {
authorization: `Bearer ${accessToken}`,
},
}).toPromise();
return {
id: response.data.sub,
username: response.data.preferred_username,
};
} catch (e) {
throw new AuthenticationError(e.message);
}
}
I never tried it myself, but i guess i will soon. What i would do:
Check out the Authentication Technique again, and especially learn how to implement the different strategies of passport in nest: https://docs.nestjs.com/techniques/authentication
Take a look at the npm-package and it's documentation. The guys from passport have dedicated a whole section to OpenID: http://www.passportjs.org/docs/openid/
Implement the OpenID-Strategy in nestjs - here i would just follow the docs, since they are pretty good
I hope this will maybe help you out. At the end of the day, you will have an OpenID implementation of passport with KeyCloak and can use a guard to protect your Routes / Schemes.

Resources