From 05db879b272852f8dfe3e546e1f31c8048c7287a Mon Sep 17 00:00:00 2001 From: Douglas Barone Date: Fri, 4 Dec 2020 18:40:47 -0400 Subject: [PATCH] Added authUpdated subscription --- server/src/classes/User.js | 8 +++++++- server/src/pubsub.js | 3 ++- server/src/resolvers/Subscriptions.js | 18 +++++++++++++++--- server/src/schemaDirectives/AuthDirective.js | 7 +++---- server/src/server.js | 2 +- server/src/typeDefs.js | 1 + server/src/utils/activedirectory/index.js | 1 + server/src/utils/validateToken.js | 7 +++++++ 8 files changed, 37 insertions(+), 10 deletions(-) create mode 100644 server/src/utils/validateToken.js diff --git a/server/src/classes/User.js b/server/src/classes/User.js index c371842..7b355b6 100755 --- a/server/src/classes/User.js +++ b/server/src/classes/User.js @@ -6,6 +6,8 @@ import { encodePassword } from '../utils/activedirectory/encodePassword' import config from '../utils/activedirectory/config' import jwt from 'jsonwebtoken' +import { pubsub, AUTH_UPDATED } from '../pubsub' + class User { constructor(username) { this.username = username @@ -227,13 +229,17 @@ class User { groups } - return prisma.user.upsert({ + const dbUser = await prisma.user.upsert({ where: { sAMAccountName: user.sAMAccountName }, update: user, create: user }) + + pubsub.publish(AUTH_UPDATED, { authUpdated: dbUser }) + + return dbUser } /** diff --git a/server/src/pubsub.js b/server/src/pubsub.js index 3fc8947..28fc89a 100644 --- a/server/src/pubsub.js +++ b/server/src/pubsub.js @@ -1,7 +1,8 @@ import { PubSub } from 'apollo-server' const USER_PRESENCE_UPDATED = 'USER_PRESENCE_UPDATED' +const AUTH_UPDATED = 'AUTH_UPDATED' const pubsub = new PubSub() -export { pubsub, USER_PRESENCE_UPDATED } +export { pubsub, USER_PRESENCE_UPDATED, AUTH_UPDATED } diff --git a/server/src/resolvers/Subscriptions.js b/server/src/resolvers/Subscriptions.js index 7610584..af6de76 100644 --- a/server/src/resolvers/Subscriptions.js +++ b/server/src/resolvers/Subscriptions.js @@ -1,10 +1,22 @@ -import { pubsub, USER_PRESENCE_UPDATED } from '../pubsub' - -import { updateDevicesInfo } from '../utils/wifiUtils' +import { pubsub, USER_PRESENCE_UPDATED, AUTH_UPDATED } from '../pubsub' +import { withFilter } from 'apollo-server' +import { validateToken } from '../utils/validateToken' const Subscription = { userPresenceUpdated: { subscribe: () => pubsub.asyncIterator([USER_PRESENCE_UPDATED]) + }, + authUpdated: { + subscribe: withFilter( + () => pubsub.asyncIterator([AUTH_UPDATED]), + (payload, variables, context) => { + const { sAMAccountName } = validateToken( + context.connection.context.authorization + ) + + return payload.authUpdated.sAMAccountName == sAMAccountName + } + ) } } diff --git a/server/src/schemaDirectives/AuthDirective.js b/server/src/schemaDirectives/AuthDirective.js index c342987..bfeda0b 100755 --- a/server/src/schemaDirectives/AuthDirective.js +++ b/server/src/schemaDirectives/AuthDirective.js @@ -1,8 +1,8 @@ import { SchemaDirectiveVisitor } from 'apollo-server' import { defaultFieldResolver } from 'graphql' -import jwt from 'jsonwebtoken' import { User } from '../classes/User' +import { validateToken } from '../utils/validateToken' class AuthDirective extends SchemaDirectiveVisitor { visitFieldDefinition(field, details) { @@ -20,9 +20,8 @@ class AuthDirective extends SchemaDirectiveVisitor { if (authorizationHeader) { const token = authorizationHeader.replace('Bearer ', '') - const { sAMAccountName, pwdLastSet } = jwt.verify( - token, - process.env.JWT_SECRET + const { sAMAccountName, pwdLastSet } = validateToken( + authorizationHeader ) const user = await new User(sAMAccountName).init() diff --git a/server/src/server.js b/server/src/server.js index 470651d..d09f762 100755 --- a/server/src/server.js +++ b/server/src/server.js @@ -19,7 +19,7 @@ const server = new ApolloServer({ subscriptions: { onConnect: connectionParams => { return { - authorization: connectionParams.headers.Authorization + authorization: connectionParams.Authorization } } }, diff --git a/server/src/typeDefs.js b/server/src/typeDefs.js index 0827388..4be2d1e 100644 --- a/server/src/typeDefs.js +++ b/server/src/typeDefs.js @@ -48,6 +48,7 @@ const typeDefs = gql` type Subscription { userPresenceUpdated: Int! @auth(roles: ["watcher"]) + authUpdated: User! @auth } directive @auth(roles: [String!]) on FIELD_DEFINITION diff --git a/server/src/utils/activedirectory/index.js b/server/src/utils/activedirectory/index.js index 5b22c54..69709c6 100755 --- a/server/src/utils/activedirectory/index.js +++ b/server/src/utils/activedirectory/index.js @@ -1,6 +1,7 @@ import { promiseWrapper as AD } from 'activedirectory2' import config from './config' +// TODO: Refactor to instantiate in context creation function const ad = new AD(config) ad.checkBinding = async () => { diff --git a/server/src/utils/validateToken.js b/server/src/utils/validateToken.js new file mode 100644 index 0000000..107ec2c --- /dev/null +++ b/server/src/utils/validateToken.js @@ -0,0 +1,7 @@ +import jwt from 'jsonwebtoken' + +export function validateToken(authorizationHeader) { + const token = authorizationHeader.replace('Bearer ', '') + + return jwt.verify(token, process.env.JWT_SECRET) +}