Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

1383 add authorization header to getmap requests #1384

Merged
merged 19 commits into from
Dec 5, 2024

Conversation

kok-foong
Copy link
Collaborator

@kok-foong kok-foong commented Oct 21, 2024

Overview:

  • Adds this header to GetMap requests for MapBox - "Authorization: Bearer ${jwtToken}"

New environment variable

  • REACT_APP_USE_GEOSERVER_PROXY

On server.js, a new API is added:

  • /geoserver-proxy
    • MapBox will be sending requests here when REACT_APP_USE_GEOSERVER_PROXY is true, it adds the JWT token to the header before sending the requests to the specified source

In mapbox-container.tsx

  • a transformRequest field is added to the Map object, when REACT_APP_USE_GEOSERVER_PROXY is true, mapbox will send the requests to /geoserver-proxy

@kok-foong kok-foong linked an issue Oct 21, 2024 that may be closed by this pull request
@kok-foong kok-foong marked this pull request as ready for review October 21, 2024 10:14
@kok-foong kok-foong requested review from Ushcode and qhouyee October 21, 2024 10:15
kok-foong and others added 9 commits November 21, 2024 15:57
…orization-header-to-getmap-requests

# Conflicts:
#	web/twa-vis-platform/code/package.json
#	web/twa-vis-platform/code/server.js
#	web/twa-vis-platform/code/src/ui/map/mapbox/mapbox-container.tsx
#	web/twa-vis-platform/resources/CHANGELOG.md
#	web/twa-vis-platform/resources/VERSION
…orization-header-to-getmap-requests

# Conflicts:
#	web/twa-vis-platform/code/package.json
#	web/twa-vis-platform/code/server.js
#	web/twa-vis-platform/code/src/ui/map/mapbox/mapbox-container.tsx
… into 1383-add-authorization-header-to-getmap-requests
Comment on lines 72 to 73
const serverUrl = `${window.location.protocol}//${window.location.host}`;
const proxyUrl = `${serverUrl}/geoserver-proxy?url=${encodeURIComponent(url)}`;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this needs to change as we do not want to restrict viz and geoserver url to the same host as the viz url

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

agree with this

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

addressed by 1250573

Comment on lines 119 to 142
if (useGeoServerProxy) {
server.get('/geoserver-proxy', async (req, res) => {
const targetUrl = req.query.url;
let headers = { ...req.headers };

if (req.kauth?.grant) {
headers['Authorization'] = 'Bearer ' + req.kauth.grant.access_token.token;
}

try {
// Forward the request to the target URL with the modified headers
const response = await axios({
url: targetUrl,
method: req.method,
headers: headers,
responseType: 'stream', // To stream the response back
});

// Pipe the response back to the client
response.data.pipe(res);
} catch (err) {
// most of these errors can probably be ignored
console.error(err);
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should get rid of this whole path and just save the req.kauth.grant.access_token to the already existing /api/userinfo/path or somewhere else as a global variable. Then call that directly from the mapbox container url transformer

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The intention behind this design is that the token needs to be taken directly from the session store/server for each request, otherwise the token gets outdated and becomes invalid.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this design guarantees that each request is handled by the middleware

Comment on lines 65 to 82
transformRequest: (url) => {
if (process.env.REACT_APP_USE_GEOSERVER_PROXY === 'true') {
try {
const urlObject = new URL(url);
const params = new URLSearchParams(urlObject.search);
if (params.get('request') === 'GetMap') {
// not sure if this will work across all conditions
const serverUrl = `${window.location.protocol}//${window.location.host}`;
const proxyUrl = `${serverUrl}/geoserver-proxy?url=${encodeURIComponent(url)}`;
return {
url: proxyUrl
}
}
} catch { }
} else {
return { url: url }
}
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
transformRequest: (url) => {
if (process.env.REACT_APP_USE_GEOSERVER_PROXY === 'true') {
try {
const urlObject = new URL(url);
const params = new URLSearchParams(urlObject.search);
if (params.get('request') === 'GetMap') {
// not sure if this will work across all conditions
const serverUrl = `${window.location.protocol}//${window.location.host}`;
const proxyUrl = `${serverUrl}/geoserver-proxy?url=${encodeURIComponent(url)}`;
return {
url: proxyUrl
}
}
} catch { }
} else {
return { url: url }
}
}
transformRequest: (url, resourceType) => {
if (resourceType === 'Source' && url.startsWith('http://myHost')) {
return {
url: url.replace('http', 'https'),
headers: {'my-custom-header': true},
credentials: 'include' // Include cookies for cross-origin requests
};
}
}

comes from here. Let's try just pass the header in this bit of code and use a variable to get the bearer token from /api/userinfo

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using resourceType does not seem to be robust enough, when I use MapBox vector tile, its value is 'Tile'

Copy link
Collaborator

@Ushcode Ushcode left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As discussed on call earlier, happy to merge this since it works well for the trajectories use case as demonstrated by @kok-foong and does not interfere with CReDo or other mapbox applications when the geoserver proxy setting is not set.

May revisit the application later with an improved resource server that authorises the token directly with keycloak using the spring adapter, or maybe uses a Requesting Party Token / Token exchange @gpeb2

@Ushcode Ushcode self-requested a review December 5, 2024 12:59
@kok-foong kok-foong merged commit d64ba65 into main Dec 5, 2024
1 check passed
@kok-foong kok-foong deleted the 1383-add-authorization-header-to-getmap-requests branch December 5, 2024 13:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add Authorization header to getmap requests
2 participants