Skip to content

Commit

Permalink
Dynamically compute OpenID redirectUri from proxy HTTP headers
Browse files Browse the repository at this point in the history
Signed-off-by: Jean-Christian Simonetti <[email protected]>
  • Loading branch information
jaycci committed Apr 8, 2022
1 parent afa8f13 commit 36c4719
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 9 deletions.
39 changes: 33 additions & 6 deletions server/auth/types/openid/helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import wreck from '@hapi/wreck';
import { parse, stringify } from 'querystring';
import { CoreSetup } from 'opensearch-dashboards/server';
import { SecurityPluginConfigType } from '../../..';
import { OpenSearchDashboardsRequest } from '../../../../../../src/core/server';

export function parseTokenResponse(payload: Buffer) {
const payloadString = payload.toString();
Expand All @@ -30,19 +31,45 @@ export function parseTokenResponse(payload: Buffer) {
return parse(payloadString);
}

export function getBaseRedirectUrl(config: SecurityPluginConfigType, core: CoreSetup): string {
export function getRootUrl(
config: SecurityPluginConfigType,
core: CoreSetup,
request: OpenSearchDashboardsRequest
): string {
const host = core.http.getServerInfo().hostname;
const port = core.http.getServerInfo().port;
let protocol = core.http.getServerInfo().protocol;
let httpHost = `${host}:${port}`;

if (config.openid?.trust_dynamic_headers) {
const xForwardedHost = (request.headers['x-forwarded-host'] as string) || undefined;
const xForwardedProto = (request.headers['x-forwarded-proto'] as string) || undefined;
if (xForwardedHost) {
httpHost = xForwardedHost;
}
if (xForwardedProto) {
protocol = xForwardedProto;
}
}

return `${protocol}://${httpHost}`;
}

export function getBaseRedirectUrl(
config: SecurityPluginConfigType,
core: CoreSetup,
request: OpenSearchDashboardsRequest
): string {
if (config.openid?.base_redirect_url) {
const baseRedirectUrl = config.openid.base_redirect_url;
return baseRedirectUrl.endsWith('/') ? baseRedirectUrl.slice(0, -1) : baseRedirectUrl;
}

const host = core.http.getServerInfo().hostname;
const port = core.http.getServerInfo().port;
const protocol = core.http.getServerInfo().protocol;
const rootUrl = getRootUrl(config, core, request);
if (core.http.basePath.serverBasePath) {
return `${protocol}://${host}:${port}${core.http.basePath.serverBasePath}`;
return `${rootUrl}${core.http.basePath.serverBasePath}`;
}
return `${protocol}://${host}:${port}`;
return rootUrl;
}

export async function callTokenEndpoint(
Expand Down
10 changes: 7 additions & 3 deletions server/auth/types/openid/routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,11 @@ export class OpenIdAuthRoutes {
const query: any = {
client_id: this.config.openid?.client_id,
response_type: 'code',
redirect_uri: `${getBaseRedirectUrl(this.config, this.core)}/auth/openid/login`,
redirect_uri: `${getBaseRedirectUrl(
this.config,
this.core,
request
)}/auth/openid/login`,
state: nonce,
scope: this.openIdAuthConfig.scope,
};
Expand Down Expand Up @@ -133,7 +137,7 @@ export class OpenIdAuthRoutes {
const query: any = {
grant_type: 'authorization_code',
code: request.query.code,
redirect_uri: `${getBaseRedirectUrl(this.config, this.core)}/auth/openid/login`,
redirect_uri: `${getBaseRedirectUrl(this.config, this.core, request)}/auth/openid/login`,
client_id: clientId,
client_secret: clientSecret,
};
Expand Down Expand Up @@ -192,7 +196,7 @@ export class OpenIdAuthRoutes {
// authHeaderValue is the bearer header, e.g. "Bearer <auth_token>"
const token = cookie?.credentials.authHeaderValue.split(' ')[1]; // get auth token
const logoutQueryParams = {
post_logout_redirect_uri: getBaseRedirectUrl(this.config, this.core),
post_logout_redirect_uri: getBaseRedirectUrl(this.config, this.core, request),
id_token_hint: token,
};

Expand Down
1 change: 1 addition & 0 deletions server/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@ export const configSchema = schema.object({
root_ca: schema.string({ defaultValue: '' }),
verify_hostnames: schema.boolean({ defaultValue: true }),
refresh_tokens: schema.boolean({ defaultValue: true }),
trust_dynamic_headers: schema.boolean({ defaultValue: false }),
})
),
proxycache: schema.maybe(
Expand Down

0 comments on commit 36c4719

Please sign in to comment.