Invoking a middleware functions on AWS lambda ( without express ) - node.js

Basically i want to invoke passport-cognito login authentication in a lambda , but i cant seem to invoke this without using express , ive tried invoking the function with req,res variables but i still cant seem to get the authentication working
module.exports = (user, callback) => {
let req = {
body: user
};
let res = {
end: (...params) => {
console.log(params);
}
}
passport.authenticate('cognito', {
successRedirect: callback(null,{"message": "success"}),
failureRedirect: callback(null,{"message": "failed"})
})(req, res);
};

I'd recommend calling API Gateway to invoke your lambda function. You can use cognito pools for authentication as AWS outline in this blog https://aws.amazon.com/blogs/mobile/integrating-amazon-cognito-user-pools-with-api-gateway/

Related

fastifyGuard not working (role based authentication)

I have a fastify project, where I use fastify-jwt to create tokens for the users. Now I want to have a role based authentication system. I found the fastifyGuard plugin but I register it correctly, nevertheless it is not working in the routes file.
What I currently have
async function routes(fastify, options, next) {
const Collection = require("$/App/Controllers/Collection/Controller");
fastify.get(
"/test/admin",
{
preValidation: [fastify.authenticate],
},
Collection.testFunction
);
}
I provide a bearer token and it works perfectly.
Than I add the fastifyGuard preHandler:
async function routes(fastify, options, next) {
const Collection = require("$/App/Controllers/Collection/Controller");
fastify.get(
"/test/admin",
{
preValidation: [fastify.authenticate],
preHandler: [fastify.guard.role('admin')]
},
Collection.testFunction
);
}
and the app crashes. So I tried to debug it, and in the routes file fastify.guard is undefined.
Thanks for any kind of help.

Error while trying to login with through Steam from node.js

