Skip to content
This repository was archived by the owner on Mar 9, 2021. It is now read-only.

Commit cd7e1bb

Browse files
committed
Added github auth
1 parent 3363429 commit cd7e1bb

File tree

4 files changed

+132
-74
lines changed

4 files changed

+132
-74
lines changed
Lines changed: 37 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,43 @@
11
import passport from 'passport'
22
import { Strategy as GitHubStrategy } from 'passport-github'
3-
import { User } from "../../models";
43

5-
const {
6-
GITHUB_CLIENT_ID,
7-
GITHUB_CLIENT_SECRET
8-
} = process.env
4+
import models from '../../models'
5+
import { GIT_CONFIG } from '../../utils/constants'
96

10-
const GIT_CONFIG = {
11-
clientID: GITHUB_CLIENT_ID,
12-
clientSecret: GITHUB_CLIENT_SECRET,
13-
callbackURL: "http://127.0.0.1:8000/auth/github/callback"
14-
}
7+
passport.serializeUser((user, done) => {
8+
done(null, user)
9+
})
10+
11+
passport.deserializeUser((user, done) => {
12+
done(null, user)
13+
})
1514

1615
passport.use(
17-
new GitHubStrategy(GIT_CONFIG, (accessToken, refreshToken, profile, cb) => {
18-
User.findOrCreate({ githubId: profile.id }, function(err, user) {
19-
return cb(err, user);
20-
});
21-
})
22-
);
16+
new GitHubStrategy(
17+
GIT_CONFIG,
18+
async (accessToken, refreshToken, profile, cb) => {
19+
const data = profile['_json']
20+
if (data['type'] === 'User') {
21+
const [user, created] = await models.User.findOrCreate({
22+
where: {
23+
email: data.email
24+
},
25+
defaults: {
26+
profilePic: data.avatar_url,
27+
name: data.name,
28+
username: data.login,
29+
gitProfile: profile.profileUrl
30+
}
31+
})
32+
return cb(
33+
created || user
34+
? null
35+
: new Error('There was an error during authentication.'),
36+
user
37+
)
38+
} else {
39+
throw TypeError('The Github profile must belong to a User.')
40+
}
41+
}
42+
)
43+
)

src/resolvers/authentication/index.js

Lines changed: 62 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,67 @@
11
import passport from 'passport'
2+
import session from 'express-session'
3+
import jwt from 'jsonwebtoken'
24

35
import './github'
6+
import { TOKEN_EXPIRES_IN, JWT_SECRET } from '../../utils/constants'
47

5-
export default (app) => {
6-
app.get("/auth/:strategy", (req, res) =>
7-
passport.authenticate(req.params.strategy)(req, res)
8-
);
8+
const generateOrRefreshToken = async (req, res) => {
9+
let token = req.headers['x-token'] || 'NO_TOKEN'
10+
let newToken = false
11+
const auth = req.isAuthenticated()
12+
if (auth) {
13+
try {
14+
const user = await jwt.verify(token, JWT_SECRET)
15+
if (user.id !== req.user.id) {
16+
throw new EvalError('Token courrpted. Please get a new one.')
17+
}
18+
} catch (e) {
19+
token = await jwt.sign(
20+
{
21+
id: req.user.id,
22+
email: req.user.email
23+
},
24+
JWT_SECRET,
25+
{
26+
expiresIn: TOKEN_EXPIRES_IN
27+
}
28+
)
29+
newToken = true
30+
}
31+
}
32+
res.send({
33+
auth,
34+
newToken,
35+
token
36+
})
37+
}
938

10-
app.post("/auth/:strategy/callback", (req, res) =>
11-
passport.authenticate(req.params.strategy)(req, res)
12-
);
13-
}
39+
export default app => {
40+
app.use(
41+
session({
42+
secret: 'session-secret',
43+
saveUninitialized: true,
44+
resave: false
45+
})
46+
)
47+
48+
app.use(passport.initialize())
49+
50+
app.use(passport.session())
51+
52+
app.get('/auth/:strategy', (req, res, next) =>
53+
passport.authenticate(req.params.strategy)(req, res, next)
54+
)
55+
56+
app.get('/auth/:strategy/callback', (req, res, next) => {
57+
if (req.query.success) {
58+
generateOrRefreshToken(req, res, next)
59+
} else {
60+
const strategy = req.params.strategy
61+
passport.authenticate(strategy, {
62+
failureRedirect: `/auth/${strategy}/callback?success=false`,
63+
successRedirect: `/auth/${strategy}/callback?success=true`
64+
})(req, res, next)
65+
}
66+
})
67+
}

