Skip to content
This repository has been archived by the owner on Oct 21, 2020. It is now read-only.

Add auth options 🎉 #58

Merged
merged 17 commits into from
Apr 28, 2018
Merged

Add auth options 🎉 #58

merged 17 commits into from
Apr 28, 2018

Conversation

Bouncey
Copy link
Member

@Bouncey Bouncey commented Apr 23, 2018

Closes #37
Closes #83

@raisedadead
Copy link
Member

Quick dumb query, how do I set a JWT for testing?

@ojongerius
Copy link
Contributor

Nice one 🙇 I'll dedicated some time to review this evening.

@Bouncey
Copy link
Member Author

Bouncey commented Apr 24, 2018

My bad, it was late at night.

You can

Use one of my expired tokens:

eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6Ik0wTTJOVU0yTWpaR1FqUkVRelV4TVRFME9VTTVOVGcwUmtFeE1rTTJOek5GUTBRelJUTkVOZyJ9.eyJuaWNrbmFtZSI6InN0dWFydCIsIm5hbWUiOiJzdHVhcnRAZnJlZWNvZGVjYW1wLm9yZyIsInBpY3R1cmUiOiJodHRwczovL3MuZ3JhdmF0YXIuY29tL2F2YXRhci85ZjhmY2YzY2MzN2QzYWY4NDg0NDg3OTk4OTBmZGRmZT9zPTQ4MCZyPXBnJmQ9aHR0cHMlM0ElMkYlMkZjZG4uYXV0aDAuY29tJTJGYXZhdGFycyUyRnN0LnBuZyIsInVwZGF0ZWRfYXQiOiIyMDE4LTA0LTIyVDEwOjA5OjEzLjkzN1oiLCJlbWFpbCI6InN0dWFydEBmcmVlY29kZWNhbXAub3JnIiwiZW1haWxfdmVyaWZpZWQiOnRydWUsImlzcyI6Imh0dHBzOi8vZnJlZWNvZGVjYW1wLmF1dGgwLmNvbS8iLCJzdWIiOiJlbWFpbHw1YWNiMmVhZGE2ODAzYTkxOTEyODgwMTciLCJhdWQiOiJ2RjcwQ0paeVBLYlpSNHkwYXZlY1hYTGtmeU1ObnlLbiIsImlhdCI6MTUyNDM5MTc1MywiZXhwIjoxNTI0NDI3NzUzLCJhdF9oYXNoIjoiZDZsSW9Ra19uWkwxakxGWlFNN01EdyIsIm5vbmNlIjoiMkJWbVlWOWkzckllSFVJZzhzUU5WTDZtXy1MZTREejUifQ.nw5kbnpqCZRrJN3qr9coUAMNCRRg3Vrs7jhSqyX_BqGNcxZRA0ZYovM0ZNHQBioy_XH0bEeIoy59Bgjzcd-hNFJyoa_8pXRbhJ4tBMYkdK7K8_d8rGdDdSDg2EkTTeeidH8uAx9E14nYCWUJdqRlD1YXp3XkqQtBPLkD5Fu296ZnGrZ8hCjqz78bvYEg-dXYd3NsuuplnbFTjhjhHJ57KxBvk6_2Xvg-eeNx73xOJBsscyStv6eVvzQKMLvEin7SbV4FA4C0cKlKZl7YVj2qVxehojxkDupnSxFCDb59gkf4Z99eOx8qQOE4lI5c3gKuoZ3sIYDd1aRgHXAsvl8Dag

Change this line to

 return jwt.verify(token.replace('Bearer ', ''), cert, { ignoreExpiration: true });

Or generate your own by:

  1. run events locally
  2. log in
  3. access id_token from your localStorage

So, you have a token

Add your token to the request headers 👇

headers

Play around with the directives on the User type and query.

The Idea is:

  • if a field has the @isAuthenticatedOnField directive, the value will be null if they are not authenticated, but other information in the request will be available.
  • if a query has the @isAuthenticatedOnQuery directive, the request will error out if they are not authenticated.

I hope this helps in your QA @raisedadead @ojongerius 😀

Copy link
Contributor