I'm trying to login through steam from my webapp but I'm having an hard time.
This is the code in my backend (I'm using Firebase cloud functions) that let me authenticate my user.
const steam = new SteamAuth({
realm: "https://storm.co.gg", // Site name displayed to users on logon
returnUrl: "http://localhost:5001/stormtestfordota/europe-west1/api/auth/steam/authenticate", // Your return route
apiKey: apiKey // Steam API key
});
let loggedUser = "";
const redirectSteamAuth = async (req, res) => {
loggedUser = req.user.username;
const redirectUrl = await steam.getRedirectUrl();
return res.json(redirectUrl);
}
So this is the first endpoint that the user calls when trying to login to Steam. And it works, so the steamcommunity.com opens without problem.
But when I click login in steamcommunity page I'm prompted with this error
So over the name of my account you can see "ERRORE" that stands for "ERROR"
This is the endpoint that should be called after authentication:
const loginWithSteam = async (req, res) => {
try {
const user = await steam.authenticate(req);
db.collection("users").doc(loggedUser).update({
steamId: user.steamid
})
activeDota2(loggedUser, user.steamid);
return res.redirect("https://storm.co.gg/dashboard/home");
} catch (error) {
console.error(error);
return res.status(401).json(error)
}
}
These are the two endpoints:
app.post("/auth/steam", (req, res, next) => validateFirebaseIdToken(req, res, next), redirectSteamAuth);
app.get("/auth/steam/authenticate", loginWithSteam);
I solved this issue. The problem was in the urls of the steam object AND there was a problem with CORS options, I didn't add the DNS of steamcommunity in origins accepted by CORS.

How to add custom middleware to express-openapi-validator using Swagger 3

I've got a Node app using express-openapi-validator that takes a an api spec file (which is a .yml file), with request and response validation. The express-openapi-validator package routes the request to a handler file (defined in the spec). This is what one of the handlers might look like:
function getUsers(req, res) {
const { 'x-user-id': userId } = req.headers
res.status(200).json(`Your userId is ${userId}`)
}
I've got an API key feature, where users can get a new API key, and the other endpoints that need the caller to have the API key in the request headers to validate the request.
I know it should be possible to use middleware to validate the request, but I can't figure out how to use custom middleware with the express-openapi-validator package on select endpoints.
For eg:
GET /apikey = does not require api key
GET /resource = requires api key
How do I configure this?
Here's what the openapi validator code in my app.js looks like:
new OpenApiValidator({
apiSpec,
validateResponses: true,
operationHandlers: path.join(__dirname, './handlers'),
})
.install(app)
.then(() => {
app.use((err, _, res) => {
res.status(err.status || 500).json({
message: err.message,
errors: err.errors,
});
});
});
I actually ended up finding a solution for this myself.
First of all, I'm using version 4.10.5 of express-openapi-validator, so the code above is slightly different.
Here's what it looks like now:
// index.js
app.use(
OpenApiValidator.middleware({
apiSpec,
validateResponses: true,
operationHandlers: path.join(__dirname, './handlers'),
validateSecurity: {
handlers: {
verifyApiKey(req, scopes) {
return middleware.verifyApiKey(req)
},
bearerAuth(req, scopes) {
return middleware.verifyToken(req)
}
}
},
}),
);
app.use((err, req, res, next) => {
res.status(err.status || 500).json({
message: err.message,
errors: err.errors,
});
The way I ended up using middleware in my routes is below:
I've added a securitySchemes section in my swagger.yml file, like so:
components:
securitySchemes:
verifyApiKey:
type: apiKey
in: header
name: x-api-key
bearerAuth:
type: http
scheme: bearer
bearerFormat: JWT
There's a bit more information about it here: https://swagger.io/docs/specification/authentication/
On each route that needs the middleware, I'm adding a security section, like so:
/team:
post:
security:
- bearerAuth: []
description: Create a new team
operationId: createTeam
x-eov-operation-id: createTeam
x-eov-operation-handler: team
As you can see in my code above (in the index.js file), I've got a validateSecurity key, with a handlers key that then has the correlating keys that are in my swagger.yml (verifyApiKey and bearerAuth). These functions get the request and scope to check if they're valid. These functions return a boolean value, so true means that the middleware lets the request through, and false means a 403 response will be returned.
validateSecurity: {
handlers: {
verifyApiKey(req, scopes) {
return middleware.verifyApiKey(req)
},
bearerAuth(req, scopes) {
return middleware.verifyToken(req)
}
}
},
Please respond if I've got anything above wrong, or if the explanation can be clearer. If you have questions, please post them below.
You can simply pass array of handlers instead of just 1 function, like in express.
So in you code, the getUsers function that probably is what the x-eov-operation-id refers to, would be an array of 2 functions:
const getUsers = [
apiKeyMiddleware,
(req, res) => {
const { 'x-user-id': userId } = req.headers
res.status(200).json(`Your userId is ${userId}`)
}
];
I was in a similar situation as you, using OpenAPI/Swagger packages like that limited my ability to add specific middleware per endpoint, so my solution was I created an npm module called #zishone/chaindler.
You can use it like this:
const { Chain } = require('#zishone/chaindler');
function getUsers(req, res) {
const { 'x-user-id': userId } = req.headers
res.status(200).json(`Your userId is ${userId}`)
}
function postUsers(req, res) {
// ...
}
function mw1(req, res, next) {
next()
}
function mw2(req, res, next) {
next()
}
module.exports = {
getUsers: new Chain(mw1, mw2).handle(getUsers),
postUsers: new Chain(mw1).handle(postUsers)
}
Basically it just chains the middlewares then calls them one by one then call the handler/controller last.

JWT authentication in Node.js + express-graphql + passport

I'm writing a fullstack application using MERN and I need to provide authentication using JWT-tokens. My code looks like:
router.use(GraphQLHTTP(
(req: Request, res: Response): Promise<any> => {
return new Promise((resolve, reject) => {
const next = (user: IUser, info = {}) => {
/**
* GraphQL configuration goes here
*/
resolve({
schema,
graphiql: config.get("isDev"), // <- only enable GraphiQL in production
pretty: config.get("isDev"),
context: {
user: user || null,
},
});
};
/**
* Try to authenticate using passport,
* but never block the call from here.
*/
passport.authenticate(['access'], { session: false }, (err, loginOptions) => {
next(loginOptions);
})(req, res, next);
})
}));
I want to provide a new generation of tokens and through GraphQL. In doing so, I need to check whether the user has used the correct method of authentication. For example, to get a new access token, you need a refresh token, you need to log in using the password and e-mail for the refresh token. But using a passport implies that after authentication I will simply have a user.
How should I proceed?

how to debug passport

I can't for the life of me seem to figure out how to debug a passport strategy. Am I just conceptually doing something horribly wrong? I've been banging my head at this for about 10 hours now, and haven't gotten a single bit closer.
This is my first time using passport. In this particular scenario, I'm using passport-jwt. I know that the object keys aren't right, but I'm just trying to trace the path through the server using console.log() so I understand how things work. I'm not even reaching the passport.use( new JwtStrategy(..)).
I've left out unnecessary code. The connection to my mongodb is fine and my mongoose schema's are fine.
I'm testing using a test route server.get('/fakelogin', ...) that does a request-promise POST to /api/login. I've also tried using a curl -X POST and modifying the post route to url query parameter. I just constantly get an "Unauthorized" error without the passport strategy code console.log ever firing.
Server
var server = express();
server.use(passport.initialize());
let opts = {
jwtFromRequest: ExtractJwt.fromBodyField('token'),
secretOrKey: config.apiKey,
algorithms: [ 'HS256', 'HS384' ],
ignoreExpiration: true
};
passport.use(new JwtStrategy(opts, function( jwt_payload, done ) {
// mongoose users query against JWT content
return done(null, true); // EDIT: test to finish flow
}));
server.use('/api', routes);
server.listen(8000);
Routes
let routes = express.Router();
routes.post('/securedroute', passport.authenticate('jwt', { session: false }),
( req, res ) => {
res.send('success');
}
);
routes.get('/testsecure', ( req, res ) => { // EDIT: mock request with JWT
let options = {
method: 'POST',
uri: 'http://localhost:8000/api/authentication/securedroute',
body: {
token: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwiZW1haWwiOiJhQGEuY29tIiwiYWRtaW4iOnRydWV9.afjyUmC81heavGBk7l9g7gAF5E6_eZeYSeE7FNmksp8'
},
json: true
};
rp(options)
.then( ( info ) => res.json({ info }) )
.catch( ( err ) => res.json({ err }) );
});
export default routes;
Made a couple edits to the code above to finish the flow.
Totally understand that this is super n00b, but hopefully it'll help a beginner trying to understand auth.
So completely missed the fact that you need to send a JWT in the request. The JWT used in the request needs to use the same secret as what you defined in your passport-jwt strategy opts.secretOrKey. If they don't match, you will get an unauthorized and never reach the passport.use strategy block.
Generated a HMAC
http://www.freeformatter.com/hmac-generator.html
Created a test JWT
https://jwt.io/#debugger
Greate guide, i eventually found
http://jonathanmh.com/express-passport-json-web-token-jwt-authentication-beginners/

Resources