Skip to content

Commit

Permalink
Modify routes for saml to suport new prefix
Browse files Browse the repository at this point in the history
Signed-off-by: Ryan Liang <[email protected]>
  • Loading branch information
RyanL1997 committed Aug 28, 2023
1 parent f655ccf commit 99afb6e
Showing 1 changed file with 170 additions and 131 deletions.
301 changes: 170 additions & 131 deletions server/auth/types/saml/routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,145 @@ export class SamlAuthRoutes {
};
}

private async handleSamlAcs(context: any, request: any, response: any) {
let requestId: string = '';
let nextUrl: string = '/';
let redirectHash: boolean = false;

Check failure on line 54 in server/auth/types/saml/routes.ts

View workflow job for this annotation

GitHub Actions / Run unit tests (ubuntu-latest)

Delete `····`

Check failure on line 54 in server/auth/types/saml/routes.ts

View workflow job for this annotation

GitHub Actions / Run unit tests (macos-latest)

Delete `····`

Check failure on line 54 in server/auth/types/saml/routes.ts

View workflow job for this annotation

GitHub Actions / Run unit tests (windows-latest)

Delete `····`
try {
const cookie = await this.sessionStorageFactory.asScoped(request).get();
if (cookie) {
requestId = cookie.saml?.requestId || '';
nextUrl = cookie.saml?.nextUrl || '/';
redirectHash = cookie.saml?.redirectHash || false;
}

Check failure on line 62 in server/auth/types/saml/routes.ts

View workflow job for this annotation

GitHub Actions / Run unit tests (ubuntu-latest)

Delete `··`

Check failure on line 62 in server/auth/types/saml/routes.ts

View workflow job for this annotation

GitHub Actions / Run unit tests (macos-latest)

Delete `··`

Check failure on line 62 in server/auth/types/saml/routes.ts

View workflow job for this annotation

GitHub Actions / Run unit tests (windows-latest)

Delete `··`
if (!requestId) {
return response.badRequest({
body: 'Invalid requestId',
});
}
} catch (error) {
context.security_plugin.logger.error(`Failed to parse cookie: ${error}`);
return response.badRequest();
}

Check failure on line 72 in server/auth/types/saml/routes.ts

View workflow job for this annotation

GitHub Actions / Run unit tests (ubuntu-latest)

Delete `··`

Check failure on line 72 in server/auth/types/saml/routes.ts

View workflow job for this annotation

GitHub Actions / Run unit tests (macos-latest)

Delete `··`

Check failure on line 72 in server/auth/types/saml/routes.ts

View workflow job for this annotation

GitHub Actions / Run unit tests (windows-latest)

Delete `··`
try {
const credentials = await this.securityClient.authToken(
requestId,
request.body.SAMLResponse,
undefined
);

Check failure on line 79 in server/auth/types/saml/routes.ts

View workflow job for this annotation

GitHub Actions / Run unit tests (ubuntu-latest)

Delete `··`

Check failure on line 79 in server/auth/types/saml/routes.ts

View workflow job for this annotation

GitHub Actions / Run unit tests (macos-latest)

Delete `··`

Check failure on line 79 in server/auth/types/saml/routes.ts

View workflow job for this annotation

GitHub Actions / Run unit tests (windows-latest)

Delete `··`
const user = await this.securityClient.authenticateWithHeader(
request,
'authorization',
credentials.authorization
);

Check failure on line 85 in server/auth/types/saml/routes.ts

View workflow job for this annotation

GitHub Actions / Run unit tests (ubuntu-latest)

Delete `··`

Check failure on line 85 in server/auth/types/saml/routes.ts

View workflow job for this annotation

GitHub Actions / Run unit tests (macos-latest)

Delete `··`

Check failure on line 85 in server/auth/types/saml/routes.ts

View workflow job for this annotation

GitHub Actions / Run unit tests (windows-latest)

Delete `··`
let expiryTime = Date.now() + this.config.session.ttl;
const [headerEncoded, payloadEncoded] = credentials.authorization.split('.');

Check failure on line 88 in server/auth/types/saml/routes.ts

View workflow job for this annotation

GitHub Actions / Run unit tests (ubuntu-latest)

Delete `······`

Check failure on line 88 in server/auth/types/saml/routes.ts

View workflow job for this annotation

GitHub Actions / Run unit tests (macos-latest)

Delete `······`

Check failure on line 88 in server/auth/types/saml/routes.ts

View workflow job for this annotation

GitHub Actions / Run unit tests (windows-latest)

Delete `······`
if (!payloadEncoded) {
context.security_plugin.logger.error('JWT token payload not found');
}

Check failure on line 92 in server/auth/types/saml/routes.ts

View workflow job for this annotation

GitHub Actions / Run unit tests (ubuntu-latest)

Delete `··`

Check failure on line 92 in server/auth/types/saml/routes.ts

View workflow job for this annotation

GitHub Actions / Run unit tests (macos-latest)

Delete `··`

Check failure on line 92 in server/auth/types/saml/routes.ts

View workflow job for this annotation

GitHub Actions / Run unit tests (windows-latest)

Delete `··`
const tokenPayload = JSON.parse(Buffer.from(payloadEncoded, 'base64').toString());

Check failure on line 94 in server/auth/types/saml/routes.ts

View workflow job for this annotation

GitHub Actions / Run unit tests (ubuntu-latest)

Delete `······`

Check failure on line 94 in server/auth/types/saml/routes.ts

View workflow job for this annotation

GitHub Actions / Run unit tests (macos-latest)

Delete `······`

Check failure on line 94 in server/auth/types/saml/routes.ts

View workflow job for this annotation

GitHub Actions / Run unit tests (windows-latest)

Delete `······`
if (tokenPayload.exp) {
expiryTime = parseInt(tokenPayload.exp, 10) * 1000;
}

Check failure on line 98 in server/auth/types/saml/routes.ts

View workflow job for this annotation

GitHub Actions / Run unit tests (ubuntu-latest)

Delete `··`

Check failure on line 98 in server/auth/types/saml/routes.ts

View workflow job for this annotation

GitHub Actions / Run unit tests (macos-latest)

Delete `··`

Check failure on line 98 in server/auth/types/saml/routes.ts

View workflow job for this annotation

GitHub Actions / Run unit tests (windows-latest)

Delete `··`
const cookie: SecuritySessionCookie = {
username: user.username,
credentials: {
authHeaderValueExtra: true,
},
authType: AuthType.SAML,
expiryTime,
};

Check failure on line 107 in server/auth/types/saml/routes.ts

View workflow job for this annotation

GitHub Actions / Run unit tests (ubuntu-latest)

Delete `··`

Check failure on line 107 in server/auth/types/saml/routes.ts

View workflow job for this annotation

GitHub Actions / Run unit tests (macos-latest)

Delete `··`

Check failure on line 107 in server/auth/types/saml/routes.ts

View workflow job for this annotation

GitHub Actions / Run unit tests (windows-latest)

Delete `··`
setExtraAuthStorage(
request,
credentials.authorization,
this.getExtraAuthStorageOptions(context.security_plugin.logger)
);

this.sessionStorageFactory.asScoped(request).set(cookie);

if (redirectHash) {
return response.redirected({
headers: {
location: `${this.coreSetup.http.basePath.serverBasePath}/auth/saml/redirectUrlFragment?nextUrl=${escape(nextUrl)}`,
},
});
} else {
return response.redirected({
headers: {
location: nextUrl,
},
});
}
} catch (error) {
context.security_plugin.logger.error(`SAML SP initiated authentication workflow failed: ${error}`);
return response.internalError();
}
}

