question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Incorrect Error Being Returned

See original GitHub issue

Hey guys, I’m currently trying to integrate graphql-shield into my project which is using type-graphql, inversifyJS and prisma and I’m running into an issue where it seems that no matter what I throw, I get a "Not Authorised!" returned and I’m really not sure why. Relevant Code:

//permissions.ts
const authService = serviceContainer.get(AuthService);

const rules = {
  isAuthenticatedUser: rule()( async (parent, args, context) => {
    const userId = await authService.getUserId(context).catch(err => err);
    return Boolean(userId);
  }),
};

export const permissions = shield({
  Query: {
    me: rules.isAuthenticatedUser
  }
});
// auth-resolver.ts
@Mutation(() => UserResponse)
    async registerUser(@Arg("data") data: RegisterInput): Promise<UserResponse> {
        const { email, password, firstname, lastname } = data;
        const user = await this.authService.register(email, password, firstname, lastname);
        return user;
    }
//auth-service.ts
async register(email: string, password: string, firstname: string, lastname: string): Promise<UserResponse> {
        return new Promise(async (resolve, reject) => {
            const hashedPassword = await hash(password, 10);
            const user = await this.prisma.user.create({
                data: {
                    email: email,
                    password: hashedPassword,
                    firstname: firstname,
                    lastname: lastname,
                },
            // reject error if user can't be created
            }).catch(err => reject(err));
            if (user) {
                resolve(user);
            }
            reject(new Error("Invalid"));
        });
    }
//server.ts
const schema = await buildSchema({
        resolvers: [ AuthResolver, UserResolver ],
        container: serviceContainer,
        emitSchemaFile: path.resolve(__dirname, "./generated-schema.graphql"),
        validate: false,
        dateScalarMode: "timestamp",
    });
    
    const server = new ApolloServer({
        schema: applyMiddleware(schema, permissions),
        playground: true,
        context: ({ req, res }): Context => ({ 
            req,
            res,
            prisma: serviceContainer.get(PrismaClient),
            container: serviceContainer
         }),
    });

In the above code, I’m only protecting one endpoint me(). When I called the mutation registerUser() with an email that’s already been registered (there’s a unique constraint on email) it’s responding with Not Authorized, instead of the error that should be resolved from Prisma, any ideas on why this might be happening when registerUser() isn’t behind the shield? (Including a link to sample repository incase that helps: https://github.com/tnolan8/typegraphql-api)

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Comments:5

github_iconTop GitHub Comments

2reactions
maticzavcommented, Jun 3, 2020

Hey @darrylyoung 👋 ,

Are docs unclear about handling errors? What I’d advise is that you return the error inside your resolver - that’s a mechanism shield uses to distinguish server errors from “predictable” patterns so that you don’t leak internal structure of the app.

2reactions
rtnolancommented, May 9, 2020

Believe I’ve found my issue. When inspecting the output of generateMiddlewareFromSchemaAndRuleTree() I can see that it’s applying Middleware to all of my types:

MIDDLEWARE:  {
  Query: { me: [AsyncFunction: middleware] },
  UserResponse: {
    email: { fragments: [], resolve: [AsyncFunction: middleware] },
    firstname: { fragments: [], resolve: [AsyncFunction: middleware] },
    lastname: { fragments: [], resolve: [AsyncFunction: middleware] },
    createdAt: { fragments: [], resolve: [AsyncFunction: middleware] }
  },
  Mutation: {
    registerUser: { fragments: [], resolve: [AsyncFunction: middleware] },
    loginUser: { fragments: [], resolve: [AsyncFunction: middleware] }
  },
  AuthPayload: {
    token: { fragments: [], resolve: [AsyncFunction: middleware] },
    user: { fragments: [], resolve: [AsyncFunction: middleware] }
  }
}

When the middleware is executing for registerUser() it gets to: return await resolve(parent, args, ctx, info) Ln 70 in generator.ts. The parent fails to resolve because of the failure on the unique constraint and is then caught in the catch() block. Looks like all I needed was to set { allowExternalErrors: true } when creating the shield, seems to do the trick.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Return incorrect error response when handle exception
Why not correct error response? I got error: org.springframework.http.converter.HttpMessageNotWritableException: No converter found for return ...
Read more >
Incorrect error odbc.ini file not found being returned when ...
ini file not found being returned when driver manager message file odbc.m file can't be found or opened with Connect/Connect64 for ODBC ...
Read more >
Query works correctly then returns incorrect results but no error!
A query that should return approximately 70 rows will return correct results for a time, then will suddenly incorrectly start returning only 1 ......
Read more >
Improper Error Handling - OWASP Foundation
Improper handling of errors can introduce a variety of security problems for a web site. The most common problem is when detailed internal...
Read more >
A Definitive Guide to Handling Errors in JavaScript - Kinsta
Getting tripped up by errors in your JavaScript? We'll show you how to tame those errors so you can get back to developing...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found