All files express.ts

100% Statements 53/53
80% Branches 4/5
100% Functions 7/7
100% Lines 49/49

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 109  1x 1x 1x     1x             1x 1x   1x 2x 2x 2x 2x     1x 1x     1x 1x 1x   1x   1x 2x 2x 2x     1x 1x     2x   2x   2x     3x 3x 3x 3x 3x 3x   3x     1x   1x   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 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';
import { OAuthStrategy } from '.';
 
const grant = grantExpress();
const debug = Debug('@feathersjs/authentication-oauth/express');
 
export default (options: OauthSetupSettings) => {
  return (feathersApp: Application) => {
    const { authService, linkStrategy } = options;
    const app = feathersApp as ExpressApplication;
    const config = app.get('grant');
    
    if (!config) {
      debug('No grant configuration found, skipping Express oAuth setup');
      return;
    }
    
    const { path } = config.defaults;
    const grantApp = grant(config);
    const authApp = express();
 
    authApp.use(options.expressSession);
 
    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 [ strategy ] = service.getStrategies(name) as OAuthStrategy[];
      const sendResponse = async (data: AuthenticationResult|Error) => {
        try {
          const redirect = await strategy.getRedirect(data);
 
          if (redirect !== null) {
            res.redirect(redirect);
          } else if (data instanceof Error) {
            throw data;
          } else {
            res.json(data);
          }
        } catch (error) {
          debug('oAuth error', error);
          next(error);
        }
      };
 
      try {
        const payload = config.defaults.transport === 'session' ?
          grant.response : req.query;
 
        const params = {
          authStrategies: [ 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);
        await sendResponse(error);
      }
    });
 
    authApp.use(grantApp);
 
    app.set('grant', grantApp.config);
    app.use(path, authApp);
  };
};