@ojongerius ojongerius left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice work @Bouncey!

import { AuthorizationError } from '../errors';

const log = debug('fcc:resolvers:directives');
const certPath = process.cwd() + '/public.pem';

This comment was marked as off-topic.

This comment was marked as off-topic.

}
try {
return jwt.verify(token.replace('Bearer ', ''), cert);
} catch (err) {

This comment was marked as off-topic.

This comment was marked as off-topic.

const certPath = process.cwd() + '/public.pem';
const cert = fs.readFileSync(certPath);

function isAuth(ctx) {

This comment was marked as off-topic.

This comment was marked as off-topic.

}
};

// Credit: agonbina https://github.com/apollographql/graphql-tools/issues/212

This comment was marked as off-topic.

This comment was marked as off-topic.

@Bouncey Bouncey added the WiP Work in Progress, not ready for QA/merge label Apr 24, 2018
import { asyncErrorHandler } from '../../utils';

const log = debug('fcc:resolvers:directives');
const certPath = process.cwd() + '/public.pem';

This comment was marked as off-topic.

@Bouncey Bouncey removed the WiP Work in Progress, not ready for QA/merge label Apr 24, 2018
.gitignore Outdated
@@ -54,6 +54,10 @@ typings/
# Yarn Integrity file
.yarn-integrity

# certificates

This comment was marked as off-topic.

README.md Outdated
@@ -25,8 +25,11 @@ docker pull lambci/lambda # Pull Docker image used to simulate an AWS Lambda con

```sh
cp sample.env .env
cp public.pem.sample public.pem

This comment was marked as off-topic.

README.md Outdated
```

Add your public key to `public.pem`, instructions can be found in `public.pem`.

This comment was marked as off-topic.

const log = debug('fcc:resolvers:directives');
const {
NODE_ENV,
STAGING_JWT_CERT: stagingCert,

This comment was marked as off-topic.

return asyncErrorHandler(next());
}
throw new AuthorizationError({
message: `You are not authorized, ${error.message}`

This comment was marked as off-topic.

@@ -0,0 +1,4 @@
-----BEGIN CERTIFICATE-----

This comment was marked as off-topic.

Copy link
Member

@raisedadead raisedadead left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

package-lock.json should be deleted.

I would recommend this just to be sure:

  1. rm -rf node_modules package-lock.json
  2. yarn

do the git thing!

package.json Outdated
@@ -23,7 +23,7 @@
"lint": "eslint ./**/*.js --fix",
"prepare-production": "snyk protect",
"start":
"nodemon ./node_modules/serverless/bin/serverless offline start --skipCacheInvalidation",
"DEBUG='fcc:*' nodemon ./node_modules/serverless/bin/serverless offline start --skipCacheInvalidation",

This comment was marked as off-topic.

This comment was marked as off-topic.

This comment was marked as off-topic.

This comment was marked as off-topic.

This comment was marked as off-topic.

This comment was marked as off-topic.

This comment was marked as off-topic.

This comment was marked as off-topic.

@ojongerius
Copy link
Contributor

@raisedadead are you happy for this to go in? Mind you this will need conflicts resolved and I hope my tests will start failing 🤪

@ojongerius
Copy link
Contributor

ojongerius commented Apr 26, 2018

▶ yarn test
yarn run v1.6.0
$ jest --runInBand
 FAIL  test/user.test.js
  ✕ should return a user after one has been created (74ms)

  ● should return a user after one has been created

    TypeError: Cannot read property '0' of null

      40 |
      41 |   /* eslint-disable no-undef */
    > 42 |   expect(data.users[0].name).toBe(user.name);
      43 |   /* eslint-enable no-undef */
      44 | });
      45 |

      at Object.<anonymous>.it (test/user.test.js:42:10)

Test Suites: 1 failed, 1 total
Tests:       1 failed, 1 total
Snapshots:   0 total
Time:        1.394s, estimated 2s
Ran all test suites.
error Command failed with exit code 1.

When having a gander at what we do get back I see:

    { errors:
       [ GraphQLError {
           message: 'Cannot read property \'headers\' of undefined',
           locations: [Array],
           path: [Array] } ],
      data: { users: null } }