private async handleIdpInitiatedAcs(context: any, request: any, response: any, acsEndpoint: string) {
try {
const credentials = await this.securityClient.authToken(
undefined,
request.body.SAMLResponse,
acsEndpoint
);
const user = await this.securityClient.authenticateWithHeader(
request,
'authorization',
credentials.authorization
);

let expiryTime = Date.now() + this.config.session.ttl;
const [headerEncoded, payloadEncoded, signature] = credentials.authorization.split('.');
if (!payloadEncoded) {
context.security_plugin.logger.error('JWT token payload not found');
}
const tokenPayload = JSON.parse(Buffer.from(payloadEncoded, 'base64').toString());
if (tokenPayload.exp) {
expiryTime = parseInt(tokenPayload.exp, 10) * 1000;
}

const cookie: SecuritySessionCookie = {
username: user.username,
credentials: {
authHeaderValueExtra: true,
},
authType: AuthType.SAML,
expiryTime,
};

setExtraAuthStorage(
request,
credentials.authorization,
this.getExtraAuthStorageOptions(context.security_plugin.logger)
);

this.sessionStorageFactory.asScoped(request).set(cookie);

return response.redirected({
headers: {
location: `${this.coreSetup.http.basePath.serverBasePath}/app/opensearch-dashboards`,
},
});
} catch (error) {
context.security_plugin.logger.error(
`SAML IDP initiated authentication workflow failed: ${error}`
);
}

return response.internalError();
}

