Skip to content

Commit

Permalink
Add steps to manage login
Browse files Browse the repository at this point in the history
  • Loading branch information
Mikescops committed May 17, 2024
1 parent 895b605 commit e17a956
Show file tree
Hide file tree
Showing 4 changed files with 113 additions and 6 deletions.
5 changes: 5 additions & 0 deletions src/modules/auth/confidential-sso/errors.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export class SAMLResponseNotFound extends Error {
constructor() {
super('SAML Response not found');
}
}
62 changes: 62 additions & 0 deletions src/modules/auth/confidential-sso/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import { chromium } from 'playwright-core';
import { ConfirmLogin2Request, RequestLogin2Request } from './types';
import { SAMLResponseNotFound } from './errors';
import { apiConnect } from '../../tunnel-api-connect';
import { performSSOVerification } from '../../../endpoints/performSSOVerification';

interface ConfidentialSSOParams {
requestedLogin: string;
}

export const doConfidentialSSOVerification = async ({ requestedLogin }: ConfidentialSSOParams) => {
const api = await apiConnect({ isProduction: true, enclavePcrList: [] });
const requestLoginResponse = await api.sendSecureContent<RequestLogin2Request>({
...api,
path: 'authentication/RequestLogin2',
payload: { login: requestedLogin },
});

const { idpAuthorizeUrl, spCallbackUrl, teamUuid, domainName } = requestLoginResponse;

const browser = await chromium.launch({ headless: false, channel: 'chrome' });
const context = await browser.newContext();
const page = await context.newPage();

await page.goto(idpAuthorizeUrl);

let samlResponseData;
const samlResponsePromise = new Promise((resolve) => {
page.on('request', (req) => {
const reqURL = req.url();
if (reqURL === spCallbackUrl) {
samlResponseData = req.postData();
if (browser) {
void browser.close();
}
console.log(`Intercepted SAML response, browser closed`);
resolve(undefined);
}
});
});

await samlResponsePromise;

const samlResponse = new URLSearchParams(samlResponseData).get('SAMLResponse');

if (!samlResponse) {
throw new SAMLResponseNotFound();
}

const confirmLoginResponse = await api.sendSecureContent<ConfirmLogin2Request>({
...api,
path: 'authentication/ConfirmLogin2',
payload: { teamUuid, domainName, samlResponse },
});

const ssoVerificationResult = await performSSOVerification({
login: requestedLogin,
ssoToken: confirmLoginResponse.ssoToken,
});

return { ...ssoVerificationResult, ssoSpKey: confirmLoginResponse.userServiceProviderKey };
};
37 changes: 37 additions & 0 deletions src/modules/auth/confidential-sso/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
export interface RequestLogin2Data {
login: string;
}

export interface RequestLogin2Output {
domainName: string;
idpAuthorizeUrl: string;
spCallbackUrl: string;
teamUuid: string;
validatedDomains: string[];
}

export interface RequestLogin2Request {
path: 'authentication/RequestLogin2';
input: RequestLogin2Data;
output: RequestLogin2Output;
}

export interface ConfirmLogin2Data {
teamUuid: string;
domainName: string;
samlResponse: string;
}

export interface ConfirmLogin2Output {
ssoToken: string;
userServiceProviderKey: string;
exists: boolean;
currentAuthenticationMethods: string[];
expectedAuthenticationMethods: string[];
}

export interface ConfirmLogin2Request {
path: 'authentication/ConfirmLogin2';
input: ConfirmLogin2Data;
output: ConfirmLogin2Output;
}
15 changes: 9 additions & 6 deletions src/modules/auth/registerDevice.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import winston from 'winston';
import { doSSOVerification } from './sso';
import { doConfidentialSSOVerification } from './confidential-sso';
import {
completeDeviceRegistration,
performDashlaneAuthenticatorVerification,
Expand Down Expand Up @@ -63,13 +64,15 @@ export const registerDevice = async (params: RegisterDevice) => {
}));
} else if (selectedVerificationMethod.type === 'sso') {
if (selectedVerificationMethod.ssoInfo.isNitroProvider) {
throw new Error('Confidential SSO is currently not supported');
({ authTicket, ssoSpKey } = await doConfidentialSSOVerification({
requestedLogin: login,
}));
} else {
({ authTicket, ssoSpKey } = await doSSOVerification({
requestedLogin: login,
serviceProviderURL: selectedVerificationMethod.ssoInfo.serviceProviderUrl,
}));
}

({ authTicket, ssoSpKey } = await doSSOVerification({
requestedLogin: login,
serviceProviderURL: selectedVerificationMethod.ssoInfo.serviceProviderUrl,
}));
} else {
throw new Error('Auth verification method not supported: ' + selectedVerificationMethod.type);
}
Expand Down

0 comments on commit e17a956

Please sign in to comment.