pharindoko / json-serverless

Transform a JSON file into a serverless REST API in AWS cloud
MIT License
205 stars 27 forks source link

How to implement auth example? #427

Closed troymclure1 closed 4 years ago

troymclure1 commented 4 years ago

Hi There,

I really like the project. Just wondering how we implement authentication (username, password) to the example? Do you have any sample code you can post?

jedfoster commented 4 years ago

I have the same question. Loving the project; I was able to deploy the example database with very little difficulty. Excited to hack on this further.

pharindoko commented 4 years ago

Hi,

I`m already working on an example with cognito and vue on that. But I need some additional time to prepare and share it.

jedfoster commented 4 years ago

FWIW, I got a very basic auth implementation working using the example code from json-server. I added the following to src/handler.ts:

server.use((req, res, next) => {
 if (isAuthorized(req)) { // add your authorization logic here
   next() // continue to JSON Server router
 } else {
   res.sendStatus(401)
 }
});

let core: CoreApp | undefined;
pharindoko commented 4 years ago

I do it the same way. You can add express middleware at that place and restrict access to httpverbs like POST.

pharindoko commented 4 years ago

This is how I do use it currently using AWS Cognito and cognito-express npm package doing the auth in the middleware

import { APIGatewayProxyHandler } from "aws-lambda";
import express from "express";
import serverlessHttp from "serverless-http";
const CognitoExpress = require("cognito-express");
import {
  AppConfig,
  Swagger,
  SwaggerConfig,
  S3StorageAdapter,
  CloudEnvironment,
  CoreApp,
  FileStorageAdapter,
} from "json-serverless-lib";

import fs from "fs";

const server = express();

console.log("process.env.region: " + process.env.region);
console.log(
  "process.env.cognitoUserPoolId: " +
    JSON.stringify(process.env.COGNITO_USER_POOL_ID)
);

const cognitoExpress = new CognitoExpress({
  region: process.env.region,
  cognitoUserPoolId: process.env.COGNITO_USER_POOL_ID,
  tokenUse: "id",
  tokenExpiration: 3600000,
});

server.use((req: any, res: any, next: any) => {
  res.setHeader(
    "Access-Control-Allow-Methods",
    "GET, POST, PUT, DELETE, OPTIONS"
  );
  res.header("Access-Control-Allow-Origin", "*");
  res.header(
    "Access-Control-Allow-Headers",
    "Origin, X-Requested-With, Content-Type, Accept, Authorization"
  );
  res.header("Access-Control-Allow-Credentials", "true");
  res.header("Cache-Control", "private, no-cache, no-store, must-revalidate");

  console.log(req.url);
  if (
    req.method !== "OPTIONS" &&
    req.method !== "GET" &&
    req.url.startsWith("/api")
  ) {
    let accessTokenFromClient = req.headers["authorization"];
    if (!accessTokenFromClient)
      return res.status(401).send("Access Token missing from header");
    cognitoExpress.validate(accessTokenFromClient, function (
      err: any,
      response: any
    ) {
      if (err) return res.status(401).send(err);
      else next();
    });
  } else {
    next();
  }
});

const sls = serverlessHttp(server);
const defaultConfig = new AppConfig();
const config = JSON.parse(fs.readFileSync("./config/appconfig.json", "UTF-8"));
const appConfig = AppConfig.merge(defaultConfig, config);
const environment = new CloudEnvironment();
const swagger = new Swagger(
  server,
  new SwaggerConfig(appConfig.readOnly, appConfig.enableApiKeyAuth),
  environment.basePath,
  "./package.json"
);
let core: CoreApp | undefined;
console.log("environment: " + process.env.NODE_ENV);
if (process.env.IS_OFFLINE) {
  core = new CoreApp(
    appConfig,
    server,
    new FileStorageAdapter("db.json"),
    swagger,
    environment
  );
} else {
  core = new CoreApp(
    appConfig,
    server,
    new S3StorageAdapter(environment.s3Bucket, environment.s3File),
    swagger,
    environment
  );
}

const init = async () => {
  return new Promise(async (resolve, reject) => {
    await core!.setup();
    resolve();
  });
};
const initPromise = init();

export const handler: APIGatewayProxyHandler = async (event, context) => {
  await initPromise;
  const result = await sls(event, context);
  return result;
};
pharindoko commented 4 years ago

Hey guys,

I added an example to show how to use middleware and authentication https://github.com/pharindoko/jsonsls-vue-cognito-demo

br,

Flo