Skip to content

Commit bf4b74c

Browse files
committed
use plain express 5 with new files
1 parent 94fc898 commit bf4b74c

5 files changed

Lines changed: 932 additions & 4 deletions

File tree

server/routes/obp.ts

Lines changed: 244 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,244 @@
1+
/*
2+
* Open Bank Project - API Explorer II
3+
* Copyright (C) 2023-2025, TESOBE GmbH
4+
*
5+
* This program is free software: you can redistribute it and/or modify
6+
* it under the terms of the GNU Affero General Public License as published by
7+
* the Free Software Foundation, either version 3 of the License, or
8+
* (at your option) any later version.
9+
*
10+
* This program is distributed in the hope that it will be useful,
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
* GNU Affero General Public License for more details.
14+
*
15+
* You should have received a copy of the GNU Affero General Public License
16+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
17+
*
18+
* Email: contact@tesobe.com
19+
* TESOBE GmbH
20+
* Osloerstrasse 16/17
21+
* Berlin 13359, Germany
22+
*
23+
* This product includes software developed at
24+
* TESOBE (http://www.tesobe.com/)
25+
*
26+
*/
27+
28+
import { Router } from 'express'
29+
import type { Request, Response } from 'express'
30+
import { Container } from 'typedi'
31+
import OBPClientService from '../services/OBPClientService.js'
32+
import { OAuth2Service } from '../services/OAuth2Service.js'
33+
34+
const router = Router()
35+
36+
// Get services from container
37+
const obpClientService = Container.get(OBPClientService)
38+
const oauth2Service = Container.get(OAuth2Service)
39+
40+
/**
41+
* Check if access token is expired and refresh it if needed
42+
* This ensures API calls always use a valid token
43+
*/
44+
async function ensureValidToken(session: any): Promise<boolean> {
45+
const accessToken = session.oauth2_access_token
46+
const refreshToken = session.oauth2_refresh_token
47+
48+
// If no access token, user is not authenticated
49+
if (!accessToken) {
50+
return false
51+
}
52+
53+
// Check if token is expired
54+
if (oauth2Service.isTokenExpired(accessToken)) {
55+
console.log('OBP: Access token expired, attempting refresh')
56+
57+
if (!refreshToken) {
58+
console.log('OBP: No refresh token available')
59+
return false
60+
}
61+
62+
try {
63+
const newTokens = await oauth2Service.refreshAccessToken(refreshToken)
64+
65+
// Update session with new tokens
66+
session.oauth2_access_token = newTokens.accessToken
67+
session.oauth2_refresh_token = newTokens.refreshToken || refreshToken
68+
session.oauth2_id_token = newTokens.idToken
69+
session.oauth2_token_timestamp = Date.now()
70+
session.oauth2_expires_in = newTokens.expiresIn
71+
72+
// Update clientConfig with new access token
73+
if (session.clientConfig && session.clientConfig.oauth2) {
74+
session.clientConfig.oauth2.accessToken = newTokens.accessToken
75+
console.log('OBP: Updated clientConfig with refreshed token')
76+
}
77+
78+
console.log('OBP: Token refresh successful')
79+
return true
80+
} catch (error) {
81+
console.error('OBP: Token refresh failed:', error)
82+
return false
83+
}
84+
}
85+
86+
// Token is still valid
87+
return true
88+
}
89+
90+
/**
91+
* GET /get
92+
* Proxy GET requests to OBP API
93+
* Query params:
94+
* - path: OBP API path to call (e.g., /obp/v5.1.0/banks)
95+
*/
96+
router.get('/get', async (req: Request, res: Response) => {
97+
try {
98+
const path = req.query.path as string
99+
const session = req.session as any
100+
101+
// Ensure token is valid before making the request
102+
const tokenValid = await ensureValidToken(session)
103+
if (!tokenValid && session.oauth2_user) {
104+
console.log('OBP: Token expired and refresh failed')
105+
return res.status(401).json({
106+
code: 401,
107+
message: 'Session expired. Please log in again.'
108+
})
109+
}
110+
111+
const oauthConfig = session.clientConfig
112+
113+
const result = await obpClientService.get(path, oauthConfig)
114+
res.json(result)
115+
} catch (error: any) {
116+
// 401 errors are expected when user is not authenticated - log as info, not error
117+
if (error.status === 401) {
118+
console.log(`OBP: 401 Unauthorized for path: ${req.query.path} (user not authenticated)`)
119+
} else {
120+
console.error('OBP: GET request error:', error)
121+
}
122+
res.status(error.status || 500).json({
123+
code: error.status || 500,
124+
message: error.message || 'Internal server error'
125+
})
126+
}
127+
})
128+
129+
/**
130+
* POST /create
131+
* Proxy POST requests to OBP API
132+
* Query params:
133+
* - path: OBP API path to call
134+
* Body: JSON data to send to OBP API
135+
*/
136+
router.post('/create', async (req: Request, res: Response) => {
137+
try {
138+
const path = req.query.path as string
139+
const data = req.body
140+
const session = req.session as any
141+
142+
// Ensure token is valid before making the request
143+
const tokenValid = await ensureValidToken(session)
144+
if (!tokenValid && session.oauth2_user) {
145+
console.log('OBP: Token expired and refresh failed')
146+
return res.status(401).json({
147+
code: 401,
148+
message: 'Session expired. Please log in again.'
149+
})
150+
}
151+
152+
const oauthConfig = session.clientConfig
153+
154+
// Debug logging to diagnose authentication issues
155+
console.log('OBP.create - Debug Info:')
156+
console.log(' Path:', path)
157+
console.log(' Session exists:', !!session)
158+
console.log(' clientConfig exists:', !!oauthConfig)
159+
console.log(' oauth2 exists:', oauthConfig?.oauth2 ? 'YES' : 'NO')
160+
console.log(' accessToken exists:', oauthConfig?.oauth2?.accessToken ? 'YES' : 'NO')
161+
console.log(' oauth2_user exists:', session?.oauth2_user ? 'YES' : 'NO')
162+
163+
const result = await obpClientService.create(path, data, oauthConfig)
164+
res.json(result)
165+
} catch (error: any) {
166+
console.error('OBP.create error:', error)
167+
res.status(error.status || 500).json({
168+
code: error.status || 500,
169+
message: error.message || 'Internal server error'
170+
})
171+
}
172+
})
173+
174+
/**
175+
* PUT /update
176+
* Proxy PUT requests to OBP API
177+
* Query params:
178+
* - path: OBP API path to call
179+
* Body: JSON data to send to OBP API
180+
*/
181+
router.put('/update', async (req: Request, res: Response) => {
182+
try {
183+
const path = req.query.path as string
184+
const data = req.body
185+
const session = req.session as any
186+
187+
// Ensure token is valid before making the request
188+
const tokenValid = await ensureValidToken(session)
189+
if (!tokenValid && session.oauth2_user) {
190+
console.log('OBP: Token expired and refresh failed')
191+
return res.status(401).json({
192+
code: 401,
193+
message: 'Session expired. Please log in again.'
194+
})
195+
}
196+
197+
const oauthConfig = session.clientConfig
198+
199+
const result = await obpClientService.update(path, data, oauthConfig)
200+
res.json(result)
201+
} catch (error: any) {
202+
console.error('OBP.update error:', error)
203+
res.status(error.status || 500).json({
204+
code: error.status || 500,
205+
message: error.message || 'Internal server error'
206+
})
207+
}
208+
})
209+
210+
/**
211+
* DELETE /delete
212+
* Proxy DELETE requests to OBP API
213+
* Query params:
214+
* - path: OBP API path to call
215+
*/
216+
router.delete('/delete', async (req: Request, res: Response) => {
217+
try {
218+
const path = req.query.path as string
219+
const session = req.session as any
220+
221+
// Ensure token is valid before making the request
222+
const tokenValid = await ensureValidToken(session)
223+
if (!tokenValid && session.oauth2_user) {
224+
console.log('OBP: Token expired and refresh failed')
225+
return res.status(401).json({
226+
code: 401,
227+
message: 'Session expired. Please log in again.'
228+
})
229+
}
230+
231+
const oauthConfig = session.clientConfig
232+
233+
const result = await obpClientService.discard(path, oauthConfig)
234+
res.json(result)
235+
} catch (error: any) {
236+
console.error('OBP.delete error:', error)
237+
res.status(error.status || 500).json({
238+
code: error.status || 500,
239+
message: error.message || 'Internal server error'
240+
})
241+
}
242+
})
243+
244+
export default router

0 commit comments

Comments
 (0)