Closed ildar-icoosoft closed 6 years ago
I'm using Apollo 2 with setContext link like this:
import ApolloClient from 'apollo-client';
import { ApolloLink } from 'apollo-link';
import { setContext } from 'apollo-link-context';
import { HttpLink } from 'apollo-link-http';
import { InMemoryCache } from 'apollo-cache-inmemory';
import { withClientState } from 'apollo-link-state';
import { clientState } from './clientState';
import { Auth } from 'aws-amplify';
const cache = new InMemoryCache();
//TODO: need to cache token
const authLink = setContext((request) => new Promise( (resolve, reject) => {
Auth.currentSession()
.then(session => {
const token = session.idToken.jwtToken;
resolve({
headers: { Authorization: token }
});
})
}));
const stateLink = withClientState({ ...clientState, cache });
const client = new ApolloClient({
cache,
link: ApolloLink.from([
authLink,
stateLink, //near end but before HttpLink
new HttpLink({uri: process.env.REACT_APP_GRAPHQL_ENDPOINT })
])
});
export default client;
also, don't forget to put this somewhere in a top level file like app.js
:
Amplify.configure({
Auth: {
identityPoolId: '', //REQUIRED - Amazon Cognito Identity Pool ID
region: '', // REQUIRED - Amazon Cognito Region
userPoolId: '', //OPTIONAL - Amazon Cognito User Pool ID
userPoolWebClientId: '', //OPTIONAL - Amazon Cognito Web Client ID
},
Storage: {
bucket: '', //REQUIRED - Amazon S3 bucket
region: '', //OPTIONAL - Amazon service region
}
});
with regard to API gateway, you need to create a user pool and set the authorization to use that pool in the API gateway settings:
I did this a while ago, but if I remember correctly I also had to enable CORS and redeploy the resource.
I'm using lambda and lambda proxy and this is what I have in my handler:
import 'babel-polyfill';
import { graphqlLambda, graphiqlLambda } from 'apollo-server-lambda';
import lambdaPlayground from 'graphql-playground-middleware-lambda';
import { makeExecutableSchema } from 'graphql-tools';
import { typeDefs } from './data/typeDefs';
import { resolvers } from './data/resolvers';
const myGraphQLSchema = makeExecutableSchema({
typeDefs,
resolvers,
});
const CORS_ORIGIN = 'http://some-website.com';
exports.graphqlHandler = function(event, context, callback) {
context.callbackWaitsForEmptyEventLoop = false;
console.log("event", JSON.stringify(event));
const requestOrigin = event.headers.origin,
callbackFilter = function(error, output) {
if (requestOrigin === CORS_ORIGIN) {
output.headers['Access-Control-Allow-Origin'] = '*';
output.headers['Access-Control-Allow-Credentials'] = 'true';
}
callback(error, output);
};
const handler = graphqlLambda((event, context) => {
const headers = event.headers,
functionName = context.functionName;
const userId = process.env.NODE_ENV === 'development'
? process.env.TEST_USER_ID
: event.requestContext.authorizer.claims.sub;
return {
schema: myGraphQLSchema,
context: {
userId,
headers,
functionName,
event,
context,
},
};
});
return handler(event, context, callbackFilter);
};
note that the userId is on event.requestContext.authorizer.claims.sub;
I can't remember the details, but as you are testing keep in mind that for AWS you need to set up IAM roles to allow some services to work together.
hope that helps
EDIT: updated handler to include Access-Control-Allow-Credentials: true
and return callbackFilter
@mlabieniec Thank you! It is helpful for me, but I use IAM authorizer (NOT user pool authorizer like in your code). And the problem is that I can't just add authorizer header, because for IAM authorizer it is required to sign the request. I could sign the request using this code:
import Signer from 'aws-amplify/lib/Common/Signer';
...
Signer.sign(request, signerCredentials, serviceInfo);
So, I need to get the request object. And I don't know how to get request object in Apollo
@ildar-icoosoft
AWS AppSync is a managed GraphQL service that you might find useful as an alternative of API Gateway + Lambda + apollo-server.
I also mention AWS AppSync because it has a JavaScript client/sdk that can handle IAM Auth with sigv4 signing
You can probably take pieces from there and adapt as needed, e.g.:
Using the apollo client, you could add the auth-link from aws-appsync to the client link chain
You might need to customize the auth-link.js a little
I haven't tried this, but let me know how it goes!
Closing.
@manueliglesias @powerful23 How would you attach the user JWT in the headers when using AppSync? (When using IAM auth it is hard to get the User Pool data, instead AppSync give you the Identity Pool credentials.) The standard AppSync example looks something like this
import React from 'react';
import { BrowserRouter as Router, Route, Link } from 'react-router-dom';
import appSyncConfig from "./AppSync";
import { ApolloProvider } from "react-apollo";
import AWSAppSyncClient from "aws-appsync";
import { Rehydrated } from "aws-appsync-react";
import { Auth } from 'aws-amplify'
import AWS from'aws-sdk';
import AllPosts from './Components/AllPosts';
// more routes
const Home = () => (
<div > <AllPosts /> </div>
);
const App = () => (
<div> <Router> <div>
<Route exact={true} path="/" component={Home} />
//more routes
</div> </Router> </div>
);
const client = new AWSAppSyncClient({
url: appSyncConfig.graphqlEndpoint,
region: appSyncConfig.region,
auth: {
type: appSyncConfig.authenticationType, //AWS_IAM
apiKey: appSyncConfig.apiKey,
credentials: () => Auth.currentCredentials(),
});
const WithProvider = () => (
<ApolloProvider client={client}>
<Rehydrated>
<App />
</Rehydrated>
</ApolloProvider>
);
export default WithProvider;
@mixja I've tried this. My question is specifically for using amplify w/ appSync. AppSync seems to over write the headers.
This issue has been automatically locked since there hasn't been any recent activity after it was closed. Please open a new issue for related bugs.
Looking for a help forum? We recommend joining the Amplify Community Discord server *-help
channels or Discussions for those types of questions.
I need to send GraphQL queries to AWS API Gateway (IAM authorizer). I could use a GraphQL client library (for example Apollo) but I have a problem with signing the request. I could use aws-amplify signer.js but I can't get any request object from Apollo library. Are there some examples of how to use aws-amplify with GraphQL?