首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >调用/api/auth/session给出ECONNRESET next-auth

调用/api/auth/session给出ECONNRESET next-auth
EN

Stack Overflow用户
提问于 2022-01-14 15:46:16
回答 1查看 583关注 0票数 0

总的来说,我对next-auth & next还是比较陌生的。我们有一个应用程序,我们正在转换为使用AWS认知进行身份验证。这是一个服务器端呈现的应用程序&我知道这一点,就像在pages/_app.tsx is getInitialProps()下面一样。守则如下:

代码语言:javascript
运行
复制
import React from "react";
import App from "next/app";
import Router from "next/router";
import { Provider } from "react-redux";
import withRedux from "next-redux-wrapper";
import ReduxToastr from "react-redux-toastr";
import NProgress from "nprogress";
import * as Sentry from "@sentry/node";
// import { setTokens } from "../util/tokens";
import jwtDecode from "jwt-decode";
import { SessionProvider, getSession } from "next-auth/react";

import createStore from "../redux/store";
import { setSession } from "../redux/session";
import "semantic-ui-css/semantic.min.css";
import "react-redux-toastr/lib/css/react-redux-toastr.min.css";
import "../styles/nprogress.css";
import "../styles/overrides.scss";
import "../styles/util.css";
import axios from "axios";
import { IdToken, CognitoTokens } from "../interfaces";

Router.events.on("routeChangeStart", () => {
    NProgress.start();
});
Router.events.on("routeChangeComplete", () => NProgress.done());
Router.events.on("routeChangeError", () => NProgress.done());

NProgress.configure({ showSpinner: false });

type tProps = {
    passport?: {};
};

class MyApp extends App {
    static async getInitialProps({ Component, ctx }: any) {
        debugger;
        let pageProps: tProps = {};
        const session = await getSession({
            req: ctx.req,
        }); // this calls '/api/auth/session'
        // let tokens: AuthTokens = {};

        if (ctx.isServer && ctx.query?.code) {
            const {
                AUTH_DOMAIN,
                COGNITO_CLIENT_ID,
                COGNITO_CLIENT_SECRET,
                BASE_URL,
            } = process.env;
            const { data }: { data: CognitoTokens } = await axios.post(
                `https://${AUTH_DOMAIN}/oauth2/token?client_id=${COGNITO_CLIENT_ID}&client_secret=${COGNITO_CLIENT_SECRET}&grant_type=authorization_code&redirect_uri=${BASE_URL}&code=${ctx.query.code}`,
            );
        }

        return { pageProps };
    }

    render() {
        debugger
        const { Component, pageProps, store }: any = this.props;

        return (
            <SessionProvider session={pageProps.session}>
                <Provider store={store}>
                    <Component {...pageProps} />
                    <ReduxToastr
                        preventDuplicates
                        position="bottom-right"
                        transitionIn="fadeIn"
                        transitionOut="fadeOut"
                        timeOut={5000}
                        progressBar
                    />
                </Provider>
            </SessionProvider>
        );
    }
}

export default withRedux(createStore)(MyApp);

pages/api/auth/[...nextauth].ts

代码语言:javascript
运行
复制
import NextAuth from "next-auth";
import CognitoProvider from "next-auth/providers/cognito";

export default NextAuth({
    providers: [
        CognitoProvider({
            clientId: process.env.COGNITO_CLIENT_ID,
            clientSecret: process.env.COGNITO_CLIENT_SECRET,
            issuer: process.env.COGNITO_ISSUER,
        }),
    ],
    debug: process.env.NODE_ENV === "development" ? true : false,
});

有为API定义的身份验证中间件。主要原因是我们在认知中为用户定义了一个自定义的permissions属性,它定义了他们在特定环境中可以执行的CRUD操作。

server/index.ts

代码语言:javascript
运行
复制
import express from "express";
import next from "next";
import bodyParser from "body-parser";
import session from "express-session";
import connectMongodbSession from "connect-mongodb-session";

// Config
import { /* auth0Strategy, */ getSessionConfig } from "./config";

const port = parseInt(process.env.PORT || "3000", 10);
const dev = process.env.NODE_ENV !== "production";

// API
import authAPI from "./api/auth";
import accountsAPI from "./api/accounts";
import usersAPI from "./api/users";
import jobsAPI from "./api/jobs";
import awsAPI from "./api/aws";
import completedJobsAPI from "./api/completedJobs";

// middleware
import { restrictAccess, checkPermissions } from "./middleware/auth";

// Server
const app = next({ dev });
const handle = app.getRequestHandler();