public setupRoutes() {
this.router.get(
{
Expand Down Expand Up @@ -108,90 +247,22 @@ export class SamlAuthRoutes {
},
},
async (context, request, response) => {
let requestId: string = '';
let nextUrl: string = '/';
let redirectHash: boolean = false;
try {
const cookie = await this.sessionStorageFactory.asScoped(request).get();
if (cookie) {
requestId = cookie.saml?.requestId || '';
nextUrl =
cookie.saml?.nextUrl ||
`${this.coreSetup.http.basePath.serverBasePath}/app/opensearch-dashboards`;
redirectHash = cookie.saml?.redirectHash || false;
}
if (!requestId) {
return response.badRequest({
body: 'Invalid requestId',
});
}
} catch (error) {
context.security_plugin.logger.error(`Failed to parse cookie: ${error}`);
return response.badRequest();
}

try {
const credentials = await this.securityClient.authToken(
requestId,
request.body.SAMLResponse,
undefined
);
const user = await this.securityClient.authenticateWithHeader(
request,
'authorization',
credentials.authorization
);

let expiryTime = Date.now() + this.config.session.ttl;
const [headerEncoded, payloadEncoded, signature] = credentials.authorization.split('.');
if (!payloadEncoded) {
context.security_plugin.logger.error('JWT token payload not found');
}
const tokenPayload = JSON.parse(Buffer.from(payloadEncoded, 'base64').toString());

if (tokenPayload.exp) {
expiryTime = parseInt(tokenPayload.exp, 10) * 1000;
}

const cookie: SecuritySessionCookie = {
username: user.username,
credentials: {
authHeaderValueExtra: true,
},
authType: AuthType.SAML, // TODO: create constant
expiryTime,
};

setExtraAuthStorage(
request,
credentials.authorization,
this.getExtraAuthStorageOptions(context.security_plugin.logger)
);

this.sessionStorageFactory.asScoped(request).set(cookie);

if (redirectHash) {
return response.redirected({
headers: {
location: `${
this.coreSetup.http.basePath.serverBasePath
}/auth/saml/redirectUrlFragment?nextUrl=${escape(nextUrl)}`,
},
});
} else {
return response.redirected({
headers: {
location: nextUrl,
},
});
}
} catch (error) {
context.security_plugin.logger.error(
`SAML SP initiated authentication workflow failed: ${error}`
);
}
return this.handleSamlAcs(context, request, response)
}
);

return response.internalError();
this.router.post(
{
path: `/_plugin/_security/saml/acs`,
validate: {
body: schema.any(),
},
options: {
authRequired: false,
},
},
async (context, request, response) => {
return this.handleSamlAcs(context, request, response)
}
);

Expand All @@ -207,55 +278,23 @@ export class SamlAuthRoutes {
},
async (context, request, response) => {
const acsEndpoint = `${this.coreSetup.http.basePath.serverBasePath}/_opendistro/_security/saml/acs/idpinitiated`;
try {
const credentials = await this.securityClient.authToken(
undefined,
request.body.SAMLResponse,
acsEndpoint
);
const user = await this.securityClient.authenticateWithHeader(
request,
'authorization',
credentials.authorization
);

let expiryTime = Date.now() + this.config.session.ttl;
const [headerEncoded, payloadEncoded, signature] = credentials.authorization.split('.');
if (!payloadEncoded) {
context.security_plugin.logger.error('JWT token payload not found');
}
const tokenPayload = JSON.parse(Buffer.from(payloadEncoded, 'base64').toString());
if (tokenPayload.exp) {
expiryTime = parseInt(tokenPayload.exp, 10) * 1000;
}

const cookie: SecuritySessionCookie = {
username: user.username,
credentials: {
authHeaderValueExtra: true,
},
authType: AuthType.SAML, // TODO: create constant
expiryTime,
};

setExtraAuthStorage(
request,
credentials.authorization,
this.getExtraAuthStorageOptions(context.security_plugin.logger)
);
return await this.handleIdpInitiatedAcs(context, request, response, acsEndpoint)
}
);

this.sessionStorageFactory.asScoped(request).set(cookie);
return response.redirected({
headers: {
location: `${this.coreSetup.http.basePath.serverBasePath}/app/opensearch-dashboards`,
},
});
} catch (error) {
context.security_plugin.logger.error(
`SAML IDP initiated authentication workflow failed: ${error}`
);
}
return response.internalError();
this.router.post(
{
path: `/_plugin/_security/saml/acs/idpinitiated`,
validate: {
body: schema.any(),
},
options: {
authRequired: false,
},
},
async (context, request, response) => {
const acsEndpoint = `${this.coreSetup.http.basePath.serverBasePath}/_opendistro/_security/saml/acs/idpinitiated`;
return await this.handleIdpInitiatedAcs(context, request, response, acsEndpoint)
}
);

Expand Down

0 comments on commit 99afb6e

Please sign in to comment.