Skip to content

Commit 2be38f2

Browse files
committed
Add basic testkit tests for AuthProvider
1 parent 700e996 commit 2be38f2

File tree

10 files changed

+132
-35
lines changed

10 files changed

+132
-35
lines changed

packages/bolt-connection/src/connection-provider/authentication-provider.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ export default class AuthenticationProvider {
3333
await this._getFreshAuthToken()
3434
}
3535

36-
if (this._renewableAuthToken.authToken !== connection.authToken || this._isTokenExpired()) {
36+
if (this._renewableAuthToken.authToken !== connection.authToken || this._isTokenExpired) {
3737
return await connection.connect(this._userAgent, this._authToken)
3838
}
3939

@@ -68,7 +68,7 @@ export default class AuthenticationProvider {
6868
async _getFreshAuthToken () {
6969
if (this._isTokenExpired) {
7070
const promise = new Promise((resolve, reject) => {
71-
this.scheduleRefresh({
71+
this._scheduleRefresh({
7272
onSuccess: resolve,
7373
onError: reject
7474
})

packages/neo4j-driver-deno/lib/bolt-connection/connection-provider/authentication-provider.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ export default class AuthenticationProvider {
3333
await this._getFreshAuthToken()
3434
}
3535

36-
if (this._renewableAuthToken.authToken !== connection.authToken || this._isTokenExpired()) {
36+
if (this._renewableAuthToken.authToken !== connection.authToken || this._isTokenExpired) {
3737
return await connection.connect(this._userAgent, this._authToken)
3838
}
3939

@@ -68,7 +68,7 @@ export default class AuthenticationProvider {
6868
async _getFreshAuthToken () {
6969
if (this._isTokenExpired) {
7070
const promise = new Promise((resolve, reject) => {
71-
this.scheduleRefresh({
71+
this._scheduleRefresh({
7272
onSuccess: resolve,
7373
onError: reject
7474
})

packages/neo4j-driver-deno/lib/bolt-connection/connection-provider/connection-provider-direct.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,9 +61,9 @@ export default class DirectConnectionProvider extends PooledConnectionProvider {
6161
this._log.warn(
6262
`Direct driver ${this._id} will close connection to ${address} for database '${database}' because of an error ${error.code} '${error.message}'`
6363
)
64-
64+
6565
this._authenticationProvider.handleError({ connection, code: error.code })
66-
66+
6767
if (error.code === 'Neo.ClientError.Security.AuthorizationExpired') {
6868
this._connectionPool.apply(address, (conn) => conn.authToken === null)
6969
}

packages/neo4j-driver/src/index.js

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,22 @@ const {
8484
urlUtil
8585
} = internal
8686

87+
function createAuthProvider (authTokenOrProvider) {
88+
if (typeof authTokenOrProvider === 'function') {
89+
return authTokenOrProvider
90+
}
91+
92+
let authToken = authTokenOrProvider
93+
// Sanitize authority token. Nicer error from server when a scheme is set.
94+
authToken = authToken ?? {}
95+
authToken.scheme = authToken.scheme ?? 'none'
96+
return function () {
97+
return {
98+
authToken
99+
}
100+
}
101+
}
102+
87103
/**
88104
* Construct a new Neo4j Driver. This is your main entry point for this
89105
* library.
@@ -262,9 +278,7 @@ function driver (url, authToken, config = {}) {
262278
config.trust = trust
263279
}
264280

265-
// Sanitize authority token. Nicer error from server when a scheme is set.
266-
authToken = authToken || {}
267-
authToken.scheme = authToken.scheme || 'none'
281+
const authTokenProvider = createAuthProvider(authToken)
268282

269283
// Use default user agent or user agent specified by user.
270284
config.userAgent = config.userAgent || USER_AGENT
@@ -286,7 +300,7 @@ function driver (url, authToken, config = {}) {
286300
config,
287301
log,
288302
hostNameResolver,
289-
authToken,
303+
authTokenProvider,
290304
address,
291305
userAgent: config.userAgent,
292306
routingContext: parsedUrl.query
@@ -303,7 +317,7 @@ function driver (url, authToken, config = {}) {
303317
id,
304318
config,
305319
log,
306-
authToken,
320+
authTokenProvider,
307321
address,
308322
userAgent: config.userAgent
309323
})

packages/testkit-backend/src/context.js

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ export default class Context {
1212
this._bookmarkSupplierRequests = {}
1313
this._notifyBookmarksRequests = {}
1414
this._bookmarksManagers = {}
15+
this._authTokenProviders = {}
16+
this._authTokenProviderRequests = {}
1517
this._binder = binder
1618
this._environmentLogLevel = environmentLogLevel
1719
}
@@ -161,6 +163,34 @@ export default class Context {
161163
delete this._bookmarksManagers[id]
162164
}
163165

166+
addAuthTokenProvider (authTokenProviderFactory) {
167+
this._id++
168+
this._authTokenProviders[this._id] = authTokenProviderFactory(this._id)
169+
return this._id
170+
}
171+
172+
getAuthTokenProvider (id) {
173+
return this._authTokenProviders[id]
174+
}
175+
176+
removeAuthTokenProvider (id) {
177+
delete this._authTokenProviders[id]
178+
}
179+
180+
addAuthTokenProviderRequest (resolve, reject) {
181+
return this._add(this._authTokenProviderRequests, {
182+
resolve, reject
183+
})
184+
}
185+
186+
removeAuthTokenProviderRequest (id) {
187+
delete this._authTokenProviderRequests[id]
188+
}
189+
190+
getAuthTokenProviderRequest (id) {
191+
return this._authTokenProviderRequests[id]
192+
}
193+
164194
_add (map, object) {
165195
this._id++
166196
map[this._id] = object

packages/testkit-backend/src/cypher-native-binders.js

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -253,10 +253,34 @@ export default function CypherNativeBinders (neo4j) {
253253
throw Error(err)
254254
}
255255

256+
function parseAuthToken (authToken) {
257+
switch (authToken.scheme) {
258+
case 'basic':
259+
return neo4j.auth.basic(
260+
authToken.principal,
261+
authToken.credentials,
262+
authToken.realm
263+
)
264+
case 'kerberos':
265+
return neo4j.auth.kerberos(authToken.credentials)
266+
case 'bearer':
267+
return neo4j.auth.bearer(authToken.credentials)
268+
default:
269+
return neo4j.auth.custom(
270+
authToken.principal,
271+
authToken.credentials,
272+
authToken.realm,
273+
authToken.scheme,
274+
authToken.parameters
275+
)
276+
}
277+
}
278+
256279
this.valueResponse = valueResponse
257280
this.objectToCypher = objectToCypher
258281
this.objectToNative = objectToNative
259282
this.objectMemberBitIntToNumber = objectMemberBitIntToNumber
260283
this.nativeToCypher = nativeToCypher
261284
this.cypherToNative = cypherToNative
285+
this.parseAuthToken = parseAuthToken
262286
}

packages/testkit-backend/src/feature/common.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ const features = [
1616
'Feature:Bolt:4.3',
1717
'Feature:Bolt:4.4',
1818
'Feature:Bolt:5.0',
19+
'Feature:Bolt:5.1',
1920
'Feature:Bolt:Patch:UTC',
2021
'Feature:API:ConnectionAcquisitionTimeout',
2122
'Feature:API:Driver:GetServerInfo',

packages/testkit-backend/src/request-handlers-rx.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@ export {
2121
BookmarkManagerClose,
2222
BookmarksSupplierCompleted,
2323
BookmarksConsumerCompleted,
24+
NewAuthTokenProvider,
25+
AuthTokenProviderCompleted,
26+
AuthTokenProviderClose,
2427
StartSubTest
2528
} from './request-handlers.js'
2629

packages/testkit-backend/src/request-handlers.js

Lines changed: 41 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -11,34 +11,23 @@ export function isFrontendError (error) {
1111
export function NewDriver (neo4j, context, data, wire) {
1212
const {
1313
uri,
14-
authorizationToken: { data: authToken },
14+
authorizationToken,
15+
authTokenProviderId,
1516
userAgent,
1617
resolverRegistered
1718
} = data
18-
let parsedAuthToken = authToken
19-
switch (authToken.scheme) {
20-
case 'basic':
21-
parsedAuthToken = neo4j.auth.basic(
22-
authToken.principal,
23-
authToken.credentials,
24-
authToken.realm
25-
)
26-
break
27-
case 'kerberos':
28-
parsedAuthToken = neo4j.auth.kerberos(authToken.credentials)
29-
break
30-
case 'bearer':
31-
parsedAuthToken = neo4j.auth.bearer(authToken.credentials)
32-
break
33-
default:
34-
parsedAuthToken = neo4j.auth.custom(
35-
authToken.principal,
36-
authToken.credentials,
37-
authToken.realm,
38-
authToken.scheme,
39-
authToken.parameters
40-
)
19+
20+
let parsedAuthToken = null
21+
22+
if (authorizationToken != null && authTokenProviderId != null) {
23+
throw new Error('Can not set authorizationToken and authTokenProviderId')
24+
} else if (authorizationToken) {
25+
const { data: authToken } = authorizationToken
26+
parsedAuthToken = context.binder.parseAuthToken(authToken)
27+
} else {
28+
parsedAuthToken = context.getAuthTokenProvider(authTokenProviderId)
4129
}
30+
4231
const resolver = resolverRegistered
4332
? address =>
4433
new Promise((resolve, reject) => {
@@ -491,6 +480,34 @@ export function BookmarksConsumerCompleted (
491480
notifyBookmarksRequest.resolve()
492481
}
493482

483+
export function NewAuthTokenProvider (_, context, _data, wire) {
484+
const id = context.addAuthTokenProvider(authTokenProviderId => {
485+
return () => new Promise((resolve, reject) => {
486+
const id = context.addAuthTokenProviderRequest(resolve, reject)
487+
wire.writeResponse(responses.AuthTokenProviderRequest({ id, authTokenProviderId }))
488+
})
489+
})
490+
491+
wire.writeResponse(responses.AuthTokenProvider({ id }))
492+
}
493+
494+
export function AuthTokenProviderCompleted (_, context, { requestId, auth }, _wire) {
495+
const request = context.getAuthTokenProviderRequest(requestId)
496+
const renewableToken = {
497+
expectedExpirationTime: auth.data.expiresInMs != null
498+
? new Date(new Date().getUTCMilliseconds() + auth.data.expiresInMs)
499+
: undefined,
500+
authToken: context.binder.parseAuthToken(auth.data.auth.data)
501+
}
502+
request.resolve(renewableToken)
503+
context.removeAuthTokenProviderRequest(requestId)
504+
}
505+
506+
export function AuthTokenProviderClose (_, context, { id }, wire) {
507+
context.removeAuthTokenProvider(id)
508+
wire.writeResponse(responses.AuthTokenProvider({ id }))
509+
}
510+
494511
export function GetRoutingTable (_, context, { driverId, database }, wire) {
495512
const driver = context.getDriver(driverId)
496513
const routingTable =

packages/testkit-backend/src/responses.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,14 @@ export function RoutingTable ({ routingTable }) {
8888
})
8989
}
9090

91+
export function AuthTokenProvider ({ id }) {
92+
return response('AuthTokenProvider', { id })
93+
}
94+
95+
export function AuthTokenProviderRequest ({ id, authTokenProviderId }) {
96+
return response('AuthTokenProviderRequest', { id, authTokenProviderId })
97+
}
98+
9199
// Testkit controller messages
92100
export function RunTest () {
93101
return response('RunTest', null)

0 commit comments

Comments
 (0)