All files express.ts

100% Statements 51/51
80% Branches 4/5
100% Functions 7/7
100% Lines 47/47

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108  1x 1x 1x 1x     1x           1x 1x   1x 2x 2x 2x 2x 2x     1x 1x     1x 1x   1x           1x 2x 2x 2x     1x 1x     2x   2x   2x     3x 3x 3x 3x 3x 3x     1x   1x   1x         3x                       3x         3x   3x   1x   1x   2x 2x       1x   1x 1x      
// @ts-ignore
import { express as grantExpress } from 'grant';
import Debug from 'debug';
import session from 'express-session';
import querystring from 'querystring';
import { Application } from '@feathersjs/feathers';
import { AuthenticationService, AuthenticationResult } from '@feathersjs/authentication';
import {
  Application as ExpressApplication,
  original as express
} from '@feathersjs/express';
import { OauthSetupSettings } from './utils';
 
const grant = grantExpress();
const debug = Debug('@feathersjs/authentication-oauth/express');
 
export default (options: OauthSetupSettings) => {
  return (feathersApp: Application) => {
    const { path, authService, linkStrategy } = options;
    const app = feathersApp as ExpressApplication;
    const config = app.get('grant');
    const secret = Math.random().toString(36).substring(7);
 
    if (!config) {
      debug('No grant configuration found, skipping Express oAuth setup');
      return;
    }
 
    const grantApp = grant(config);
    const authApp = express();
 
    authApp.use(session({
      secret,
      resave: true,
      saveUninitialized: true
    }));
 
    authApp.get('/:name', (req, res) => {
      const { name } = req.params;
      const { feathers_token, ...query } = req.query;
      const qs = querystring.stringify(query);
 
      if (feathers_token) {
        debug(`Got feathers_token query parameter to link accounts`, feathers_token);
        req.session.accessToken = feathers_token;
      }
 
      const redirect = `${path}/connect/${name}${qs.length ? '?' + qs : ''}`;
 
      debug(`Starting ${name} oAuth flow, redirecting to ${redirect}`);
 
      res.redirect(redirect);
    });
 
    authApp.get('/:name/authenticate', async (req, res, next) => {
      const { name } = req.params;
      const { accessToken, grant } = req.session;
      const service: AuthenticationService = app.service(authService);
      const sendResponse = async (data: AuthenticationResult|Error) => {
        const redirect = await options.getRedirect(service, data);
 
        if (redirect !== null) {
          res.redirect(redirect);
        } else if (data instanceof Error) {
          next(data);
        } else {
          res.json(data);
        }
      };
 
      try {
        const payload = config.defaults.transport === 'session' ?
          grant.response : req.query;
 
        const params = {
          provider: 'rest',
          jwtStrategies: [ name ],
          authentication: accessToken ? {
            strategy: linkStrategy,
            accessToken
          } : null
        };
 
        const authentication = {
          strategy: name,
          ...payload
        };
 
        debug(`Calling ${authService}.create authentication with strategy ${name}`);
 
        const authResult = await service.create(authentication, params);
 
        debug('Successful oAuth authentication, sending response');
 
        await sendResponse(authResult);
      } catch (error) {
        debug('Received oAuth authentication error', error);
        sendResponse(error);
      }
    });
 
    authApp.use(grantApp);
 
    app.set('grant', grantApp.config);
    app.use(path, authApp);
  };
};