@feathersjs/authentication-oauth 5.0.0-pre.9 → 5.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +148 -186
- package/LICENSE +1 -1
- package/README.md +2 -2
- package/lib/index.d.ts +1 -3
- package/lib/index.js +22 -56
- package/lib/index.js.map +1 -1
- package/lib/service.d.ts +36 -0
- package/lib/service.js +143 -0
- package/lib/service.js.map +1 -0
- package/lib/strategy.d.ts +4 -3
- package/lib/strategy.js +95 -119
- package/lib/strategy.js.map +1 -1
- package/lib/utils.d.ts +13 -4
- package/lib/utils.js +90 -5
- package/lib/utils.js.map +1 -1
- package/package.json +32 -23
- package/src/index.ts +35 -66
- package/src/service.ts +179 -0
- package/src/strategy.ts +97 -80
- package/src/utils.ts +118 -12
- package/lib/express.d.ts +0 -16
- package/lib/express.js +0 -114
- package/lib/express.js.map +0 -1
- package/src/express.ts +0 -128
package/src/strategy.ts
CHANGED
|
@@ -1,159 +1,176 @@
|
|
|
1
|
-
/* eslint-disable @typescript-eslint/no-unused-vars */
|
|
2
|
-
// @ts-ignore
|
|
3
|
-
import querystring from 'querystring';
|
|
4
1
|
import {
|
|
5
|
-
AuthenticationRequest,
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
2
|
+
AuthenticationRequest,
|
|
3
|
+
AuthenticationBaseStrategy,
|
|
4
|
+
AuthenticationResult,
|
|
5
|
+
AuthenticationParams
|
|
6
|
+
} from '@feathersjs/authentication'
|
|
7
|
+
import { Params } from '@feathersjs/feathers'
|
|
8
|
+
import { NotAuthenticated } from '@feathersjs/errors'
|
|
9
|
+
import { createDebug, _ } from '@feathersjs/commons'
|
|
10
|
+
import qs from 'qs'
|
|
11
|
+
|
|
12
|
+
const debug = createDebug('@feathersjs/authentication-oauth/strategy')
|
|
12
13
|
|
|
13
14
|
export interface OAuthProfile {
|
|
14
|
-
id?: string|number
|
|
15
|
-
[key: string]: any
|
|
15
|
+
id?: string | number
|
|
16
|
+
[key: string]: any
|
|
16
17
|
}
|
|
17
18
|
|
|
18
19
|
export class OAuthStrategy extends AuthenticationBaseStrategy {
|
|
19
|
-
get configuration
|
|
20
|
-
const { entity, service, entityId, oauth } = this.authentication.configuration
|
|
21
|
-
const config = oauth[this.name]
|
|
20
|
+
get configuration() {
|
|
21
|
+
const { entity, service, entityId, oauth } = this.authentication.configuration
|
|
22
|
+
const config = oauth[this.name] as any
|
|
22
23
|
|
|
23
24
|
return {
|
|
24
25
|
entity,
|
|
25
26
|
service,
|
|
26
27
|
entityId,
|
|
27
28
|
...config
|
|
28
|
-
}
|
|
29
|
+
}
|
|
29
30
|
}
|
|
30
31
|
|
|
31
|
-
get entityId
|
|
32
|
-
const { entityService } = this
|
|
32
|
+
get entityId(): string {
|
|
33
|
+
const { entityService } = this
|
|
33
34
|
|
|
34
|
-
return this.configuration.entityId || (entityService && (entityService as any).id)
|
|
35
|
+
return this.configuration.entityId || (entityService && (entityService as any).id)
|
|
35
36
|
}
|
|
36
37
|
|
|
37
|
-
async getEntityQuery
|
|
38
|
+
async getEntityQuery(profile: OAuthProfile, _params: Params) {
|
|
38
39
|
return {
|
|
39
40
|
[`${this.name}Id`]: profile.sub || profile.id
|
|
40
|
-
}
|
|
41
|
+
}
|
|
41
42
|
}
|
|
42
43
|
|
|
43
|
-
async getEntityData
|
|
44
|
+
async getEntityData(profile: OAuthProfile, _existingEntity: any, _params: Params) {
|
|
44
45
|
return {
|
|
45
46
|
[`${this.name}Id`]: profile.sub || profile.id
|
|
46
|
-
}
|
|
47
|
+
}
|
|
47
48
|
}
|
|
48
49
|
|
|
49
|
-
async getProfile
|
|
50
|
+
async getProfile(data: AuthenticationRequest, _params: Params) {
|
|
50
51
|
return data.profile
|
|
51
52
|
}
|
|
52
53
|
|
|
53
|
-
async getCurrentEntity
|
|
54
|
-
const { authentication } = params
|
|
55
|
-
const { entity } = this.configuration
|
|
54
|
+
async getCurrentEntity(params: Params) {
|
|
55
|
+
const { authentication } = params
|
|
56
|
+
const { entity } = this.configuration
|
|
56
57
|
|
|
57
58
|
if (authentication && authentication.strategy) {
|
|
58
|
-
debug('getCurrentEntity with authentication', authentication)
|
|
59
|
+
debug('getCurrentEntity with authentication', authentication)
|
|
59
60
|
|
|
60
|
-
const { strategy } = authentication
|
|
61
|
-
const authResult = await this.authentication
|
|
62
|
-
.authenticate(authentication, params, strategy);
|
|
61
|
+
const { strategy } = authentication
|
|
62
|
+
const authResult = await this.authentication.authenticate(authentication, params, strategy)
|
|
63
63
|
|
|
64
|
-
return authResult[entity]
|
|
64
|
+
return authResult[entity]
|
|
65
65
|
}
|
|
66
66
|
|
|
67
|
-
return null
|
|
67
|
+
return null
|
|
68
68
|
}
|
|
69
69
|
|
|
70
|
-
async
|
|
71
|
-
const
|
|
72
|
-
|
|
70
|
+
async getAllowedOrigin(params?: Params) {
|
|
71
|
+
const { redirect, origins = this.app.get('origins') } = this.authentication.configuration.oauth
|
|
72
|
+
|
|
73
|
+
if (Array.isArray(origins)) {
|
|
74
|
+
const referer = params?.headers?.referer || origins[0]
|
|
75
|
+
const allowedOrigin = origins.find((current) => referer.toLowerCase().startsWith(current.toLowerCase()))
|
|
76
|
+
|
|
77
|
+
if (!allowedOrigin) {
|
|
78
|
+
throw new NotAuthenticated(`Referer "${referer}" is not allowed.`)
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
return allowedOrigin
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
return redirect
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
async getRedirect(
|
|
88
|
+
data: AuthenticationResult | Error,
|
|
89
|
+
params?: AuthenticationParams
|
|
90
|
+
): Promise<string | null> {
|
|
91
|
+
const queryRedirect = (params && params.redirect) || ''
|
|
92
|
+
const redirect = await this.getAllowedOrigin(params)
|
|
73
93
|
|
|
74
94
|
if (!redirect) {
|
|
75
|
-
return null
|
|
95
|
+
return null
|
|
76
96
|
}
|
|
77
97
|
|
|
78
|
-
const redirectUrl = `${redirect}${queryRedirect}
|
|
79
|
-
const separator = redirect.endsWith('?') ? '' :
|
|
80
|
-
|
|
81
|
-
const
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
};
|
|
87
|
-
|
|
88
|
-
return `${redirectUrl}${separator}${querystring.stringify(query)}`;
|
|
98
|
+
const redirectUrl = `${redirect}${queryRedirect}`
|
|
99
|
+
const separator = redirect.endsWith('?') ? '' : redirect.indexOf('#') !== -1 ? '?' : '#'
|
|
100
|
+
const authResult: AuthenticationResult = data
|
|
101
|
+
const query = authResult.accessToken
|
|
102
|
+
? { access_token: authResult.accessToken }
|
|
103
|
+
: { error: data.message || 'OAuth Authentication not successful' }
|
|
104
|
+
|
|
105
|
+
return `${redirectUrl}${separator}${qs.stringify(query)}`
|
|
89
106
|
}
|
|
90
107
|
|
|
91
|
-
async findEntity
|
|
92
|
-
const query = await this.getEntityQuery(profile, params)
|
|
108
|
+
async findEntity(profile: OAuthProfile, params: Params) {
|
|
109
|
+
const query = await this.getEntityQuery(profile, params)
|
|
93
110
|
|
|
94
|
-
debug('findEntity with query', query)
|
|
111
|
+
debug('findEntity with query', query)
|
|
95
112
|
|
|
96
113
|
const result = await this.entityService.find({
|
|
97
114
|
...params,
|
|
98
115
|
query
|
|
99
|
-
})
|
|
100
|
-
const [
|
|
116
|
+
})
|
|
117
|
+
const [entity = null] = result.data ? result.data : result
|
|
101
118
|
|
|
102
|
-
debug('findEntity returning', entity)
|
|
119
|
+
debug('findEntity returning', entity)
|
|
103
120
|
|
|
104
|
-
return entity
|
|
121
|
+
return entity
|
|
105
122
|
}
|
|
106
123
|
|
|
107
|
-
async createEntity
|
|
108
|
-
const data = await this.getEntityData(profile, null, params)
|
|
124
|
+
async createEntity(profile: OAuthProfile, params: Params) {
|
|
125
|
+
const data = await this.getEntityData(profile, null, params)
|
|
109
126
|
|
|
110
|
-
debug('createEntity with data', data)
|
|
127
|
+
debug('createEntity with data', data)
|
|
111
128
|
|
|
112
|
-
return this.entityService.create(data, _.omit(params, 'query'))
|
|
129
|
+
return this.entityService.create(data, _.omit(params, 'query'))
|
|
113
130
|
}
|
|
114
131
|
|
|
115
|
-
async updateEntity
|
|
116
|
-
const id = entity[this.entityId]
|
|
117
|
-
const data = await this.getEntityData(profile, entity, params)
|
|
132
|
+
async updateEntity(entity: any, profile: OAuthProfile, params: Params) {
|
|
133
|
+
const id = entity[this.entityId]
|
|
134
|
+
const data = await this.getEntityData(profile, entity, params)
|
|
118
135
|
|
|
119
|
-
debug(`updateEntity with id ${id} and data`, data)
|
|
136
|
+
debug(`updateEntity with id ${id} and data`, data)
|
|
120
137
|
|
|
121
|
-
return this.entityService.patch(id, data, _.omit(params, 'query'))
|
|
138
|
+
return this.entityService.patch(id, data, _.omit(params, 'query'))
|
|
122
139
|
}
|
|
123
140
|
|
|
124
|
-
async getEntity
|
|
125
|
-
const { entityService } = this
|
|
126
|
-
const { entityId = (entityService as any).id, entity } = this.configuration
|
|
141
|
+
async getEntity(result: any, params: Params) {
|
|
142
|
+
const { entityService } = this
|
|
143
|
+
const { entityId = (entityService as any).id, entity } = this.configuration
|
|
127
144
|
|
|
128
145
|
if (!entityId || result[entityId] === undefined) {
|
|
129
|
-
throw new NotAuthenticated('Could not get oAuth entity')
|
|
146
|
+
throw new NotAuthenticated('Could not get oAuth entity')
|
|
130
147
|
}
|
|
131
148
|
|
|
132
149
|
if (!params.provider) {
|
|
133
|
-
return result
|
|
150
|
+
return result
|
|
134
151
|
}
|
|
135
152
|
|
|
136
153
|
return entityService.get(result[entityId], {
|
|
137
154
|
..._.omit(params, 'query'),
|
|
138
155
|
[entity]: result
|
|
139
|
-
})
|
|
156
|
+
})
|
|
140
157
|
}
|
|
141
158
|
|
|
142
|
-
async authenticate
|
|
143
|
-
const entity: string = this.configuration.entity
|
|
144
|
-
const { provider, ...params } = originalParams
|
|
145
|
-
const profile = await this.getProfile(authentication, params)
|
|
146
|
-
const existingEntity = await this.findEntity(profile, params)
|
|
147
|
-
|| await this.getCurrentEntity(params);
|
|
159
|
+
async authenticate(authentication: AuthenticationRequest, originalParams: AuthenticationParams) {
|
|
160
|
+
const entity: string = this.configuration.entity
|
|
161
|
+
const { provider, ...params } = originalParams
|
|
162
|
+
const profile = await this.getProfile(authentication, params)
|
|
163
|
+
const existingEntity = (await this.findEntity(profile, params)) || (await this.getCurrentEntity(params))
|
|
148
164
|
|
|
149
|
-
debug('authenticate with (existing) entity', existingEntity)
|
|
165
|
+
debug('authenticate with (existing) entity', existingEntity)
|
|
150
166
|
|
|
151
|
-
const authEntity = !existingEntity
|
|
152
|
-
|
|
167
|
+
const authEntity = !existingEntity
|
|
168
|
+
? await this.createEntity(profile, params)
|
|
169
|
+
: await this.updateEntity(existingEntity, profile, params)
|
|
153
170
|
|
|
154
171
|
return {
|
|
155
172
|
authentication: { strategy: this.name },
|
|
156
173
|
[entity]: await this.getEntity(authEntity, originalParams)
|
|
157
|
-
}
|
|
174
|
+
}
|
|
158
175
|
}
|
|
159
176
|
}
|
package/src/utils.ts
CHANGED
|
@@ -1,17 +1,123 @@
|
|
|
1
|
-
import { RequestHandler } from 'express'
|
|
2
|
-
import { Application } from '@feathersjs/
|
|
1
|
+
import type { RequestHandler } from 'express'
|
|
2
|
+
import type { Middleware, Application as KoaApplication } from '@feathersjs/koa'
|
|
3
|
+
|
|
4
|
+
import type { ServiceOptions } from '@feathersjs/feathers'
|
|
5
|
+
|
|
6
|
+
import '@feathersjs/koa'
|
|
7
|
+
import '@feathersjs/express'
|
|
8
|
+
import expressCookieSession from 'cookie-session'
|
|
9
|
+
import koaCookieSession from 'koa-session'
|
|
10
|
+
|
|
11
|
+
import { AuthenticationService } from '@feathersjs/authentication'
|
|
12
|
+
import { GrantConfig } from 'grant'
|
|
13
|
+
|
|
14
|
+
import { defaultsDeep, each, omit } from 'lodash'
|
|
3
15
|
|
|
4
16
|
export interface OauthSetupSettings {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
17
|
+
linkStrategy: string
|
|
18
|
+
authService?: string
|
|
19
|
+
expressSession?: RequestHandler
|
|
20
|
+
koaSession?: Middleware
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export const getGrantConfig = (service: AuthenticationService): GrantConfig => {
|
|
24
|
+
const {
|
|
25
|
+
app,
|
|
26
|
+
configuration: { oauth }
|
|
27
|
+
} = service
|
|
28
|
+
// Set up all the defaults
|
|
29
|
+
const port = app.get('port')
|
|
30
|
+
let host = app.get('host')
|
|
31
|
+
let protocol = 'https'
|
|
32
|
+
|
|
33
|
+
// Development environments commonly run on HTTP with an extended port
|
|
34
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
35
|
+
protocol = 'http'
|
|
36
|
+
if (String(port) !== '80') {
|
|
37
|
+
host += `:${port}`
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const grant: GrantConfig = defaultsDeep({}, omit(oauth, ['redirect', 'origins']), {
|
|
42
|
+
defaults: {
|
|
43
|
+
prefix: '/oauth',
|
|
44
|
+
origin: `${protocol}://${host}`,
|
|
45
|
+
transport: 'state',
|
|
46
|
+
response: ['tokens', 'raw', 'profile']
|
|
47
|
+
}
|
|
48
|
+
})
|
|
49
|
+
|
|
50
|
+
const getUrl = (url: string) => {
|
|
51
|
+
const { defaults } = grant
|
|
52
|
+
return `${defaults.origin}${defaults.prefix}/${url}`
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
each(grant, (value, name) => {
|
|
56
|
+
if (name !== 'defaults') {
|
|
57
|
+
value.redirect_uri = value.redirect_uri || getUrl(`${name}/callback`)
|
|
58
|
+
}
|
|
59
|
+
})
|
|
60
|
+
|
|
61
|
+
return grant
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export const setExpressParams: RequestHandler = (req, res, next) => {
|
|
65
|
+
req.session.destroy ||= () => {
|
|
66
|
+
req.session = null
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
req.feathers = {
|
|
70
|
+
...req.feathers,
|
|
71
|
+
session: req.session,
|
|
72
|
+
state: res.locals
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
next()
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export const setKoaParams: Middleware = async (ctx, next) => {
|
|
79
|
+
ctx.session.destroy ||= () => {
|
|
80
|
+
ctx.session = null
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
ctx.feathers = {
|
|
84
|
+
...ctx.feathers,
|
|
85
|
+
session: ctx.session,
|
|
86
|
+
state: ctx.state
|
|
87
|
+
} as any
|
|
88
|
+
|
|
89
|
+
await next()
|
|
8
90
|
}
|
|
9
91
|
|
|
10
|
-
export const
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
}
|
|
92
|
+
export const authenticationServiceOptions = (
|
|
93
|
+
service: AuthenticationService,
|
|
94
|
+
settings: OauthSetupSettings
|
|
95
|
+
): ServiceOptions => {
|
|
96
|
+
const { secret } = service.configuration
|
|
97
|
+
const koaApp = service.app as KoaApplication
|
|
98
|
+
|
|
99
|
+
if (koaApp.context) {
|
|
100
|
+
koaApp.keys = [secret]
|
|
101
|
+
|
|
102
|
+
const { koaSession = koaCookieSession({ key: 'feathers.oauth' }, koaApp as any) } = settings
|
|
15
103
|
|
|
16
|
-
|
|
17
|
-
|
|
104
|
+
return {
|
|
105
|
+
koa: {
|
|
106
|
+
before: [koaSession, setKoaParams]
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
const {
|
|
112
|
+
expressSession = expressCookieSession({
|
|
113
|
+
name: 'feathers.oauth',
|
|
114
|
+
keys: [secret]
|
|
115
|
+
})
|
|
116
|
+
} = settings
|
|
117
|
+
|
|
118
|
+
return {
|
|
119
|
+
express: {
|
|
120
|
+
before: [expressSession, setExpressParams]
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
package/lib/express.d.ts
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import { Application } from '@feathersjs/feathers';
|
|
2
|
-
import { OauthSetupSettings } from './utils';
|
|
3
|
-
declare module 'express-session' {
|
|
4
|
-
interface SessionData {
|
|
5
|
-
redirect: string;
|
|
6
|
-
accessToken: string;
|
|
7
|
-
query: {
|
|
8
|
-
[key: string]: any;
|
|
9
|
-
};
|
|
10
|
-
grant: {
|
|
11
|
-
[key: string]: any;
|
|
12
|
-
};
|
|
13
|
-
}
|
|
14
|
-
}
|
|
15
|
-
declare const _default: (options: OauthSetupSettings) => (feathersApp: Application) => void;
|
|
16
|
-
export default _default;
|
package/lib/express.js
DELETED
|
@@ -1,114 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
-
});
|
|
10
|
-
};
|
|
11
|
-
var __rest = (this && this.__rest) || function (s, e) {
|
|
12
|
-
var t = {};
|
|
13
|
-
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
14
|
-
t[p] = s[p];
|
|
15
|
-
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
16
|
-
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
17
|
-
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
18
|
-
t[p[i]] = s[p[i]];
|
|
19
|
-
}
|
|
20
|
-
return t;
|
|
21
|
-
};
|
|
22
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
23
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
24
|
-
};
|
|
25
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
-
const grant_1 = __importDefault(require("grant"));
|
|
27
|
-
const express_session_1 = __importDefault(require("express-session"));
|
|
28
|
-
const commons_1 = require("@feathersjs/commons");
|
|
29
|
-
const express_1 = require("@feathersjs/express");
|
|
30
|
-
const grantInstance = grant_1.default.express();
|
|
31
|
-
const debug = commons_1.createDebug('@feathersjs/authentication-oauth/express');
|
|
32
|
-
exports.default = (options) => {
|
|
33
|
-
return (feathersApp) => {
|
|
34
|
-
const { authService, linkStrategy } = options;
|
|
35
|
-
const app = feathersApp;
|
|
36
|
-
const config = app.get('grant');
|
|
37
|
-
if (!config) {
|
|
38
|
-
debug('No grant configuration found, skipping Express oAuth setup');
|
|
39
|
-
return;
|
|
40
|
-
}
|
|
41
|
-
const { prefix } = config.defaults;
|
|
42
|
-
const expressSession = options.expressSession || express_session_1.default({
|
|
43
|
-
secret: Math.random().toString(36).substring(7),
|
|
44
|
-
saveUninitialized: true,
|
|
45
|
-
resave: true
|
|
46
|
-
});
|
|
47
|
-
const grantApp = grantInstance(config);
|
|
48
|
-
const authApp = express_1.original();
|
|
49
|
-
authApp.use(expressSession);
|
|
50
|
-
authApp.get('/:name', (req, _res, next) => {
|
|
51
|
-
const _a = req.query, { feathers_token, redirect } = _a, query = __rest(_a, ["feathers_token", "redirect"]);
|
|
52
|
-
if (feathers_token) {
|
|
53
|
-
debug('Got feathers_token query parameter to link accounts', feathers_token);
|
|
54
|
-
req.session.accessToken = feathers_token;
|
|
55
|
-
}
|
|
56
|
-
req.session.redirect = redirect;
|
|
57
|
-
req.session.query = query;
|
|
58
|
-
next();
|
|
59
|
-
});
|
|
60
|
-
authApp.get('/:name/authenticate', (req, res, next) => __awaiter(void 0, void 0, void 0, function* () {
|
|
61
|
-
const { name } = req.params;
|
|
62
|
-
const { accessToken, grant, query = {}, redirect } = req.session;
|
|
63
|
-
const service = app.defaultAuthentication(authService);
|
|
64
|
-
const [strategy] = service.getStrategies(name);
|
|
65
|
-
const params = Object.assign(Object.assign({}, req.feathers), { authStrategies: [name], authentication: accessToken ? {
|
|
66
|
-
strategy: linkStrategy,
|
|
67
|
-
accessToken
|
|
68
|
-
} : null, query,
|
|
69
|
-
redirect });
|
|
70
|
-
const sendResponse = (data) => __awaiter(void 0, void 0, void 0, function* () {
|
|
71
|
-
try {
|
|
72
|
-
const redirect = yield strategy.getRedirect(data, params);
|
|
73
|
-
if (redirect !== null) {
|
|
74
|
-
res.redirect(redirect);
|
|
75
|
-
}
|
|
76
|
-
else if (data instanceof Error) {
|
|
77
|
-
throw data;
|
|
78
|
-
}
|
|
79
|
-
else {
|
|
80
|
-
res.json(data);
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
catch (error) {
|
|
84
|
-
debug('oAuth error', error);
|
|
85
|
-
next(error);
|
|
86
|
-
}
|
|
87
|
-
});
|
|
88
|
-
try {
|
|
89
|
-
const payload = config.defaults.transport === 'session' ?
|
|
90
|
-
grant.response : req.query;
|
|
91
|
-
const authentication = Object.assign({ strategy: name }, payload);
|
|
92
|
-
yield new Promise((resolve, reject) => {
|
|
93
|
-
if (!req.session.destroy) {
|
|
94
|
-
req.session = null;
|
|
95
|
-
resolve();
|
|
96
|
-
}
|
|
97
|
-
req.session.destroy((err) => err ? reject(err) : resolve());
|
|
98
|
-
});
|
|
99
|
-
debug(`Calling ${authService}.create authentication with strategy ${name}`);
|
|
100
|
-
const authResult = yield service.create(authentication, params);
|
|
101
|
-
debug('Successful oAuth authentication, sending response');
|
|
102
|
-
yield sendResponse(authResult);
|
|
103
|
-
}
|
|
104
|
-
catch (error) {
|
|
105
|
-
debug('Received oAuth authentication error', error.stack);
|
|
106
|
-
yield sendResponse(error);
|
|
107
|
-
}
|
|
108
|
-
}));
|
|
109
|
-
authApp.use(grantApp);
|
|
110
|
-
app.set('grant', grantApp.config);
|
|
111
|
-
app.use(prefix, authApp);
|
|
112
|
-
};
|
|
113
|
-
};
|
|
114
|
-
//# sourceMappingURL=express.js.map
|
package/lib/express.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"express.js","sourceRoot":"","sources":["../src/express.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;AAAA,kDAA0B;AAC1B,sEAAsC;AAEtC,iDAAkD;AAGlD,iDAG6B;AAI7B,MAAM,aAAa,GAAG,eAAK,CAAC,OAAO,EAAE,CAAC;AACtC,MAAM,KAAK,GAAG,qBAAW,CAAC,0CAA0C,CAAC,CAAC;AAWtE,kBAAe,CAAC,OAA2B,EAAE,EAAE;IAC7C,OAAO,CAAC,WAAwB,EAAE,EAAE;QAClC,MAAM,EAAE,WAAW,EAAE,YAAY,EAAE,GAAG,OAAO,CAAC;QAC9C,MAAM,GAAG,GAAG,WAAiC,CAAC;QAC9C,MAAM,MAAM,GAAG,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QAEhC,IAAI,CAAC,MAAM,EAAE;YACX,KAAK,CAAC,4DAA4D,CAAC,CAAC;YACpE,OAAO;SACR;QAED,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,CAAC,QAAQ,CAAC;QACnC,MAAM,cAAc,GAAG,OAAO,CAAC,cAAc,IAAI,yBAAO,CAAC;YACvD,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC;YAC/C,iBAAiB,EAAE,IAAI;YACvB,MAAM,EAAE,IAAI;SACb,CAAC,CAAC;QACH,MAAM,QAAQ,GAAG,aAAa,CAAC,MAAM,CAAC,CAAC;QACvC,MAAM,OAAO,GAAG,kBAAe,EAAE,CAAC;QAElC,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;QAE5B,OAAO,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC,GAAY,EAAE,IAAc,EAAE,IAAkB,EAAE,EAAE;YACzE,MAAM,KAAyC,GAAG,CAAC,KAAK,EAAlD,EAAE,cAAc,EAAE,QAAQ,OAAwB,EAAnB,KAAK,cAApC,8BAAsC,CAAY,CAAC;YAEzD,IAAI,cAAc,EAAE;gBAClB,KAAK,CAAC,qDAAqD,EAAE,cAAc,CAAC,CAAC;gBAC7E,GAAG,CAAC,OAAO,CAAC,WAAW,GAAG,cAAwB,CAAC;aACpD;YACD,GAAG,CAAC,OAAO,CAAC,QAAQ,GAAG,QAAkB,CAAC;YAC1C,GAAG,CAAC,OAAO,CAAC,KAAK,GAAG,KAAK,CAAC;YAE1B,IAAI,EAAE,CAAA;QACR,CAAC,CAAC,CAAC;QAEH,OAAO,CAAC,GAAG,CAAC,qBAAqB,EAAE,CAAO,GAAY,EAAE,GAAa,EAAE,IAAkB,EAAE,EAAE;YAC3F,MAAM,EAAE,IAAI,EAAE,GAAG,GAAG,CAAC,MAAM,CAAE;YAC7B,MAAM,EAAE,WAAW,EAAE,KAAK,EAAE,KAAK,GAAG,EAAE,EAAE,QAAQ,EAAE,GAAG,GAAG,CAAC,OAAO,CAAC;YACjE,MAAM,OAAO,GAAG,GAAG,CAAC,qBAAqB,CAAC,WAAW,CAAC,CAAC;YACvD,MAAM,CAAE,QAAQ,CAAE,GAAG,OAAO,CAAC,aAAa,CAAC,IAAI,CAAoB,CAAC;YACpE,MAAM,MAAM,mCACP,GAAG,CAAC,QAAQ,KACf,cAAc,EAAE,CAAE,IAAI,CAAE,EACxB,cAAc,EAAE,WAAW,CAAC,CAAC,CAAC;oBAC5B,QAAQ,EAAE,YAAY;oBACtB,WAAW;iBACZ,CAAC,CAAC,CAAC,IAAI,EACR,KAAK;gBACL,QAAQ,GACT,CAAC;YACF,MAAM,YAAY,GAAG,CAAO,IAAgC,EAAE,EAAE;gBAC9D,IAAI;oBACF,MAAM,QAAQ,GAAG,MAAM,QAAQ,CAAC,WAAW,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;oBAE1D,IAAI,QAAQ,KAAK,IAAI,EAAE;wBACrB,GAAG,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;qBACxB;yBAAM,IAAI,IAAI,YAAY,KAAK,EAAE;wBAChC,MAAM,IAAI,CAAC;qBACZ;yBAAM;wBACL,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;qBAChB;iBACF;gBAAC,OAAO,KAAK,EAAE;oBACd,KAAK,CAAC,aAAa,EAAE,KAAK,CAAC,CAAC;oBAC5B,IAAI,CAAC,KAAK,CAAC,CAAC;iBACb;YACH,CAAC,CAAA,CAAC;YAEF,IAAI;gBACF,MAAM,OAAO,GAAG,MAAM,CAAC,QAAQ,CAAC,SAAS,KAAK,SAAS,CAAC,CAAC;oBACvD,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC;gBAC7B,MAAM,cAAc,mBAClB,QAAQ,EAAE,IAAI,IACX,OAAO,CACX,CAAC;gBAEF,MAAM,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;oBAC1C,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,OAAO,EAAE;wBACxB,GAAG,CAAC,OAAO,GAAG,IAAI,CAAC;wBACnB,OAAO,EAAE,CAAC;qBACX;oBAED,GAAG,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,GAAQ,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC;gBACnE,CAAC,CAAC,CAAC;gBAEH,KAAK,CAAC,WAAW,WAAW,wCAAwC,IAAI,EAAE,CAAC,CAAC;gBAE5E,MAAM,UAAU,GAAG,MAAM,OAAO,CAAC,MAAM,CAAC,cAAc,EAAE,MAAM,CAAC,CAAC;gBAEhE,KAAK,CAAC,mDAAmD,CAAC,CAAC;gBAE3D,MAAM,YAAY,CAAC,UAAU,CAAC,CAAC;aAChC;YAAC,OAAO,KAAK,EAAE;gBACd,KAAK,CAAC,qCAAqC,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC;gBAC1D,MAAM,YAAY,CAAC,KAAK,CAAC,CAAC;aAC3B;QACH,CAAC,CAAA,CAAC,CAAC;QAEH,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAEtB,GAAG,CAAC,GAAG,CAAC,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;QAClC,GAAG,CAAC,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC3B,CAAC,CAAC;AACJ,CAAC,CAAC"}
|
package/src/express.ts
DELETED
|
@@ -1,128 +0,0 @@
|
|
|
1
|
-
import grant from 'grant';
|
|
2
|
-
import session from 'express-session';
|
|
3
|
-
import { Request, Response, NextFunction } from 'express';
|
|
4
|
-
import { createDebug } from '@feathersjs/commons';
|
|
5
|
-
import { Application } from '@feathersjs/feathers';
|
|
6
|
-
import { AuthenticationResult } from '@feathersjs/authentication';
|
|
7
|
-
import {
|
|
8
|
-
Application as ExpressApplication,
|
|
9
|
-
original as originalExpress
|
|
10
|
-
} from '@feathersjs/express';
|
|
11
|
-
import { OauthSetupSettings } from './utils';
|
|
12
|
-
import { OAuthStrategy } from './strategy';
|
|
13
|
-
|
|
14
|
-
const grantInstance = grant.express();
|
|
15
|
-
const debug = createDebug('@feathersjs/authentication-oauth/express');
|
|
16
|
-
|
|
17
|
-
declare module 'express-session' {
|
|
18
|
-
interface SessionData {
|
|
19
|
-
redirect: string;
|
|
20
|
-
accessToken: string;
|
|
21
|
-
query: { [key: string]: any };
|
|
22
|
-
grant: { [key: string]: any };
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
export default (options: OauthSetupSettings) => {
|
|
27
|
-
return (feathersApp: Application) => {
|
|
28
|
-
const { authService, linkStrategy } = options;
|
|
29
|
-
const app = feathersApp as ExpressApplication;
|
|
30
|
-
const config = app.get('grant');
|
|
31
|
-
|
|
32
|
-
if (!config) {
|
|
33
|
-
debug('No grant configuration found, skipping Express oAuth setup');
|
|
34
|
-
return;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
const { prefix } = config.defaults;
|
|
38
|
-
const expressSession = options.expressSession || session({
|
|
39
|
-
secret: Math.random().toString(36).substring(7),
|
|
40
|
-
saveUninitialized: true,
|
|
41
|
-
resave: true
|
|
42
|
-
});
|
|
43
|
-
const grantApp = grantInstance(config);
|
|
44
|
-
const authApp = originalExpress();
|
|
45
|
-
|
|
46
|
-
authApp.use(expressSession);
|
|
47
|
-
|
|
48
|
-
authApp.get('/:name', (req: Request, _res: Response, next: NextFunction) => {
|
|
49
|
-
const { feathers_token, redirect, ...query } = req.query;
|
|
50
|
-
|
|
51
|
-
if (feathers_token) {
|
|
52
|
-
debug('Got feathers_token query parameter to link accounts', feathers_token);
|
|
53
|
-
req.session.accessToken = feathers_token as string;
|
|
54
|
-
}
|
|
55
|
-
req.session.redirect = redirect as string;
|
|
56
|
-
req.session.query = query;
|
|
57
|
-
|
|
58
|
-
next()
|
|
59
|
-
});
|
|
60
|
-
|
|
61
|
-
authApp.get('/:name/authenticate', async (req: Request, res: Response, next: NextFunction) => {
|
|
62
|
-
const { name } = req.params ;
|
|
63
|
-
const { accessToken, grant, query = {}, redirect } = req.session;
|
|
64
|
-
const service = app.defaultAuthentication(authService);
|
|
65
|
-
const [ strategy ] = service.getStrategies(name) as OAuthStrategy[];
|
|
66
|
-
const params = {
|
|
67
|
-
...req.feathers,
|
|
68
|
-
authStrategies: [ name ],
|
|
69
|
-
authentication: accessToken ? {
|
|
70
|
-
strategy: linkStrategy,
|
|
71
|
-
accessToken
|
|
72
|
-
} : null,
|
|
73
|
-
query,
|
|
74
|
-
redirect
|
|
75
|
-
};
|
|
76
|
-
const sendResponse = async (data: AuthenticationResult|Error) => {
|
|
77
|
-
try {
|
|
78
|
-
const redirect = await strategy.getRedirect(data, params);
|
|
79
|
-
|
|
80
|
-
if (redirect !== null) {
|
|
81
|
-
res.redirect(redirect);
|
|
82
|
-
} else if (data instanceof Error) {
|
|
83
|
-
throw data;
|
|
84
|
-
} else {
|
|
85
|
-
res.json(data);
|
|
86
|
-
}
|
|
87
|
-
} catch (error) {
|
|
88
|
-
debug('oAuth error', error);
|
|
89
|
-
next(error);
|
|
90
|
-
}
|
|
91
|
-
};
|
|
92
|
-
|
|
93
|
-
try {
|
|
94
|
-
const payload = config.defaults.transport === 'session' ?
|
|
95
|
-
grant.response : req.query;
|
|
96
|
-
const authentication = {
|
|
97
|
-
strategy: name,
|
|
98
|
-
...payload
|
|
99
|
-
};
|
|
100
|
-
|
|
101
|
-
await new Promise<void>((resolve, reject) => {
|
|
102
|
-
if (!req.session.destroy) {
|
|
103
|
-
req.session = null;
|
|
104
|
-
resolve();
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
req.session.destroy((err: any) => err ? reject(err) : resolve());
|
|
108
|
-
});
|
|
109
|
-
|
|
110
|
-
debug(`Calling ${authService}.create authentication with strategy ${name}`);
|
|
111
|
-
|
|
112
|
-
const authResult = await service.create(authentication, params);
|
|
113
|
-
|
|
114
|
-
debug('Successful oAuth authentication, sending response');
|
|
115
|
-
|
|
116
|
-
await sendResponse(authResult);
|
|
117
|
-
} catch (error) {
|
|
118
|
-
debug('Received oAuth authentication error', error.stack);
|
|
119
|
-
await sendResponse(error);
|
|
120
|
-
}
|
|
121
|
-
});
|
|
122
|
-
|
|
123
|
-
authApp.use(grantApp);
|
|
124
|
-
|
|
125
|
-
app.set('grant', grantApp.config);
|
|
126
|
-
app.use(prefix, authApp);
|
|
127
|
-
};
|
|
128
|
-
};
|