src/resolvers/authorization.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
1-
import { ForbiddenError } from 'apollo-server';
2-
import { combineResolvers, skip } from 'graphql-resolvers';
1+
import { ForbiddenError } from 'apollo-server'
2+
import { combineResolvers, skip } from 'graphql-resolvers'
33

44
export const isAuthenticated = (parent, args, { loggedInUser }) =>
5-
loggedInUser ? skip : new ForbiddenError('Not authenticated as user.');
5+
loggedInUser ? skip : new ForbiddenError('Not authenticated as user.')
66

77
export const isSelfDeleteAuth = combineResolvers(
88
isAuthenticated,
99
(parent, { id }, { loggedInUser }) =>
1010
id === loggedInUser.id
1111
? skip
12-
: new ForbiddenError('Not authorized as admin.'),
12+
: new ForbiddenError('Not authorized as admin.')
1313
)

src/resolvers/user.js

Lines changed: 29 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,16 @@
1-
import jwt from 'jsonwebtoken'
21
import { combineResolvers } from 'graphql-resolvers'
3-
import { AuthenticationError, UserInputError } from 'apollo-server'
42

53
import { isSelfDeleteAuth, isAuthenticated } from './authorization'
64

7-
const createToken = async (user, secret, expiresIn) => {
8-
const { id, email } = user
9-
return await jwt.sign({ id, email }, secret, {
10-
expiresIn
11-
})
12-
}
5+
/*
6+
User - Base user model used in profiles feature
7+
8+
Extends each new profile for each feature.
9+
10+
- Add new queries under Query
11+
- Whenever a new extension added please add it as field under User
12+
- Add necessary mutations if needed.
13+
*/
1314

1415
export default {
1516
Query: {
@@ -18,82 +19,64 @@ export default {
1819
return allUsers
1920
},
2021
userById: async (parent, { id }, { models }) => {
21-
return await models.User.findByPk(id)
22+
const user = await models.User.findByPk(id)
23+
return user
2224
},
2325
userByEmail: async (parent, { email }, { models }) => {
24-
return await models.User.findOne({
26+
const user = await models.User.findOne({
2527
where: {
2628
email
2729
}
2830
})
31+
return user
2932
},
3033
currentUser: async (parent, args, { models, loggedInUser }) => {
3134
if (!loggedInUser) {
32-
return null;
35+
return null
3336
}
3437

35-
return await models.User.findByPk(loggedInUser.id);
38+
const currentUser = await models.User.findByPk(loggedInUser.id)
39+
return currentUser
3640
}
3741
},
3842

3943
Mutation: {
40-
signUp: async (parent, { email, password }, { models, secret }) => {
41-
const user = await models.User.create({
42-
email,
43-
password
44-
});
45-
46-
return { token: createToken(user, secret, "30m") };
47-
},
48-
49-
signIn: async (parent, { login, password }, { models, secret }) => {
50-
const user = await models.User.findByLogin(login);
51-
52-
if (!user) {
53-
throw new UserInputError("No user found with this login credentials.");
54-
}
55-
56-
const isValid = await user.validatePassword(password);
57-
58-
if (!isValid) {
59-
throw new AuthenticationError("Invalid password.");
60-
}
61-
62-
return { token: createToken(user, secret, "30m") };
63-
},
64-
6544
updateUser: combineResolvers(
6645
isAuthenticated,
6746
async (parent, args, { models, loggedInUser }) => {
68-
const user = await models.User.findByPk(loggedInUser.id);
69-
return await user.update({ ...args });
47+
const user = await models.User.findByPk(loggedInUser.id)
48+
const updatedUser = await user.update({ ...args })
49+
return updatedUser
7050
}
7151
),
7252

7353
deleteUser: combineResolvers(
7454
isSelfDeleteAuth,
7555
async (parent, { id }, { models }) => {
76-
return await models.User.destroy({
56+
const isDestroyed = await models.User.destroy({
7757
where: { id }
78-
});
58+
})
59+
return isDestroyed
7960
}
8061
)
8162
},
8263

8364
User: {
8465
socialProfile: async (user, args, { models }) => {
85-
return await models.SocialProfile.findOne({
66+
const socialProfile = await models.SocialProfile.findOne({
8667
where: {
8768
userId: user.id
8869
}
89-
});
70+
})
71+
return socialProfile
9072
},
9173
eventProfile: async (user, args, { models }) => {
92-
return await models.EventProfile.findOne({
74+
const eventProfile = await models.EventProfile.findOne({
9375
where: {
9476
userId: user.id
9577
}
96-
});
78+
})
79+
return eventProfile
9780
}
9881
}
99-
};
82+
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy