1- import { createDriver } from 'use-neo4j' ;
21import { initializeSSO } from '../component/sso/SSOUtils' ;
32import { DEFAULT_SCREEN , Screens } from '../config/ApplicationConfig' ;
43import { setDashboard } from '../dashboard/DashboardActions' ;
@@ -44,6 +43,9 @@ import {
4443} from './ApplicationActions' ;
4544import { setLoggingMode , setLoggingDatabase , setLogErrorNotification } from './logging/LoggingActions' ;
4645import { version } from '../modal/AboutModal' ;
46+ import neo4j , { auth , authTokenManagers } from 'neo4j-driver' ;
47+ import type { Neo4jScheme } from 'use-neo4j/dist/neo4j-config.interface' ;
48+ import { SSOProviderOriginal , handleRefreshingToken } from 'neo4j-client-sso' ;
4749import { applicationIsStandalone } from './ApplicationSelectors' ;
4850import { applicationGetLoggingSettings } from './logging/LoggingSelectors' ;
4951import { createLogThunk } from './logging/LoggingThunk' ;
@@ -54,6 +56,47 @@ import { createUUID } from '../utils/uuid';
5456 * Several actions/other thunks may be dispatched from here.
5557 */
5658
59+ export const createDriver = (
60+ scheme : Neo4jScheme ,
61+ host : string ,
62+ port : string | number ,
63+ username ?: string ,
64+ password ?: string ,
65+ config ?: { userAgent ?: string } ,
66+ ssoProviders : SSOProviderOriginal [ ] = [ ]
67+ ) => {
68+ if ( ssoProviders . length > 0 ) {
69+ const authTokenMgr = authTokenManagers . bearer ( {
70+ tokenProvider : async ( ) => {
71+ const credentials = await handleRefreshingToken ( ssoProviders ) ;
72+ const token = auth . bearer ( credentials . password ) ;
73+ // Get the expiration from the JWT's payload, which is a JSON string encoded
74+ // using base64. You could also use a JWT parsing lib
75+ const [ , payloadBase64 ] = credentials . password . split ( '.' ) ;
76+ const payload : unknown = JSON . parse ( window . atob ( payloadBase64 ?? '' ) ) ;
77+ let expiration : Date ;
78+ if ( typeof payload === 'object' && payload !== null && 'exp' in payload ) {
79+ expiration = new Date ( Number ( payload . exp ) * 1000 ) ;
80+ } else {
81+ expiration = new Date ( ) ;
82+ }
83+
84+ return {
85+ expiration,
86+ token,
87+ } ;
88+ } ,
89+ } ) ;
90+ return neo4j . driver ( `${ scheme } ://${ host } :${ port } ` , authTokenMgr , config ) ;
91+ }
92+
93+ if ( ! username || ! password ) {
94+ return neo4j . driver ( `${ scheme } ://${ host } :${ port } ` ) ;
95+ }
96+
97+ return neo4j . driver ( `${ scheme } ://${ host } :${ port } ` , neo4j . auth . basic ( username , password ) , config ) ;
98+ } ;
99+
57100/**
58101 * Establish a connection to Neo4j with the specified credentials. Open/close the relevant windows when connection is made (un)successfully.
59102 * @param protocol - the neo4j protocol (e.g. bolt, bolt+s, neo4j+s, ...)
@@ -62,14 +105,24 @@ import { createUUID } from '../utils/uuid';
62105 * @param database - the Neo4j database to connect to.
63106 * @param username - Neo4j username.
64107 * @param password - Neo4j password.
108+ * @param SSOProviders - List of available SSO providers
65109 */
66110export const createConnectionThunk =
67- ( protocol , url , port , database , username , password ) => ( dispatch : any , getState : any ) => {
111+ ( protocol , url , port , database , username , password , SSOProviders = [ ] ) =>
112+ ( dispatch : any , getState : any ) => {
68113 const loggingState = getState ( ) ;
69114 const loggingSettings = applicationGetLoggingSettings ( loggingState ) ;
70115 const neodashMode = applicationIsStandalone ( loggingState ) ? 'Standalone' : 'Editor' ;
71116 try {
72- const driver = createDriver ( protocol , url , port , username , password , { userAgent : `neodash/v${ version } ` } ) ;
117+ const driver = createDriver (
118+ protocol ,
119+ url ,
120+ port ,
121+ username ,
122+ password ,
123+ { userAgent : `neodash/v${ version } ` } ,
124+ SSOProviders
125+ ) ;
73126 // eslint-disable-next-line no-console
74127 console . log ( 'Attempting to connect...' ) ;
75128 const validateConnection = ( records ) => {
@@ -508,7 +561,7 @@ export const loadApplicationConfigThunk = () => async (dispatch: any, getState:
508561 dispatch ( setAboutModalOpen ( false ) ) ;
509562 dispatch ( setConnected ( false ) ) ;
510563 dispatch ( setWelcomeScreenOpen ( false ) ) ;
511- const success = await initializeSSO ( state . application . cachedSSODiscoveryUrl , ( credentials ) => {
564+ const success = await initializeSSO ( state . application . cachedSSODiscoveryUrl , ( credentials , ssoProviders ) => {
512565 if ( standalone ) {
513566 // Redirected from SSO and running in viewer mode, merge retrieved config with hardcoded credentials.
514567 dispatch (
@@ -518,7 +571,8 @@ export const loadApplicationConfigThunk = () => async (dispatch: any, getState:
518571 config . standalonePort ,
519572 config . standaloneDatabase ,
520573 credentials . username ,
521- credentials . password
574+ credentials . password ,
575+ ssoProviders
522576 )
523577 ) ;
524578 dispatch (
@@ -528,7 +582,8 @@ export const loadApplicationConfigThunk = () => async (dispatch: any, getState:
528582 config . standalonePort ,
529583 config . standaloneDatabase ,
530584 credentials . username ,
531- credentials . password
585+ credentials . password ,
586+ ssoProviders
532587 )
533588 ) ;
534589 } else {
@@ -540,7 +595,8 @@ export const loadApplicationConfigThunk = () => async (dispatch: any, getState:
540595 state . application . connection . port ,
541596 state . application . connection . database ,
542597 credentials . username ,
543- credentials . password
598+ credentials . password ,
599+ ssoProviders
544600 )
545601 ) ;
546602 dispatch ( setConnected ( true ) ) ;
0 commit comments