Different graphql endpoint for authenticated requests - apollo-server

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' });

Related

How to Connect Vue.js App to Laravel REST API After Heroku Deployment

I have a front-end application (Vue.js). I have my own REST API (Laravel). I want my Vue.js app to fetch my data from the REST API. Both apps have been deployed to Heroku and each has their own domains.
Locally, in my Vue.js app, I just had this following code snippet to connect to my REST API:
mounted() {
fetch('http://127.0.0.1:8000/api/testdata', {
method: 'get'
})
.then((response) => {
return response.json()
})
// 'jsonData' refers to the json parsed response
.then((jsonData) => {
this.testData = jsonData.data
})
Since both apps have now been deployed, this obviously doesn't work now. I was wondering what I would have to put inside the fetch() method, now that both apps are on the web.
To view my API data locally with Postman, I can just enter this URL in the 'GET' search: http://127.0.0.1:8000/api/test_data.
Now, I'm not sure what I have to enter to see my deployed API data. I've tried this: https://pure-mountain-87762.herokuapp.com/api/test_data and this: https://pure-mountain-87762.herokuapp.com/test_data.
If I know what to put in Postman to view my data, then I should know what to put in my fetch() method (in theory), since the URL's are the same locally.
Also, does anyone know if there would be anything else to configure after this step has been completed?
Thank you
Yes you add a normal domain url to make requests. It will be Your-app-name.herokuapp.com
Check out if you need CORS allowed methods on your backend

How to use openid connect with flutter on spring security

I created a spring boot service that is secured by the spring-security-keycloak-adapter. As the service already knows about the (keycloak) identity provider, I don't see any point in sending the issuerUrl and clientId to the mobile client to login directly into keycloak. Instead, I want to simply call the loginurl of the service in a webview on the client. In my understanding spring should redirect to keycloak and in the end return the token.
Unfortunately all flutter packages require the clientId and issuerUrl for the oauth process
I alread tried the openid_client package for flutter
As your can see in the following code example from the official repository it requires the clientId and issuerUrl
// import the io version
import 'package:openid_client/openid_client_io.dart';
authenticate(Uri uri, String clientId, List<String> scopes) async {
// create the client
var issuer = await Issuer.discover(uri);
var client = new Client(issuer, clientId);
// create an authenticator
var authenticator = new Authenticator(client,
scopes: scopes,
port: 4000);
// starts the authentication
var c = await authenticator.authorize(); // this will open a browser
// return the user info
return await c.getUserInfo();
}
Full disclosure: I didn't write Flutter, but I did write some of the related client code for Spring Security.
Why issuerUri? The reason for this is likely for OIDC Discovery. You can use the issuer to infer the other authorization server endpoints. This cuts down on configuration for you: You don't need to specify the token endpoint, the authorization endpoint, and on and on. If you supply only the issuer, then flutter figures out the rest.
Note that with Spring Security, this is just one configuration option among multiple, but something needs to be specified either way so the app knows where to go. I can't speak for flutter, but it may just be a matter of time before it supports more configuration modes.
Why clientId? This is a security measure and is required by the specification. If someone is calling my API, I want to know who it is. Additionally, authorization servers will use this client_id to do things like make sure that the redirect_uri in the /authorize request matches what is configured for that client_id.

How to secure prisma endpoint deployed to 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".

How do I use golang and nuxt?

I want to use Golang as the server and Nuxt as the frontend, I googled it around but couldn't find any examples.
Code for express/node.js that i found out in the nuxt + express. Link is below
const express = require('express')
// Create express instnace
const app = express()
// Require API routes
const users = require('./routes/users')
// Import API Routes
app.use(users)
// Export the server middleware
module.exports = {
path: '/api',
handler: app
}
I can just create golang server api and deploy it as a microservice but will I lose the SSR power of nuxt? as in will google still crawl my web pages if i use a separate server as opposed to monolithic version of nuxt + node.js
link: https://github.com/nuxt-community/express-template
Regards
You should just separate them. One server is for your backend api in golang. Other server is node server for nuxt ssr. Then you can use nginx to route requests to desired server based on path or anything. And everything will work

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.

Resources