app.prepare().then(() => {
    const server = express();
    const MongoDBStore = connectMongodbSession(session);
    const store = new MongoDBStore({
        uri: process.env.MONGO_PROD_URL,
        collection: "godfatherSessions",
    });

    server.use(bodyParser.json());
    server.use(session(getSessionConfig(store)));

    server.get("/healthcheck", async (req: any, res, next) => {
        const { db } = req.session.req.sessionStore;

        try {
            await db.command({
                ping: 1,
            });

            res.status(200).end();
        } catch (err) {
            next(err);
        }
    });

    // Middleware
    server.use(checkPermissions);

    // API
    server.use(authAPI);
    server.use(accountsAPI, restrictAccess);
    server.use(usersAPI, restrictAccess);
    server.use(jobsAPI, restrictAccess);
    server.use(awsAPI, restrictAccess);
    server.use(completedJobsAPI, restrictAccess);

    // Protected Page Routes
    server.get("/accounts", restrictAccess, (req: any, res) =>
        app.render(req, res, "/accounts", req.query),
    );
    server.get("/users", restrictAccess, (req: any, res) =>
        app.render(req, res, "/users", req.query),
    );
    server.get("/jobs", restrictAccess, (req: any, res) =>
        app.render(req, res, "/jobs", req.query),
    );
    server.get("/completedJobs", restrictAccess, (req: any, res) => {
        app.render(req, res, "/completedJobs", req.query);
    });

    server.get("/debug-sentry", function mainHandler() {
        throw new Error("My first Sentry error!");
    });

    // Fallback Routes
    server.all("*", handle as any);

    // The error handler must be before any other error middleware and after all controllers
    // server.use(Sentry.Handlers.errorHandler());

    server.listen(port, (err?: Error) => {
        if (err) throw err;
        console.log(
            `> Server listening at http://localhost:${port} as ${
                dev ? "development" : process.env.NODE_ENV
            }`,
        );
    });
});

server/middleware/auth.ts

代码语言:javascript
运行
复制
/* eslint-disable @typescript-eslint/camelcase */
import "cross-fetch/polyfill";
import { Request, Response, NextFunction } from "express";
import { ForbiddenError } from "../../util/errors";
import { Environments } from "../../interfaces";
import jwt_decode from "jwt-decode";
import { CognitoUser, CognitoUserPool } from "amazon-cognito-identity-js";
import { getSession } from "next-auth/react";

export async function checkPermissions(
    req: CustomRequest,
    res: Response,
    next: NextFunction,
) {
    const { path, method } = req;
    const { authorization, env } = req.headers;
    const session = await getSession({ req });

    debugger;

    if (
        !req.url.includes("/api/") ||
        ["/api/auth/callback/cognito", "/api/auth/session"].includes(req.path)
    ) {
        return next();
    }

    if (req.headers.env === "development") {
        return next();
    }
    console.log(session);

    if (!authorization) {
        return res.status(401).redirect("/login");
    }
    const decoded: any = jwt_decode(authorization);
    const invalidAuth = isInvalidAuth(decoded, path);

    if (!invalidAuth) {
        const userPool = new CognitoUserPool({
            UserPoolId: process.env.COGNITO_USER_POOL_ID,
            ClientId: process.env.COGNITO_CLIENT_ID,
        });
        const username = decoded.username || decoded["cognito:username"];
        const cognitoUser = new CognitoUser({
            Username: username,
            Pool: userPool,
        });
        const userAttributes: any = await getUserAttributes(cognitoUser);
        const permissions = userAttributes.permissions
            .split(",")
            .map(perm => `"${perm}"`);
        const hasPermission = getHasPermission(
            method,
            permissions,
            env as Environments,
        );

        if (!hasPermission) {
            return res
                .status(403)
                .send(
                    new ForbiddenError(
                        "You do not have permission to perform this action.",
                    ).toErrorObject(),
                );
        }

        return next();
    }
    return next(invalidAuth);
}

认知应用客户端中定义的回调URL为"http://localhost:3000/api/auth/callback/cognito“(为了开发目的--正如https://next-auth.js.org/providers/cognito中突出显示的那样)。

当通过认知托管UI运行应用程序和登录时,第一个断点命中是L5上的checkPermissions调试器。此时session为空&路径为/api/auth/session

当我跨过这个断点到return next()时,问题就出现了,在那里我得到了下图所示的错误。因此,这些都是ECONNRESET错误&如果我允许它自由运行,这些错误会反复发生,每次都会导致EMFILE错误,直到应用程序崩溃为止。没有其他断点被击中。

版本:

  • next:9.3.5版
  • next-auth:v4.1.0

尽管默认情况下,next-auth将使用localhost:3000,但当我没有在.env中定义URL时,仍然会得到一个ENOTFOUND错误,因此我将其设置为:

代码语言:javascript
运行
复制
NEXTAUTH_URL=http://127.0.0.1:3000

在阅读了所有的文档&示例&关于如何做到这一点的几个教程(没有人做过关于v4的教程--只是v3)之后,我仍然感到困惑。

EN

回答 1

Stack Overflow用户

发布于 2022-08-24 14:36:47

对于我来说,帮助删除.next/并将这些行添加到.env

代码语言:javascript
运行
复制
NODE_TLS_REJECT_UNAUTHORIZED="0"
NEXTAUTH_URL="http://127.0.0.1:3000"
NEXTAUTH_URL_INTERNAL="http://127.0.0.1:3000"

好像很好用。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/70713143

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档