How to secure prisma endpoint deployed to heroku - heroku

I deployed prisma PostgreSQL and yoga server to heroku,
but the graphql endpoint is public, and anyone can mutate from it.
is there a straightforward way of doing it like hasura does:
https://docs.hasura.io/1.0/graphql/manual/deployment/securing-graphql-endpoint.html
PS: I didn't use docker to deploy it, i deployed everything through the prisma wizard in: prisma console

You need a Prisma "secret" to protect your endpoint so that only you and your applications can access/mutate the data. Prisma calls this a managementApiSecret (see here).
I'm not very familiar with the Prisma console, but if you deploy your Prisma server to Heroku with something like a prisma.yml file then you can specify a secret: line like this: secret: ${env: PRISMA_SECRET}. You can then set a Config Var in the settings for your Prisma server on Heroku where the key is PRISMA_SECRET and the value is a random string. I believe you want to do the same thing when using the prisma deploy command. So you're prisma.yml should look something like this:
endpoint: ${env:PRISMA_ENDPOINT_PROD}
datamodel: datamodel.graphql
secret: ${env:PRISMA_SECRET}
hooks:
post-deploy:
- graphql get-schema -p prisma
Then you'll need to specify that same secret in your Yoga server so that it can access the Prisma server. It's hard to help you with this without seeing your code for the Yoga server, but mine uses the prisma-binding package like this:
const { Prisma } = require('prisma-binding');
const db = new Prisma({
typeDefs: 'src/generated/prisma.graphql',
endpoint: process.env.PRISMA_ENDPOINT_PROD,
secret: process.env.PRISMA_SECRET,
debug: false, // Turn on to console.log queries and mutations
});
module.exports = db;
You can see that the Yoga server connects to the Prisma database with the secret specified. The Yoga server is deployed on Heroku and I've specified the PRISMA_SECRET environment variable in the Heroku settings for the Yoga server.
This setup though will prevent you from going to your Prisma endpoint in your browser and manually querying and mutating the data in your database through the GraphQL playground. There may be a way around this but I'm not sure how. Also note that this won't give you the nice login interface that Hasura appears to give you.
If you want more code to follow you can view this GitHub repo by Wes Bos, which is what he uses for his course called "Fullstack Advanced React & GraphQL".

Related

How to change AWS Amplify Appsync default authorization mode form API KEY to cognito user pool?

I'm working with Amplify, I added the authentication to my application and my graphQL schema is with rule private, all things work good in my local, each graphQl api called, It contains the access token and appSync accept my request.
But when I deploy my App, I get an error because all my graphQl request still with api-key not with access token.
my schema.graphQl
My AWSAppSyncClient
In the console I use this configuration:
In my local : all thins work good after authentication.
In production : graphQl still with api-key after authentication
Based on this documentation I ran amplify update api:
From there the command line prompts you to select the API type:
? Please select from one of the below mentioned services:
> `GraphQL`
? Select a setting to edit:
> `Authorization modes`
? Choose the default authorization type for the API
API key
Amazon Cognito User Pool
❯ IAM
OpenID Connect
I updated the default authorization type for the API to be Amazon Cognito User Pool instead of API key.
Then I had to run amplify push --appId YOUR_APP_ID --envName YOUR_STAGING_ENV to sync up the changes.

Using non-default schema in GraphQL

I'm building a GraphQL API for a mobile app backend. I'm building it on top of Laravel using rebing/graphql-laravel, and I'm having a bit of trouble.
Most of the queries and mutations require that the user be logged in, so they use authentication middleware to limit access (though at some point I plan to replace this with JWT, which is what will be used in production). However, there are two mutations that should be accessible to users who are not logged in - one to pass through the login details and get a JWT, the other to register the user and get a JWT.
The only way I could find to do this was to move these mutations to a separate auth schema. However, despite rooting through the documentation I can't for the life of me find how to specify a schema other than the default.
The mutation for creating a user looks like this:
mutation {
createUser (
email: "jeff#example.co.uk",
name: "Jeff",
password: "password"
) {
token
}
}
It works if I move the mutation to the default schema, but of course that's no use for my use case.
How do I need to adapt this to use the auth schema instead of the default schema? It sounds like it should be straightforward, but I can't for the life of me find it via Google.
Turns out this is straightforward enough, just seemed hard to track down.
The URL for both the GraphQL endpoint and the GraphiQL interface has an optional parameter for the schema name field, as show in the relevant lines from the output of php artisan routes:list. This includes the following routes:
graphql/{default}
graphql/{auth}
graphiql/{default}
graphiql/{auth}
If you navigate to the graphiql/auth in the browser, you can therefore use the queries and mutations registered to the auth schema there. Similarly, you can query graphql/auth as usual. In both cases, you'll have the middleware set for the auth schema applied.
If you don't specify the second URL parameter, then you'll be using the default schema.

Different graphql endpoint for authenticated requests

How do you provide a different endpoint for authenticated GraphQL queries using Apollo Server? i.e. /graphql for public queries and /auth/graphql for private queries? I can find plenty of examples for doing both over a single endpoint but none for multiple endpoints.
If you are using apollo-server-express, you can create multiple ApolloServer instance and applyMiddleware to express app.
const app = express();
// create server1, server2 with its schema
// then
server1.applyMiddleware({ app, path: '/auth/graphql' });
server2.applyMiddleware({ app, path: '/graphql' });

Struggling with apollo-link-ws x-api-key authorization

I'm using Apollo to connect to an AWS Appsync API which is secured with an API Key. No problems with queries and mutations over http but I'm on unfamiliar territory using websockets for subscriptions.
Using apollo-link-ws I have the following, and I have no idea how to add the API Key. Can any kind soul offer advice?
const ws = new WebSocketLink({
uri: `wss://xxxxx.appsync-api.eu-west-1.amazonaws.com/graphql`,
options: {
reconnect: true
}
});
BTW I'm assuming that the url for wss is the same as for http....
apollo-ws-link does not directly work with AWS AppSync subscriptions. Take a look at the AWS Amplify GraphQL client that handles authorization with AppSync as well as subscriptions. This should get your app working with AppSync in a couple minutes.
If you want to implement your own subscriptions client, the handshake is documented within the Amplify library.
Authorization is usually based on connectionParams, but AWS decided to go different way, and they implemented it some shady way using REST and custom headers.
The problem is Websockets doesn't support custom headers. What makes it difficult to integrate with Apollo.
AppSync has much more flaws than just this one. I wouldn't recommend it for anything more ambitious than a blog or chat anyway. This article explain better some of its drawbacks.
Have you checked out the AppSync guide for "Building a JavaScript Client App": https://docs.aws.amazon.com/appsync/latest/devguide/building-a-client-app-javascript.html
With AWSAppSyncClient setting up subscriptions is effortless. It uses websockets automatically when setting up subscriptions.
I haven't even been aware of apollo-link-ws and such complexities when using AppSync subscriptions with Apollo. I only have experience of AppSync subscriptions with the React client but the plain JavaScript usage seems comparatively simple.
From the example in the guide:
const client = new AWSAppSyncClient({
url: url,
region: region,
auth: {
type: type,
credentials: credentials,
}
});
client.hydrated().then(function (client) {
//Now subscribe to results
const observable = client.subscribe({ query: subquery });
const realtimeResults = function realtimeResults(data) {
console.log('realtime data: ', data);
};
observable.subscribe({
next: realtimeResults,
complete: console.log,
error: console.log,
});
});
// Set up a subscription query
const subquery = gql(`
subscription NewPostSub {
newPost {
__typename
id
title
author
version
}
}`);
For Node.js usage, the guide also shows how to set up global.WebSocket and such dependencies in the example code.

React Native with Apollo can't connect to Graphql server in Heroku

I'm been working in a project to test Graphql and is working fine in the server, but I can not connect my React Native app to the "API" server that is configured in Heroku with Django + Postgress + Graphene. You can test it here: https://hosting-api.herokuapp.com/graphiql
I choose Apollo for the React Native app to manage the connection following this example: http://dev.apollodata.com/react/simple-example.html
The app works ok with the default URL: http://api.githunt.com/graphql but when I change to my server I got the error in the image. 403 is the code for forbidden, but I have already added '*' to the allowed_hosts and cors_origin_whitelist. Also, when I change to another URL, e.g. my blog, it returns a 200 error which is ok because I don't have Graphql configured there but at least the app can make a connection.
Any ideas or suggestions?
Try to check django log, in my case trouble was with CSRF token.
And fix looks like:
urls.py
from django.views.decorators.csrf import csrf_exempt
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^graphql', csrf_exempt(GraphQLView.as_view(graphiql=True))),
]

Resources