Looks like the contents of data are all good, but the error object could to with some attention, and, as expected, we need to adjust these tests to validate requests with, and without authentication and authorisation behave as expected.

For the record, the same code using /api in a browser does return exactly what we want when not authenticated 👍

{
  "data": {
    "users": null
  },
  "errors": [
    {
      "message": "You must supply a JSON Web Token for authorization!",
      "locations": [
        {
          "line": 2,
          "column": 3
        }
      ],
      "path": [
        "users"
      ]
    }
  ]
} 


export const userResolvers = {
Query: {
users: (_, args) => dbUsers.getUsers(args)
users: getUsers
},
Mutation: {
createUser: (_, { email }) => dbUsers.createUser(email)

This comment was marked as off-topic.

This comment was marked as off-topic.

handler.js Outdated
@@ -15,12 +20,12 @@ const connectToDatabase = require('./dataLayer');

const server = require('apollo-server-lambda');

exports.graphqlHandler = function graphqlHandler(event, context, callback) {
export async function graphqlHandler(event, context, callback) {

This comment was marked as off-topic.

This comment was marked as off-topic.

handler.js Outdated

exports.apiHandler = lambdaPlayground({
export const apiHandler = lambdaPlayground({

This comment was marked as off-topic.

@Bouncey
Copy link
Member Author

Bouncey commented Apr 26, 2018

I did a git pull --rebase upstream staging which must have must have reverted things and I didn't notice. I'll untangle this mess when I get in to work

@Bouncey
Copy link
Member Author

Bouncey commented Apr 26, 2018

I will take a look at the test suite. We may need to spilt the current tests in to smaller units, as currently it is a bit end-to-end -ish. The errors headers tells me that context hasn't been set in the handler correctly, for example.

@raisedadead
Copy link
Member

Hi @ojongerius @Bouncey I just rebase and force pushed staging after #69 was merged.

@ojongerius For all intents and purposes, its best to rebase an pr against staging, to avoid nasty merge commits. Or the escape hatch is to simple use squash commit button.

@Bouncey
Copy link
Member Author

Bouncey commented Apr 27, 2018

I want to see if I can get gulp to handle the tests due to the exporting of the JWT_CERT during testing

@Bouncey
Copy link
Member Author

Bouncey commented Apr 27, 2018

@raisedadead after rebasing and merging #83 into this PR I kept on getting this weird gulp error before I even touched the gulpfile

AssertionError [ERR_ASSERTION]: Task function must be specified

I have replaced what gulp was doing for us with cross-env. Can you please check everything is OK on your end using Windows?

@raisedadead
Copy link
Member

Hi @Bouncey

My primary reason for having a task runner was to have the ability to offload stuff from package.json. We could potentially use tasks for deployment and release (github, npm) automation instead of having raw shell files and workarounds in the run scripts.

But, I am OK with removing gulp as long as we are moving forward for now.

@Bouncey
Copy link
Member Author

Bouncey commented Apr 27, 2018

Sweet!

This is now ready for QA @raisedadead @ojongerius

auth/index.js Outdated
let error = null;
try {
decoded = jwt.verify(token.replace('Bearer ', ''), JWT_CERT, {
ignoreExpiration: NODE_ENV === 'test'

This comment was marked as off-topic.

@raisedadead
Copy link
Member

Other than that everything else LGTM. Go to merge.

Side note, I have to lookup but the headers variable like authorization should be capitalised?

authorization => Authorization

As a practice else where?

@Bouncey
Copy link
Member Author

Bouncey commented Apr 28, 2018

The headers are passed to us from serverless through context. We have no control over that.

I was using Authorization in the playground headers, and they were always showing up as authorization in the handler context

@raisedadead
Copy link
Member

Ok perfect.

@raisedadead raisedadead merged commit 2b9f1a0 into freeCodeCamp:staging Apr 28, 2018
@Bouncey
Copy link
Member Author

Bouncey commented Apr 28, 2018

Travis is failing on commitlint-travis. There is an open issue to relax these rules #54, all tests pass

@Bouncey
Copy link
Member Author

Bouncey commented Apr 28, 2018

Sweet!

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants