Skip to content

Commit

Permalink
feat(oauth2): implement oAuth2
Browse files Browse the repository at this point in the history
  • Loading branch information
udaydenduluri33 committed May 19, 2020
1 parent 60f4de6 commit bcedfb9
Show file tree
Hide file tree
Showing 9 changed files with 210 additions and 30 deletions.
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
"@commitlint/config-conventional": "^8.2.0",
"@types/express": "^4.17.2",
"@types/express-session": "^1.15.16",
"@types/hapi__joi": "^17.1.0",
"@types/jest": "^24.0.24",
"@types/node": "^12.12.21",
"@types/passport": "^1.0.2",
Expand All @@ -57,7 +58,7 @@
"tslint": "^5.20.1",
"tslint-config-prettier": "^1.18.0",
"typescript": "^3.7.3",
"@types/hapi__joi": "^17.1.0"
"@types/passport-oauth2": "^1.4.9"
},
"config": {
"commitizen": {
Expand All @@ -72,6 +73,7 @@
"express-session": "^1.17.0",
"openid-client": "^3.10.0",
"passport": "^0.4.1",
"passport-oauth2": "^1.5.0",
"session-file-store": "^1.3.1"
}
}
14 changes: 14 additions & 0 deletions src/auth/auth.constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
export const AUTH = {
EVENT: {
AUTHENTICATE_SUCCESS: 'auth.authenticate.success',
SERIALIZE_USER: 'auth.serializeUser',
DESERIALIZE_USER: 'auth.deserializeUser',
},
ROUTE: {
DEFAULT_REDIRECT: '/',
LOGIN: '/auth/login',
DEFAULT_AUTH_ROUTE: '/auth/isAuthenticated',
OAUTH_CALLBACK: '/oauth2/callback',
LOGOUT: '/auth/logout',
},
}
20 changes: 14 additions & 6 deletions src/auth/index.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,21 @@
import { NextFunction, Request, RequestHandler, Response } from 'express'
import { ClientMetadata } from 'openid-client'
import * as events from 'events'

export function auth(options: ClientMetadata): RequestHandler {
console.log(options)
return function authMiddleware(req: Request, res: Response, next: NextFunction): void {
return next()
export class Authentication extends events.EventEmitter {
constructor() {
super()
}
}

// import { NextFunction, Request, RequestHandler, Response } from 'express'
// import { ClientMetadata } from 'openid-client'

// export function auth(options: ClientMetadata): RequestHandler {
// console.log(options)
// return function authMiddleware(req: Request, res: Response, next: NextFunction): void {
// return next()
// }
// }

/*
import * as express from "express";
import session from "express-session";
Expand Down
8 changes: 8 additions & 0 deletions src/auth/oauth2/OAuth2Metadata.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { _StrategyOptionsBase } from 'passport-oauth2'

export interface OAuth2Metadata extends _StrategyOptionsBase {
scope: string
sessionKey?: string
logoutUrl: string
useRoutes?: boolean
}
119 changes: 119 additions & 0 deletions src/auth/oauth2/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
import * as events from 'events'
import { NextFunction, Request, RequestHandler, Response } from 'express'
import * as express from 'express'
import { OAuth2Metadata } from './OAuth2Metadata'
import passport from 'passport'
import { AUTH } from '../auth.constants'
import { OAUTH2 } from './oauth2.constants'
import OAuth2Strategy, { VerifyCallback } from 'passport-oauth2'
import { Authentication } from '..'

export class OAuth2 extends Authentication {
protected options: OAuth2Metadata = {
authorizationURL: '',
tokenURL: '',
clientID: '',
clientSecret: '',
scope: '',
logoutUrl: '',
sessionKey: '',
useRoutes: true,
}

router = express.Router({ mergeParams: true })
constructor() {
super()
}

public loginHandler = (req: Request, res: Response, next: NextFunction): RequestHandler => {
console.log('loginHandler Hit')
return passport.authenticate(OAUTH2.STRATEGY_NAME)(req, res, next)
}

public callbackHandler = (req: Request, res: Response, next: NextFunction): void => {
console.info('outside passport authenticate', req.query.code)
passport.authenticate(OAUTH2.STRATEGY_NAME, (error, user, info) => {
console.info('inside passport authenticate')
console.error(error)
if (error) {
console.error(error)
// return next(error);
}
if (info) {
console.info(info)
// return next(info);
}
if (!user) {
console.info('No user found, redirecting')
return res.redirect(AUTH.ROUTE.LOGIN)
}
req.logIn(user, (err) => {
if (err) {
return next(err)
}
if (!this.listenerCount(OAUTH2.EVENT.AUTHENTICATE_SUCCESS)) {
console.log(`redirecting, no listener count: ${OAUTH2.EVENT.AUTHENTICATE_SUCCESS}`, req.session)
res.redirect(AUTH.ROUTE.DEFAULT_REDIRECT)
} else {
this.emit(OAUTH2.EVENT.AUTHENTICATE_SUCCESS, req, res, next)
}
})
})(req, res, next)
}

public configure = (options: OAuth2Metadata): RequestHandler => {
console.log('configure start')
this.options = options
passport.serializeUser((user, done) => {
if (!this.listenerCount(AUTH.EVENT.SERIALIZE_USER)) {
done(null, user)
} else {
this.emit(AUTH.EVENT.SERIALIZE_USER, user, done)
}
})

passport.deserializeUser((id, done) => {
if (!this.listenerCount(AUTH.EVENT.DESERIALIZE_USER)) {
done(null, id)
} else {
this.emit(AUTH.EVENT.DESERIALIZE_USER, id, done)
}
})
console.log('before initialiseStrategy')
this.initialiseStrategy(this.options)
console.log('after initialiseStrategy')

this.router.use(passport.initialize())
this.router.use(passport.session())

if (options.useRoutes) {
this.router.get(AUTH.ROUTE.DEFAULT_AUTH_ROUTE, (req, res) => {
res.send(req.isAuthenticated())
})
this.router.get(AUTH.ROUTE.LOGIN, this.loginHandler)
this.router.get(AUTH.ROUTE.OAUTH_CALLBACK, this.callbackHandler)
this.router.get(AUTH.ROUTE.LOGOUT, async (req, res) => {
await this.logout(req, res)
})
}
this.emit('outh2.bootstrap.success')
console.log('configure end')
return this.router
}

public logout = async (req: express.Request, res: express.Response): Promise<void> => {
await console.log('logout')
}

public initialiseStrategy = (options: OAuth2Metadata): void => {
passport.use(OAUTH2.STRATEGY_NAME, new OAuth2Strategy(options, this.verify))
console.log('initialiseStrategy end')
}

public verify = (accessToken: string, refreshToken: string, results: any, profile: any, done: VerifyCallback) => {
console.log('verify')
done(null, profile)
}
}

export default new OAuth2()
8 changes: 8 additions & 0 deletions src/auth/oauth2/oauth2.constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
export const OAUTH2 = {
EVENT: {
AUTHENTICATE_SUCCESS: 'outh2.authenticate.success',
AUTHENTICATE_FAILURE: 'outh2.authenticate.failure',
},
PROMPT: 'login',
STRATEGY_NAME: 'oauth2',
}
7 changes: 4 additions & 3 deletions src/auth/oidc/index.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
import { NextFunction, Request, RequestHandler, Response } from 'express'
import { Client, Issuer, Strategy, TokenSet, UserinfoResponse } from 'openid-client'
import * as express from 'express'
import * as events from 'events'
import passport from 'passport'
import { AUTH, OIDC } from './oidc.constants'
import { OIDC } from './oidc.constants'
import { URL } from 'url'
import { http } from '../../http/http'
import { OpenIDMetadata } from './OpenIDMetadata'
import { ValidateOpenIdOptions } from './validation/openIdOptions.validation'
import { AUTH } from '../auth.constants'
import { Authentication } from '..'

export class OpenID extends events.EventEmitter {
export class OpenID extends Authentication {
router = express.Router({ mergeParams: true })

protected issuer: Issuer<Client> | undefined
Expand Down
17 changes: 0 additions & 17 deletions src/auth/oidc/oidc.constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,3 @@ export const OIDC = {
PROMPT: 'login',
STRATEGY_NAME: 'oidc',
}

// AUTH

export const AUTH = {
EVENT: {
AUTHENTICATE_SUCCESS: 'auth.authenticate.success',
SERIALIZE_USER: 'auth.serializeUser',
DESERIALIZE_USER: 'auth.deserializeUser',
},
ROUTE: {
DEFAULT_REDIRECT: '/',
LOGIN: '/auth/login',
DEFAULT_AUTH_ROUTE: '/auth/isAuthenticated',
OAUTH_CALLBACK: '/oauth2/callback',
LOGOUT: '/auth/logout',
},
}
43 changes: 40 additions & 3 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -701,12 +701,28 @@
resolved "https://registry.yarnpkg.com/@types/node/-/node-12.12.38.tgz#58841a382f231ad005dbb935c36d44aa1118a26b"
integrity sha512-75eLjX0pFuTcUXnnWmALMzzkYorjND0ezNEycaKesbUBg9eGZp4GHPuDmkRc4mQQvIpe29zrzATNRA6hkYqwmA==

"@types/oauth@*":
version "0.9.1"
resolved "https://registry.yarnpkg.com/@types/oauth/-/oauth-0.9.1.tgz#e17221e7f7936b0459ae7d006255dff61adca305"
integrity sha512-a1iY62/a3yhZ7qH7cNUsxoI3U/0Fe9+RnuFrpTKr+0WVOzbKlSLojShCKe20aOD1Sppv+i8Zlq0pLDuTJnwS4A==
dependencies:
"@types/node" "*"

"@types/parse-json@^4.0.0":
version "4.0.0"
resolved "https://registry.yarnpkg.com/@types/parse-json/-/parse-json-4.0.0.tgz#2f8bb441434d163b35fb8ffdccd7138927ffb8c0"
integrity sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==

"@types/passport@^1.0.2":
"@types/passport-oauth2@^1.4.9":
version "1.4.9"
resolved "https://registry.yarnpkg.com/@types/passport-oauth2/-/passport-oauth2-1.4.9.tgz#134007c4b505a82548c9cb19094c5baeb2205c92"
integrity sha512-QP0q+NVQOaIu2r0e10QWkiUA0Ya5mOBHRJN0UrI+LolMLOP1/VN4EVIpJ3xVwFo+xqNFRoFvFwJhBvKnk7kpUA==
dependencies:
"@types/express" "*"
"@types/oauth" "*"
"@types/passport" "*"

"@types/passport@*", "@types/passport@^1.0.2":
version "1.0.3"
resolved "https://registry.yarnpkg.com/@types/passport/-/passport-1.0.3.tgz#e459ed6c262bf0686684d1b05901be0d0b192a9c"
integrity sha512-nyztuxtDPQv9utCzU0qW7Gl8BY2Dn8BKlYAFFyxKipFxjaVd96celbkLCV/tRqqBUZ+JB8If3UfgV8347DTo3Q==
Expand Down Expand Up @@ -1128,7 +1144,7 @@ balanced-match@^1.0.0:
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767"
integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c=

base64url@^3.0.1:
base64url@3.x.x, base64url@^3.0.1:
version "3.0.1"
resolved "https://registry.yarnpkg.com/base64url/-/base64url-3.0.1.tgz#6399d572e2bc3f90a9a8b22d5dbb0a32d33f788d"
integrity sha512-ir1UPr3dkwexU7FdV8qBBbNDRUhMmIekYMFZfi+C/sLNnRESKPl23nB9b2pltqfOQNnGzsDdId90AEtG5tCx4A==
Expand Down Expand Up @@ -4622,6 +4638,11 @@ oauth-sign@~0.9.0:
resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455"
integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==

oauth@0.9.x:
version "0.9.15"
resolved "https://registry.yarnpkg.com/oauth/-/oauth-0.9.15.tgz#bd1fefaf686c96b75475aed5196412ff60cfb9c1"
integrity sha1-vR/vr2hslrdUda7VGWQS/2DPucE=

object-assign@^4.0.1, object-assign@^4.1.1:
version "4.1.1"
resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
Expand Down Expand Up @@ -4918,6 +4939,17 @@ pascalcase@^0.1.1:
resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14"
integrity sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=

passport-oauth2@^1.5.0:
version "1.5.0"
resolved "https://registry.yarnpkg.com/passport-oauth2/-/passport-oauth2-1.5.0.tgz#64babbb54ac46a4dcab35e7f266ed5294e3c4108"
integrity sha512-kqBt6vR/5VlCK8iCx1/KpY42kQ+NEHZwsSyt4Y6STiNjU+wWICG1i8ucc1FapXDGO15C5O5VZz7+7vRzrDPXXQ==
dependencies:
base64url "3.x.x"
oauth "0.9.x"
passport-strategy "1.x.x"
uid2 "0.0.x"
utils-merge "1.x.x"

passport-strategy@1.x.x:
version "1.0.0"
resolved "https://registry.yarnpkg.com/passport-strategy/-/passport-strategy-1.0.0.tgz#b5539aa8fc225a3d1ad179476ddf236b440f52e4"
Expand Down Expand Up @@ -6358,6 +6390,11 @@ uid-safe@~2.1.5:
dependencies:
random-bytes "~1.0.0"

uid2@0.0.x:
version "0.0.3"
resolved "https://registry.yarnpkg.com/uid2/-/uid2-0.0.3.tgz#483126e11774df2f71b8b639dcd799c376162b82"
integrity sha1-SDEm4Rd03y9xuLY53NeZw3YWK4I=

union-value@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/union-value/-/union-value-1.0.1.tgz#0b6fe7b835aecda61c6ea4d4f02c14221e109847"
Expand Down Expand Up @@ -6425,7 +6462,7 @@ util.promisify@^1.0.0:
has-symbols "^1.0.1"
object.getownpropertydescriptors "^2.1.0"

utils-merge@1.0.1:
utils-merge@1.0.1, utils-merge@1.x.x:
version "1.0.1"
resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713"
integrity sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=
Expand Down

0 comments on commit bcedfb9

Please sign in to comment.